Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 26 additions & 2 deletions .github/workflows/copilot-pr-merged-report.lock.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 26 additions & 2 deletions .github/workflows/daily-performance-summary.lock.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 26 additions & 2 deletions .github/workflows/dev.lock.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 26 additions & 2 deletions .github/workflows/test-python-safe-input.lock.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions pkg/workflow/compiler_yaml.go
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,11 @@ func (c *Compiler) generateMainJobSteps(yaml *strings.Builder, data *WorkflowDat
// upload MCP logs (if any MCP tools were used)
c.generateUploadMCPLogs(yaml)

// upload SafeInputs logs (if safe-inputs is enabled)
if IsSafeInputsEnabled(data.SafeInputs, data) {
c.generateUploadSafeInputsLogs(yaml)
}

// parse agent logs for GITHUB_STEP_SUMMARY
c.generateLogParsing(yaml, engine)

Expand Down Expand Up @@ -653,6 +658,19 @@ func (c *Compiler) generateUploadMCPLogs(yaml *strings.Builder) {
yaml.WriteString(" if-no-files-found: ignore\n")
}

func (c *Compiler) generateUploadSafeInputsLogs(yaml *strings.Builder) {
// Record artifact upload for validation
c.stepOrderTracker.RecordArtifactUpload("Upload SafeInputs logs", []string{"/tmp/gh-aw/safe-inputs/logs/"})

yaml.WriteString(" - name: Upload SafeInputs logs\n")
yaml.WriteString(" if: always()\n")
yaml.WriteString(fmt.Sprintf(" uses: %s\n", GetActionPin("actions/upload-artifact")))
yaml.WriteString(" with:\n")
yaml.WriteString(" name: safeinputs\n")
yaml.WriteString(" path: /tmp/gh-aw/safe-inputs/logs/\n")
yaml.WriteString(" if-no-files-found: ignore\n")
}

func splitContentIntoChunks(content string) []string {
const maxChunkSize = 20900 // 21000 - 100 character buffer
const indentSpaces = " " // 10 spaces added to each line
Expand Down
14 changes: 14 additions & 0 deletions pkg/workflow/js/safe_inputs_mcp_server_http.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,20 @@ async function startHttpServer(configPath, options = {}) {
return;
}

// Handle GET /health endpoint for health checks
if (req.method === "GET" && req.url === "/health") {
res.writeHead(200, { "Content-Type": "application/json" });
res.end(
JSON.stringify({
status: "ok",
server: config.serverName || "safeinputs",
version: config.version || "1.0.0",
tools: config.tools.length,
})
);
return;
}

// Only handle POST requests for MCP protocol
if (req.method !== "POST") {
res.writeHead(405, { "Content-Type": "application/json" });
Expand Down
34 changes: 34 additions & 0 deletions pkg/workflow/js/safe_inputs_mcp_server_http.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,40 @@ describe("safe_inputs_mcp_server_http.cjs integration", () => {
sessionId = response.headers["mcp-session-id"];
});

it("should respond to GET /health endpoint", async () => {
return new Promise((resolve, reject) => {
const req = http.request(
{
hostname: "localhost",
port: serverPort,
path: "/health",
method: "GET",
},
res => {
let responseData = "";
res.on("data", chunk => {
responseData += chunk;
});
res.on("end", () => {
try {
expect(res.statusCode).toBe(200);
const data = JSON.parse(responseData);
expect(data.status).toBe("ok");
expect(data.server).toBe("http-integration-test-server");
expect(data.version).toBe("1.0.0");
expect(data.tools).toBe(1);
resolve();
} catch (e) {
reject(e);
}
});
}
);
req.on("error", reject);
req.end();
});
});

it("should list tools via HTTP", async () => {
const headers = sessionId ? { "Mcp-Session-Id": sessionId } : {};

Expand Down
10 changes: 8 additions & 2 deletions pkg/workflow/sh/start_safe_inputs_server.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,15 @@ echo " Working directory: $(pwd)"
# Ensure logs directory exists
mkdir -p /tmp/gh-aw/safe-inputs/logs

# Create initial server.log file for artifact upload
echo "Safe Inputs MCP Server Log" > /tmp/gh-aw/safe-inputs/logs/server.log
echo "Start time: $(date)" >> /tmp/gh-aw/safe-inputs/logs/server.log
echo "===========================================" >> /tmp/gh-aw/safe-inputs/logs/server.log
echo "" >> /tmp/gh-aw/safe-inputs/logs/server.log

# Start the HTTP server in the background
echo "Starting safe-inputs MCP HTTP server..."
node mcp-server.cjs > /tmp/gh-aw/safe-inputs/logs/server.log 2>&1 &
node mcp-server.cjs >> /tmp/gh-aw/safe-inputs/logs/server.log 2>&1 &
SERVER_PID=$!
echo "Started safe-inputs MCP server with PID $SERVER_PID"

Expand All @@ -41,7 +47,7 @@ for i in {1..10}; do
fi

# Check if server is responding
if curl -s -f -H "Authorization: Bearer $GH_AW_SAFE_INPUTS_API_KEY" http://localhost:$GH_AW_SAFE_INPUTS_PORT/ > /dev/null 2>&1; then
if curl -s -f http://localhost:$GH_AW_SAFE_INPUTS_PORT/health > /dev/null 2>&1; then
echo "Safe Inputs MCP server is ready (attempt $i/10)"
break
fi
Expand Down
Loading