diff --git a/.github/workflows/contribution-check.lock.yml b/.github/workflows/contribution-check.lock.yml index 41c58b2a7ac..2a4d6d80e3d 100644 --- a/.github/workflows/contribution-check.lock.yml +++ b/.github/workflows/contribution-check.lock.yml @@ -23,10 +23,6 @@ # For more information: https://github.github.com/gh-aw/introduction/overview/ # # -# Resolved workflow manifest: -# Includes: -# - shared/noop-reminder.md -# # Frontmatter env variables: # - TARGET_REPOSITORY: (main workflow) # diff --git a/.github/workflows/contribution-check.md b/.github/workflows/contribution-check.md index 04936faa915..4cd4cf2e5c4 100644 --- a/.github/workflows/contribution-check.md +++ b/.github/workflows/contribution-check.md @@ -252,4 +252,8 @@ If any subagent call failed (❓), also apply `outdated`. - Close the previous report issue when creating a new one (`close-older-issues: true`). - Be constructive in assessments — these reports help maintainers prioritize, not gatekeep. -{{#import shared/noop-reminder.md}} +**Important**: If no action is needed after completing your analysis, you **MUST** call the `noop` safe-output tool with a brief explanation. Failing to call any safe-output tool is the most common cause of safe-output workflow failures. + +```json +{"noop": {"message": "No action needed: [brief explanation of what was analyzed and why]"}} +``` diff --git a/.github/workflows/daily-fact.lock.yml b/.github/workflows/daily-fact.lock.yml index 7781c07ccf9..a77d9d22721 100644 --- a/.github/workflows/daily-fact.lock.yml +++ b/.github/workflows/daily-fact.lock.yml @@ -739,8 +739,10 @@ jobs: export GH_AW_ENGINE="codex" export GH_AW_MCP_CLI_SERVERS='["mempalace"]' echo 'GH_AW_MCP_CLI_SERVERS=["mempalace"]' >> "$GITHUB_ENV" + MCP_GATEWAY_UID=$(id -u 2>/dev/null || echo '0') + MCP_GATEWAY_GID=$(id -g 2>/dev/null || echo '0') DOCKER_SOCK_GID=$(stat -c '%g' /var/run/docker.sock 2>/dev/null || echo '0') - export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.2.24' + export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.2.22' cat > "${RUNNER_TEMP}/gh-aw/mcp-config/config.toml" << GH_AW_MCP_CONFIG_1b4b127ec8d7bd00_EOF [history] diff --git a/.github/workflows/smoke-claude.lock.yml b/.github/workflows/smoke-claude.lock.yml index e5bb3c9d0c5..b435aab861f 100644 --- a/.github/workflows/smoke-claude.lock.yml +++ b/.github/workflows/smoke-claude.lock.yml @@ -2001,8 +2001,10 @@ jobs: export DEBUG="*" export GH_AW_ENGINE="claude" + MCP_GATEWAY_UID=$(id -u 2>/dev/null || echo '0') + MCP_GATEWAY_GID=$(id -g 2>/dev/null || echo '0') DOCKER_SOCK_GID=$(stat -c '%g' /var/run/docker.sock 2>/dev/null || echo '0') - export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_MCP_SCRIPTS_PORT -e GH_AW_MCP_SCRIPTS_API_KEY -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e GH_AW_GH_TOKEN -e GH_DEBUG -e GH_TOKEN -e TAVILY_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.2.24' + export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_MCP_SCRIPTS_PORT -e GH_AW_MCP_SCRIPTS_API_KEY -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e GH_AW_GH_TOKEN -e GH_DEBUG -e GH_TOKEN -e TAVILY_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.2.22' GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) cat << GH_AW_MCP_CONFIG_7f02447c1d397bd6_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" diff --git a/.github/workflows/smoke-crush.lock.yml b/.github/workflows/smoke-crush.lock.yml index d4f5b6672dd..3c9df86e45b 100644 --- a/.github/workflows/smoke-crush.lock.yml +++ b/.github/workflows/smoke-crush.lock.yml @@ -28,8 +28,6 @@ # Imports: # - shared/gh.md # - shared/reporting.md -# Includes: -# - shared/noop-reminder.md # # Secrets used: # - COPILOT_GITHUB_TOKEN diff --git a/.github/workflows/smoke-crush.md b/.github/workflows/smoke-crush.md index 30ef05b2937..2ea78b61b1d 100644 --- a/.github/workflows/smoke-crush.md +++ b/.github/workflows/smoke-crush.md @@ -72,4 +72,8 @@ Add a **very brief** comment (max 5-10 lines) to the current pull request with: If all tests pass, use the `add_labels` safe-output tool to add the label `smoke-crush` to the pull request. -{{#import shared/noop-reminder.md}} +**Important**: If no action is needed after completing your analysis, you **MUST** call the `noop` safe-output tool with a brief explanation. Failing to call any safe-output tool is the most common cause of safe-output workflow failures. + +```json +{"noop": {"message": "No action needed: [brief explanation of what was analyzed and why]"}} +``` diff --git a/.github/workflows/workflow-skill-extractor.lock.yml b/.github/workflows/workflow-skill-extractor.lock.yml index a6ae03759ac..2599102f251 100644 --- a/.github/workflows/workflow-skill-extractor.lock.yml +++ b/.github/workflows/workflow-skill-extractor.lock.yml @@ -27,8 +27,6 @@ # Resolved workflow manifest: # Imports: # - shared/reporting.md -# Includes: -# - shared/noop-reminder.md # # Secrets used: # - COPILOT_GITHUB_TOKEN diff --git a/.github/workflows/workflow-skill-extractor.md b/.github/workflows/workflow-skill-extractor.md index 7955f785312..909741ab385 100644 --- a/.github/workflows/workflow-skill-extractor.md +++ b/.github/workflows/workflow-skill-extractor.md @@ -157,4 +157,8 @@ Use this priority rubric: - Keep recommendations concrete and actionable. - If no action is needed, call `noop` with a brief explanation. -{{#import shared/noop-reminder.md}} +**Important**: If no action is needed after completing your analysis, you **MUST** call the `noop` safe-output tool with a brief explanation. Failing to call any safe-output tool is the most common cause of safe-output workflow failures. + +```json +{"noop": {"message": "No action needed: [brief explanation of what was analyzed and why]"}} +``` diff --git a/pkg/workflow/mcp_setup_generator.go b/pkg/workflow/mcp_setup_generator.go index a04006d1082..bff796a51ec 100644 --- a/pkg/workflow/mcp_setup_generator.go +++ b/pkg/workflow/mcp_setup_generator.go @@ -696,6 +696,9 @@ func (c *Compiler) generateMCPSetup(yaml *strings.Builder, tools map[string]any, var containerCmd strings.Builder containerCmd.WriteString("docker run -i --rm --network host") + // Use runner UID/GID so gateway-created /tmp logs remain readable by downstream + // redaction/upload steps; keep a supplementary docker.sock group for daemon access. + containerCmd.WriteString(" --user ${MCP_GATEWAY_UID}:${MCP_GATEWAY_GID}") containerCmd.WriteString(" --group-add ${DOCKER_SOCK_GID}") containerCmd.WriteString(" -v /var/run/docker.sock:/var/run/docker.sock") // Enable docker-in-docker for MCP gateway // Pass required gateway environment variables @@ -902,11 +905,15 @@ func (c *Compiler) generateMCPSetup(yaml *strings.Builder, tools map[string]any, } } - // Compute the Docker socket group ID so the MCPG container can access /var/run/docker.sock + // Compute the runner user/group IDs and Docker socket group ID before constructing + // the docker command so these values are expanded to literals in the exported command. + yaml.WriteString(" MCP_GATEWAY_UID=$(id -u 2>/dev/null || echo '0')\n") + yaml.WriteString(" MCP_GATEWAY_GID=$(id -g 2>/dev/null || echo '0')\n") yaml.WriteString(" DOCKER_SOCK_GID=$(stat -c '%g' /var/run/docker.sock 2>/dev/null || echo '0')\n") // Build the export command with proper quoting that allows variable expansion - // We need to break out of quotes for shell variables like ${GITHUB_WORKSPACE} and ${DOCKER_SOCK_GID} + // We need to break out of quotes for shell variables like + // ${GITHUB_WORKSPACE}, ${MCP_GATEWAY_UID}, ${MCP_GATEWAY_GID}, and ${DOCKER_SOCK_GID} cmdWithExpandableVars := buildDockerCommandWithExpandableVars(containerCmd.String()) yaml.WriteString(" export MCP_GATEWAY_DOCKER_COMMAND=" + cmdWithExpandableVars + "\n") yaml.WriteString(" \n") diff --git a/pkg/workflow/mcp_setup_generator_test.go b/pkg/workflow/mcp_setup_generator_test.go index 108253533c9..9a89ad711fd 100644 --- a/pkg/workflow/mcp_setup_generator_test.go +++ b/pkg/workflow/mcp_setup_generator_test.go @@ -477,9 +477,9 @@ Test that TAVILY_API_KEY is passed to gateway container. "Docker command should include -e TAVILY_API_KEY before the container image") } -// TestMCPGatewayDockerCommandIncludesDockerSocketGroup verifies the gateway docker command -// adds the docker socket group as a supplementary group for non-root execution. -func TestMCPGatewayDockerCommandIncludesDockerSocketGroup(t *testing.T) { +// TestMCPGatewayDockerCommandUsesRunnerIdentityAndSocketGroup verifies the gateway docker command +// computes and uses runner UID/GID and docker socket group values in the generated command. +func TestMCPGatewayDockerCommandUsesRunnerIdentityAndSocketGroup(t *testing.T) { frontmatter := `--- on: workflow_dispatch engine: copilot @@ -508,16 +508,31 @@ tools: require.NoError(t, err, "Failed to read output file") yamlStr := string(content) + userSnippet := `--user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"'` groupAddSnippet := `--group-add '"${DOCKER_SOCK_GID}"'` mountSnippet := `-v /var/run/docker.sock:/var/run/docker.sock` - gidComputeSnippet := `DOCKER_SOCK_GID=$(stat -c '%g' /var/run/docker.sock 2>/dev/null || echo '0')` - require.Contains(t, yamlStr, gidComputeSnippet, + uidComputeSnippet := `MCP_GATEWAY_UID=$(id -u 2>/dev/null || echo '0')` + runnerGIDComputeSnippet := `MCP_GATEWAY_GID=$(id -g 2>/dev/null || echo '0')` + socketGIDComputeSnippet := `DOCKER_SOCK_GID=$(stat -c '%g' /var/run/docker.sock 2>/dev/null || echo '0')` + require.Contains(t, yamlStr, uidComputeSnippet, + "Shell should compute MCP_GATEWAY_UID before docker command") + require.Contains(t, yamlStr, runnerGIDComputeSnippet, + "Shell should compute MCP_GATEWAY_GID before docker command") + require.Contains(t, yamlStr, userSnippet, + "Docker command should include runner UID/GID user mapping") + require.Contains(t, yamlStr, socketGIDComputeSnippet, "Shell should compute DOCKER_SOCK_GID before docker command") require.Contains(t, yamlStr, groupAddSnippet, "Docker command should include docker socket supplementary group mapping") require.Contains(t, yamlStr, mountSnippet, "Docker command should mount the Docker socket") - require.Less(t, strings.Index(yamlStr, gidComputeSnippet), strings.Index(yamlStr, groupAddSnippet), + require.Less(t, strings.Index(yamlStr, uidComputeSnippet), strings.Index(yamlStr, userSnippet), + "MCP_GATEWAY_UID should be computed before it is used in the docker command") + require.Less(t, strings.Index(yamlStr, runnerGIDComputeSnippet), strings.Index(yamlStr, userSnippet), + "MCP_GATEWAY_GID should be computed before it is used in the docker command") + require.Less(t, strings.Index(yamlStr, userSnippet), strings.Index(yamlStr, groupAddSnippet), + "Docker command should include user mapping before supplementary group mapping") + require.Less(t, strings.Index(yamlStr, socketGIDComputeSnippet), strings.Index(yamlStr, groupAddSnippet), "DOCKER_SOCK_GID should be computed before it is used in the docker command") require.Less(t, strings.Index(yamlStr, groupAddSnippet), strings.Index(yamlStr, mountSnippet), "Docker command should add supplementary group before mounting the Docker socket")