diff --git a/.github/workflows/copilot-pr-merged-report.lock.yml b/.github/workflows/copilot-pr-merged-report.lock.yml index 4ec53522a7..2582793417 100644 --- a/.github/workflows/copilot-pr-merged-report.lock.yml +++ b/.github/workflows/copilot-pr-merged-report.lock.yml @@ -2902,6 +2902,18 @@ jobs: res.end(); return; } + 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; + } if (req.method !== "POST") { res.writeHead(405, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: "Method not allowed" })); @@ -3140,9 +3152,14 @@ jobs: 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" # Wait for server to be ready (max 10 seconds) @@ -3156,7 +3173,7 @@ jobs: exit 1 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 @@ -4878,6 +4895,13 @@ jobs: name: mcp-logs path: /tmp/gh-aw/mcp-logs/ if-no-files-found: ignore + - name: Upload SafeInputs logs + if: always() + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 + with: + name: safeinputs + path: /tmp/gh-aw/safe-inputs/logs/ + if-no-files-found: ignore - name: Parse agent logs for step summary if: always() uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 diff --git a/.github/workflows/daily-performance-summary.lock.yml b/.github/workflows/daily-performance-summary.lock.yml index 4e2e1bcf2e..2cb5185a57 100644 --- a/.github/workflows/daily-performance-summary.lock.yml +++ b/.github/workflows/daily-performance-summary.lock.yml @@ -3485,6 +3485,18 @@ jobs: res.end(); return; } + 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; + } if (req.method !== "POST") { res.writeHead(405, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: "Method not allowed" })); @@ -4014,9 +4026,14 @@ jobs: 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" # Wait for server to be ready (max 10 seconds) @@ -4030,7 +4047,7 @@ jobs: exit 1 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 @@ -6266,6 +6283,13 @@ jobs: name: mcp-logs path: /tmp/gh-aw/mcp-logs/ if-no-files-found: ignore + - name: Upload SafeInputs logs + if: always() + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 + with: + name: safeinputs + path: /tmp/gh-aw/safe-inputs/logs/ + if-no-files-found: ignore - name: Parse agent logs for step summary if: always() uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 diff --git a/.github/workflows/dev.lock.yml b/.github/workflows/dev.lock.yml index 39d198943c..8a7a03e3fe 100644 --- a/.github/workflows/dev.lock.yml +++ b/.github/workflows/dev.lock.yml @@ -1491,6 +1491,18 @@ jobs: res.end(); return; } + 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; + } if (req.method !== "POST") { res.writeHead(405, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: "Method not allowed" })); @@ -1729,9 +1741,14 @@ jobs: 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" # Wait for server to be ready (max 10 seconds) @@ -1745,7 +1762,7 @@ jobs: exit 1 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 @@ -2236,6 +2253,13 @@ jobs: name: mcp-logs path: /tmp/gh-aw/mcp-logs/ if-no-files-found: ignore + - name: Upload SafeInputs logs + if: always() + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 + with: + name: safeinputs + path: /tmp/gh-aw/safe-inputs/logs/ + if-no-files-found: ignore - name: Parse agent logs for step summary if: always() uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 diff --git a/.github/workflows/test-python-safe-input.lock.yml b/.github/workflows/test-python-safe-input.lock.yml index 76bd23b7d4..79d87417be 100644 --- a/.github/workflows/test-python-safe-input.lock.yml +++ b/.github/workflows/test-python-safe-input.lock.yml @@ -2674,6 +2674,18 @@ jobs: res.end(); return; } + 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; + } if (req.method !== "POST") { res.writeHead(405, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: "Method not allowed" })); @@ -3005,9 +3017,14 @@ jobs: 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" # Wait for server to be ready (max 10 seconds) @@ -3021,7 +3038,7 @@ jobs: exit 1 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 @@ -4508,6 +4525,13 @@ jobs: name: mcp-logs path: /tmp/gh-aw/mcp-logs/ if-no-files-found: ignore + - name: Upload SafeInputs logs + if: always() + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 + with: + name: safeinputs + path: /tmp/gh-aw/safe-inputs/logs/ + if-no-files-found: ignore - name: Parse agent logs for step summary if: always() uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 diff --git a/pkg/workflow/compiler_yaml.go b/pkg/workflow/compiler_yaml.go index 2616d0eaf8..91c32cad9f 100644 --- a/pkg/workflow/compiler_yaml.go +++ b/pkg/workflow/compiler_yaml.go @@ -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) @@ -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 diff --git a/pkg/workflow/js/safe_inputs_mcp_server_http.cjs b/pkg/workflow/js/safe_inputs_mcp_server_http.cjs index 21e36c520a..6e88ee7eaa 100644 --- a/pkg/workflow/js/safe_inputs_mcp_server_http.cjs +++ b/pkg/workflow/js/safe_inputs_mcp_server_http.cjs @@ -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" }); diff --git a/pkg/workflow/js/safe_inputs_mcp_server_http.test.cjs b/pkg/workflow/js/safe_inputs_mcp_server_http.test.cjs index 0d4f2c9429..9501e68a98 100644 --- a/pkg/workflow/js/safe_inputs_mcp_server_http.test.cjs +++ b/pkg/workflow/js/safe_inputs_mcp_server_http.test.cjs @@ -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 } : {}; diff --git a/pkg/workflow/sh/start_safe_inputs_server.sh b/pkg/workflow/sh/start_safe_inputs_server.sh index b5e46f3fa9..147bda2426 100644 --- a/pkg/workflow/sh/start_safe_inputs_server.sh +++ b/pkg/workflow/sh/start_safe_inputs_server.sh @@ -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" @@ -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