diff --git a/.github/workflows/smoke-claude.lock.yml b/.github/workflows/smoke-claude.lock.yml index 9016509e6fd..9c0a11d0426 100644 --- a/.github/workflows/smoke-claude.lock.yml +++ b/.github/workflows/smoke-claude.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"fd3c8da08b0f0fcb6f954160a2922b21a97c9e8644aaca9f64c66b6543986705","agent_id":"claude"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"7ff3d043b54c7592911fa0d572f5d82cd766fcfe4216dd67c7069fbc7159cedc","agent_id":"claude"} # gh-aw-manifest: {"version":1,"secrets":["ANTHROPIC_API_KEY","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_GRAFANA_AUTHORIZATION","GH_AW_OTEL_GRAFANA_ENDPOINT","GH_AW_OTEL_SENTRY_AUTHORIZATION","GH_AW_OTEL_SENTRY_ENDPOINT","GITHUB_TOKEN","TAVILY_API_KEY"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-go","sha":"4a3601121dd01d1626a1e23e37211e3254c1c06c","version":"v6.4.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"docker/build-push-action","sha":"bcafcacb16a39f128d818304e6c9c0c18556b85f","version":"v7.1.0"},{"repo":"docker/setup-buildx-action","sha":"4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd","version":"v4.0.0"},{"repo":"github/codeql-action/upload-sarif","sha":"68bde559dea0fdcac2102bfdf6230c5f70eb485e","version":"v4.35.4"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.46"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.46"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.46"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.46"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.9","digest":"sha256:64828b42a4482f58fab16509d7f8f495a6d97c972a98a68aff20543531ac0388","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.9@sha256:64828b42a4482f58fab16509d7f8f495a6d97c972a98a68aff20543531ac0388"},{"image":"ghcr.io/github/github-mcp-server:v1.0.4"},{"image":"ghcr.io/github/serena-mcp-server:latest","digest":"sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5","pinned_image":"ghcr.io/github/serena-mcp-server:latest@sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -273,9 +273,9 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_4a229bb66e47bd57_EOF' + cat << 'GH_AW_PROMPT_95bb68917c1c404d_EOF' - GH_AW_PROMPT_4a229bb66e47bd57_EOF + GH_AW_PROMPT_95bb68917c1c404d_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" @@ -283,16 +283,16 @@ jobs: cat "${RUNNER_TEMP}/gh-aw/prompts/agentic_workflows_guide.md" cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_4a229bb66e47bd57_EOF' + cat << 'GH_AW_PROMPT_95bb68917c1c404d_EOF' Tools: add_comment(max:2), create_issue, close_pull_request, update_pull_request, create_pull_request_review_comment(max:5), submit_pull_request_review, resolve_pull_request_review_thread(max:5), add_labels, add_reviewer(max:2), push_to_pull_request_branch, create_code_scanning_alert, missing_tool, missing_data, noop, post_slack_message - GH_AW_PROMPT_4a229bb66e47bd57_EOF + GH_AW_PROMPT_95bb68917c1c404d_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_push_to_pr_branch.md" - cat << 'GH_AW_PROMPT_4a229bb66e47bd57_EOF' + cat << 'GH_AW_PROMPT_95bb68917c1c404d_EOF' - GH_AW_PROMPT_4a229bb66e47bd57_EOF + GH_AW_PROMPT_95bb68917c1c404d_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_4a229bb66e47bd57_EOF' + cat << 'GH_AW_PROMPT_95bb68917c1c404d_EOF' The following GitHub context information is available for this workflow: {{#if github.actor}} @@ -324,9 +324,9 @@ jobs: - **Note**: If a branch you need is not in the list above and is not listed as an additional fetched ref, it has NOT been checked out. For private repositories you cannot fetch it without proper authentication. If the branch is required and not available, exit with an error and ask the user to add it to the `fetch:` option of the `checkout:` configuration (e.g., `fetch: ["refs/pulls/open/*"]` for all open PR refs, or `fetch: ["main", "feature/my-branch"]` for specific branches). - GH_AW_PROMPT_4a229bb66e47bd57_EOF + GH_AW_PROMPT_95bb68917c1c404d_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/cli_proxy_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_4a229bb66e47bd57_EOF' + cat << 'GH_AW_PROMPT_95bb68917c1c404d_EOF' ## Serena Code Analysis @@ -713,7 +713,7 @@ jobs: {{#runtime-import shared/noop-reminder.md}} - GH_AW_PROMPT_4a229bb66e47bd57_EOF + GH_AW_PROMPT_95bb68917c1c404d_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -863,35 +863,8 @@ jobs: - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: - persist-credentials: true + persist-credentials: false fetch-depth: 0 - - name: Clean git credentials after checkout - continue-on-error: true - run: | - if [ -x "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials_checkout.sh" ]; then - bash "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials_checkout.sh" - else - echo "WARNING: Checkout cleanup helper missing. Running inline fallback." - cleaned_configs=0 - while IFS= read -r git_config; do - git config --file "${git_config}" --remove-section credential 2>/dev/null || true - sed -i '/^\[credential /,/^\[/{ /^\[credential /d; /^\[/!d; }' "${git_config}" 2>/dev/null || true - git config --file "${git_config}" --unset-all http.extraheader 2>/dev/null || true - git config --file "${git_config}" --get-regexp '^http\..*\.extraheader$' 2>/dev/null | while read -r key _; do - git config --file "${git_config}" --unset-all "${key}" || true - done || true - git config --file "${git_config}" --get-regexp '^remote\..*\.url$' 2>/dev/null | while read -r key url; do - clean_url=$(echo "${url}" | sed -E 's|(https?://)([^@]+@)?(.*)|\1\3|') - if [ "${url}" != "${clean_url}" ]; then - git config --file "${git_config}" "${key}" "${clean_url}" - fi - done || true - cleaned_configs=$((cleaned_configs + 1)) - done < <(find "${GITHUB_WORKSPACE}" /tmp -maxdepth 15 -type f -name "config" \( -path "*/.git/config" -o -path "*/.git/modules/*/config" \) 2>/dev/null | sort -u) - if [ "${cleaned_configs}" -eq 0 ]; then - echo "No git config files found for checkout cleanup fallback" - fi - fi - name: Fetch additional refs env: GH_AW_FETCH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} @@ -1057,9 +1030,9 @@ jobs: mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_dd68eaeb4100df80_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_06febd1c3841de38_EOF' {"add_comment":{"hide_older_comments":true,"max":2},"add_labels":{"allowed":["smoke-claude"]},"add_reviewer":{"max":2,"target":"*"},"close_pull_request":{"max":1,"staged":true},"create_code_scanning_alert":{"driver":"Smoke Claude"},"create_issue":{"close_older_issues":true,"close_older_key":"smoke-claude","expires":2,"group":true,"labels":["automation","testing"],"max":1},"create_pull_request_review_comment":{"max":5,"side":"RIGHT","target":"*"},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"post_slack_message":{"description":"Post a message to a fictitious Slack channel (smoke test only — no real Slack integration)","inputs":{"channel":{"default":"#general","description":"Slack channel name to post to","required":false,"type":"string"},"message":{"description":"Message text to post","required":false,"type":"string"}}},"push_to_pull_request_branch":{"allowed_files":["smoke-test-files/smoke-claude-push-test.md"],"if_no_changes":"warn","labels":["smoke-claude"],"max_patch_size":1024,"protect_top_level_dot_folders":true,"protected_files":["package.json","bun.lockb","bunfig.toml","deno.json","deno.jsonc","deno.lock","global.json","NuGet.Config","Directory.Packages.props","mix.exs","mix.lock","go.mod","go.sum","stack.yaml","stack.yaml.lock","pom.xml","build.gradle","build.gradle.kts","settings.gradle","settings.gradle.kts","gradle.properties","package-lock.json","yarn.lock","pnpm-lock.yaml","npm-shrinkwrap.json","requirements.txt","Pipfile","Pipfile.lock","pyproject.toml","setup.py","setup.cfg","Gemfile","Gemfile.lock","uv.lock","CODEOWNERS","DESIGN.md","README.md","CONTRIBUTING.md","CHANGELOG.md","SECURITY.md","CODE_OF_CONDUCT.md","CLAUDE.md","AGENTS.md"],"staged":true,"target":"*"},"report_incomplete":{},"resolve_pull_request_review_thread":{"max":5},"submit_pull_request_review":{"footer":"always","max":1},"update_pull_request":{"allow_body":true,"allow_title":true,"max":1,"target":"*","update_branch":false}} - GH_AW_SAFE_OUTPUTS_CONFIG_dd68eaeb4100df80_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_06febd1c3841de38_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -1507,7 +1480,7 @@ jobs: - name: Write MCP Scripts Config run: | mkdir -p "${RUNNER_TEMP}/gh-aw/mcp-scripts/logs" - cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/tools.json" << 'GH_AW_MCP_SCRIPTS_TOOLS_3c2781cc6cad5375_EOF' + cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/tools.json" << 'GH_AW_MCP_SCRIPTS_TOOLS_ef234139c51284c9_EOF' { "serverName": "mcpscripts", "version": "1.0.0", @@ -1637,8 +1610,8 @@ jobs: } ] } - GH_AW_MCP_SCRIPTS_TOOLS_3c2781cc6cad5375_EOF - cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/mcp-server.cjs" << 'GH_AW_MCP_SCRIPTS_SERVER_e796b7c5b63e5bc7_EOF' + GH_AW_MCP_SCRIPTS_TOOLS_ef234139c51284c9_EOF + cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/mcp-server.cjs" << 'GH_AW_MCP_SCRIPTS_SERVER_f0b689cc7a7fa760_EOF' const path = require("path"); const { startHttpServer } = require("./mcp_scripts_mcp_server_http.cjs"); const configPath = path.join(__dirname, "tools.json"); @@ -1652,12 +1625,12 @@ jobs: console.error("Failed to start mcp-scripts HTTP server:", error); process.exit(1); }); - GH_AW_MCP_SCRIPTS_SERVER_e796b7c5b63e5bc7_EOF + GH_AW_MCP_SCRIPTS_SERVER_f0b689cc7a7fa760_EOF chmod +x "${RUNNER_TEMP}/gh-aw/mcp-scripts/mcp-server.cjs" - name: Write MCP Scripts Tool Files run: | - cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/github-discussion-query.sh" << 'GH_AW_MCP_SCRIPTS_SH_GITHUB-DISCUSSION-QUERY_b50de5e7f97072ad_EOF' + cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/github-discussion-query.sh" << 'GH_AW_MCP_SCRIPTS_SH_GITHUB-DISCUSSION-QUERY_4bb5a1d76051bfda_EOF' #!/bin/bash # Auto-generated mcp-script tool: github-discussion-query # Query GitHub discussions with jq filtering support. Without --jq, returns schema and data size info. Use --jq '.' to get all data, or specific jq expressions to filter. @@ -1793,9 +1766,9 @@ jobs: fi - GH_AW_MCP_SCRIPTS_SH_GITHUB-DISCUSSION-QUERY_b50de5e7f97072ad_EOF + GH_AW_MCP_SCRIPTS_SH_GITHUB-DISCUSSION-QUERY_4bb5a1d76051bfda_EOF chmod +x "${RUNNER_TEMP}/gh-aw/mcp-scripts/github-discussion-query.sh" - cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/github-issue-query.sh" << 'GH_AW_MCP_SCRIPTS_SH_GITHUB-ISSUE-QUERY_054c8b7aaab273dc_EOF' + cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/github-issue-query.sh" << 'GH_AW_MCP_SCRIPTS_SH_GITHUB-ISSUE-QUERY_1cda48bd8258ba69_EOF' #!/bin/bash # Auto-generated mcp-script tool: github-issue-query # Query GitHub issues with jq filtering support. Without --jq, returns schema and data size info. Use --jq '.' to get all data, or specific jq expressions to filter. @@ -1874,9 +1847,9 @@ jobs: fi - GH_AW_MCP_SCRIPTS_SH_GITHUB-ISSUE-QUERY_054c8b7aaab273dc_EOF + GH_AW_MCP_SCRIPTS_SH_GITHUB-ISSUE-QUERY_1cda48bd8258ba69_EOF chmod +x "${RUNNER_TEMP}/gh-aw/mcp-scripts/github-issue-query.sh" - cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/github-pr-query.sh" << 'GH_AW_MCP_SCRIPTS_SH_GITHUB-PR-QUERY_a5da61d678c8152b_EOF' + cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/github-pr-query.sh" << 'GH_AW_MCP_SCRIPTS_SH_GITHUB-PR-QUERY_f7002bcd7e94653c_EOF' #!/bin/bash # Auto-generated mcp-script tool: github-pr-query # Query GitHub pull requests with jq filtering support. Without --jq, returns schema and data size info. Use --jq '.' to get all data, or specific jq expressions to filter. @@ -1961,9 +1934,9 @@ jobs: fi - GH_AW_MCP_SCRIPTS_SH_GITHUB-PR-QUERY_a5da61d678c8152b_EOF + GH_AW_MCP_SCRIPTS_SH_GITHUB-PR-QUERY_f7002bcd7e94653c_EOF chmod +x "${RUNNER_TEMP}/gh-aw/mcp-scripts/github-pr-query.sh" - cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/go.sh" << 'GH_AW_MCP_SCRIPTS_SH_GO_a5e8cdfc6555c88b_EOF' + cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/go.sh" << 'GH_AW_MCP_SCRIPTS_SH_GO_0db7e2f95b351762_EOF' #!/bin/bash # Auto-generated mcp-script tool: go # Execute any Go command. This tool is accessible as 'mcpscripts-go'. Provide the full command after 'go' (e.g., args: 'test ./...'). The tool will run: go . Use single quotes ' for complex args to avoid shell interpretation issues. @@ -1974,9 +1947,9 @@ jobs: go $INPUT_ARGS - GH_AW_MCP_SCRIPTS_SH_GO_a5e8cdfc6555c88b_EOF + GH_AW_MCP_SCRIPTS_SH_GO_0db7e2f95b351762_EOF chmod +x "${RUNNER_TEMP}/gh-aw/mcp-scripts/go.sh" - cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/make.sh" << 'GH_AW_MCP_SCRIPTS_SH_MAKE_04f6e6e974e8cded_EOF' + cat > "${RUNNER_TEMP}/gh-aw/mcp-scripts/make.sh" << 'GH_AW_MCP_SCRIPTS_SH_MAKE_4e7df60498ef2d78_EOF' #!/bin/bash # Auto-generated mcp-script tool: make # Execute any Make target. This tool is accessible as 'mcpscripts-make'. Provide the target name(s) (e.g., args: 'build'). The tool will run: make . Use single quotes ' for complex args to avoid shell interpretation issues. @@ -1987,7 +1960,7 @@ jobs: make $INPUT_ARGS - GH_AW_MCP_SCRIPTS_SH_MAKE_04f6e6e974e8cded_EOF + GH_AW_MCP_SCRIPTS_SH_MAKE_4e7df60498ef2d78_EOF chmod +x "${RUNNER_TEMP}/gh-aw/mcp-scripts/make.sh" - name: Generate MCP Scripts Server Config @@ -2062,7 +2035,7 @@ jobs: export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v '"${DOCKER_SOCK_PATH}"':/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 DOCKER_HOST=unix:///var/run/docker.sock -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 GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -e OTEL_EXPORTER_OTLP_HEADERS -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.3.9' GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_b1913958c44ac757_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_4c182b9a69f0c7d9_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "agenticworkflows": { @@ -2170,7 +2143,7 @@ jobs: } } } - GH_AW_MCP_CONFIG_b1913958c44ac757_EOF + GH_AW_MCP_CONFIG_4c182b9a69f0c7d9_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true @@ -3060,7 +3033,7 @@ jobs: echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV" - name: Configure Safe Outputs Custom Scripts run: | - cat > "${RUNNER_TEMP}/gh-aw/actions/safe_output_script_post_slack_message.cjs" << 'GH_AW_SAFE_OUTPUT_SCRIPT_POST_SLACK_MESSAGE_7e9e0beee2799851_EOF' + cat > "${RUNNER_TEMP}/gh-aw/actions/safe_output_script_post_slack_message.cjs" << 'GH_AW_SAFE_OUTPUT_SCRIPT_POST_SLACK_MESSAGE_97f928eae5e28942_EOF' // @ts-check /// // Auto-generated safe-output script handler: post-slack-message @@ -3080,7 +3053,7 @@ jobs: } module.exports = { main }; - GH_AW_SAFE_OUTPUT_SCRIPT_POST_SLACK_MESSAGE_7e9e0beee2799851_EOF + GH_AW_SAFE_OUTPUT_SCRIPT_POST_SLACK_MESSAGE_97f928eae5e28942_EOF - name: Process Safe Outputs id: process_safe_outputs uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 diff --git a/.github/workflows/smoke-claude.md b/.github/workflows/smoke-claude.md index e5d0559bc19..6f914ff3566 100644 --- a/.github/workflows/smoke-claude.md +++ b/.github/workflows/smoke-claude.md @@ -58,7 +58,6 @@ runtimes: checkout: fetch: ["*"] fetch-depth: 0 - force-clean-git-credentials: true safe-outputs: allowed-domains: [default-safe-outputs] add-comment: diff --git a/actions/setup/README.md b/actions/setup/README.md index ef99cd0e1f7..2cb81b6b066 100644 --- a/actions/setup/README.md +++ b/actions/setup/README.md @@ -8,7 +8,7 @@ This action runs in all workflow jobs to provide scripts that can be used instea The action copies: - 226 `.cjs` JavaScript files from the `js/` directory -- 8 `.sh` shell scripts from the `sh/` directory +- 7 `.sh` shell scripts from the `sh/` directory All files are copied to the destination directory (default: `${{ runner.temp }}/gh-aw/actions`). These files are generated by running `make actions-build` and are committed to the repository. @@ -35,7 +35,7 @@ Default: `${{ runner.temp }}/gh-aw/actions` ### `files-copied` -The number of files copied to the destination directory (should be 234: 226 JavaScript files + 8 shell scripts). +The number of files copied to the destination directory (should be 233: 226 JavaScript files + 7 shell scripts). ## Example diff --git a/actions/setup/sh/clean_git_credentials.sh b/actions/setup/sh/clean_git_credentials.sh index 44e90c48622..487f3cb1fc9 100755 --- a/actions/setup/sh/clean_git_credentials.sh +++ b/actions/setup/sh/clean_git_credentials.sh @@ -78,15 +78,12 @@ clean_git_config() { # Get the workspace directory (defaults to current GITHUB_WORKSPACE) WORKSPACE="${GITHUB_WORKSPACE:-.}" -# Collect all git config files to clean from workspace and /tmp/. -# Includes both repository configs and submodule configs under .git/modules/**/config. -# Use maxdepth 15 as a conservative cap to cover deeply nested submodules -# (.git/modules//modules//...) without unbounded traversal. +# Collect all .git/config files to clean from workspace and /tmp/ CLEANED=0 while IFS= read -r git_config; do clean_git_config "${git_config}" CLEANED=$((CLEANED + 1)) -done < <(find "${WORKSPACE}" /tmp -maxdepth 15 -type f -name "config" \( -path "*/.git/config" -o -path "*/.git/modules/*/config" \) 2>/dev/null | sort -u) +done < <(find "${WORKSPACE}" /tmp -maxdepth 10 -name "config" -path "*/.git/config" 2>/dev/null | sort -u) if [ "${CLEANED}" -eq 0 ]; then echo "No .git/config files found, nothing to clean" diff --git a/actions/setup/sh/clean_git_credentials_checkout.sh b/actions/setup/sh/clean_git_credentials_checkout.sh deleted file mode 100644 index e79f46a3d91..00000000000 --- a/actions/setup/sh/clean_git_credentials_checkout.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env bash -# clean_git_credentials_checkout.sh - Checkout-time git credential cleanup orchestration -set -euo pipefail -set +o histexpand - -if [ -x "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh" ]; then - echo "Using shared clean_git_credentials.sh from setup action" - bash "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh" - exit 0 -fi - -if [ -x "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials_pre_setup.sh" ]; then - echo "Using pre-setup clean_git_credentials helper from runner temp bundle" - bash "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials_pre_setup.sh" - exit 0 -fi - -echo "WARNING: Git credential cleanup helper unavailable. Running inline fallback." - -cleaned_configs=0 -while IFS= read -r git_config; do - git config --file "${git_config}" --remove-section credential 2>/dev/null || true - sed -i '/^\[credential /,/^\[/{ /^\[credential /d; /^\[/!d; }' "${git_config}" 2>/dev/null || true - git config --file "${git_config}" --unset-all http.extraheader 2>/dev/null || true - git config --file "${git_config}" --get-regexp '^http\..*\.extraheader$' 2>/dev/null | while read -r key _; do - git config --file "${git_config}" --unset-all "${key}" || true - done || true - git config --file "${git_config}" --get-regexp '^remote\..*\.url$' 2>/dev/null | while read -r key url; do - clean_url=$(echo "${url}" | sed -E 's|(https?://)([^@]+@)?(.*)|\1\3|') - if [ "${url}" != "${clean_url}" ]; then - git config --file "${git_config}" "${key}" "${clean_url}" - fi - done || true - cleaned_configs=$((cleaned_configs + 1)) -done < <(find "${GITHUB_WORKSPACE}" /tmp -maxdepth 15 -type f -name "config" \( -path "*/.git/config" -o -path "*/.git/modules/*/config" \) 2>/dev/null | sort -u) - -if [ "${cleaned_configs}" -eq 0 ]; then - echo "No git config files found for checkout cleanup fallback" -fi diff --git a/actions/setup/sh/clean_git_credentials_pre_setup.sh b/actions/setup/sh/clean_git_credentials_pre_setup.sh deleted file mode 100755 index 17e5f0cf360..00000000000 --- a/actions/setup/sh/clean_git_credentials_pre_setup.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash -# clean_git_credentials_pre_setup.sh - Checkout-time credential cleanup fallback -# -# Used only before Setup Scripts has copied runtime helpers to -# ${RUNNER_TEMP}/gh-aw/actions. Unlike clean_git_credentials.sh, this script runs -# from a pre-setup helper path (runner temp bundle or repository workspace). -set -euo pipefail -# Disable history expansion so values containing "!" are handled safely. -set +o histexpand - -git_configs_processed=0 -while IFS= read -r git_config; do - git config --file "${git_config}" --remove-section credential 2>/dev/null || true - git config --file "${git_config}" --unset-all http.extraheader 2>/dev/null || true - git config --file "${git_config}" --get-regexp '^http\..*\.extraheader$' 2>/dev/null | while read -r key _; do - git config --file "${git_config}" --unset-all "${key}" || true - done || true - git_configs_processed=$((git_configs_processed + 1)) -done < <(find "${GITHUB_WORKSPACE}" /tmp -maxdepth 15 -type f -name "config" \( -path "*/.git/config" -o -path "*/.git/modules/*/config" \) 2>/dev/null | sort -u) - -if [ "${git_configs_processed}" -eq 0 ]; then - echo "No git config files found for cleanup" -fi diff --git a/actions/setup/sh/clean_git_credentials_test.sh b/actions/setup/sh/clean_git_credentials_test.sh index 74066169711..cd0a487b19b 100644 --- a/actions/setup/sh/clean_git_credentials_test.sh +++ b/actions/setup/sh/clean_git_credentials_test.sh @@ -144,36 +144,6 @@ assert "config still valid" "git config --file '${REPO}/.git/config' --list >/de assert "core settings intact" "git config --file '${REPO}/.git/config' core.repositoryformatversion >/dev/null 2>&1" echo "" -# ── Test 8: Cleans submodule git configs under .git/modules ───────────────── -echo "Test 8: Cleans submodule git config files" -REPO="${TEST_WORKSPACE}/repo8" -mkdir -p "${REPO}/.git/modules/sub" "${REPO}/.git/modules/sub/modules/nested" -cat >"${REPO}/.git/modules/sub/config" <<'EOF' -[core] - repositoryformatversion = 0 -[credential "https://github.com"] - helper = store -[http "https://github.com/"] - extraheader = Authorization: Basic abc123 -[remote "origin"] - url = https://x-access-token:ghs_sub@github.com/org/sub.git -EOF -cat >"${REPO}/.git/modules/sub/modules/nested/config" <<'EOF' -[core] - repositoryformatversion = 0 -[credential] - helper = store -[http] - extraheader = Authorization: Basic def456 -EOF -GITHUB_WORKSPACE="${REPO}" bash "${CLEAN_SCRIPT}" >/dev/null 2>&1 -assert "submodule credential section removed" "! grep -q '\[credential' '${REPO}/.git/modules/sub/config'" -assert "submodule url extraheader removed" "! git config --file '${REPO}/.git/modules/sub/config' 'http.https://github.com/.extraheader' 2>/dev/null" -assert "submodule remote URL credentials stripped" "[ \"\$(git config --file '${REPO}/.git/modules/sub/config' remote.origin.url)\" = 'https://github.com/org/sub.git' ]" -assert "nested submodule credential section removed" "! grep -q '\[credential' '${REPO}/.git/modules/sub/modules/nested/config'" -assert "nested submodule http.extraheader removed" "! git config --file '${REPO}/.git/modules/sub/modules/nested/config' http.extraheader 2>/dev/null" -echo "" - # ── Summary ────────────────────────────────────────────────────────────────── echo "Tests passed: ${TESTS_PASSED}" echo "Tests failed: ${TESTS_FAILED}" diff --git a/docs/adr/26666-add-pre-agent-steps-support.md b/docs/adr/26666-add-pre-agent-steps-support.md index f235237eb9e..784a33afd00 100644 --- a/docs/adr/26666-add-pre-agent-steps-support.md +++ b/docs/adr/26666-add-pre-agent-steps-support.md @@ -36,7 +36,7 @@ Users could approximate "run before engine" behaviour by placing steps in `post- - Users can inject pre-execution logic (context preparation, validation, environment mutations) at exactly the right lifecycle point — after setup, before the agent starts. - The new field mirrors the naming and import-merge semantics of `pre-steps` and `post-steps`, keeping the mental model consistent and the feature discoverable. - Secret expression validation is automatically enforced on the new field using the existing `validateStepsSecrets` infrastructure, preserving the security model without new code. -- Integration tests cover placement order (after force-clean-git-credentials, before engine execution) and import merge ordering. +- Integration tests cover placement order (after clean-git-credentials, before engine execution) and import merge ordering. #### Negative - The workflow extension model now has three named step positions (`pre-steps`, `pre-agent-steps`, `post-steps`) plus the main `steps` field; the distinction between `pre-steps` and `pre-agent-steps` requires documentation to avoid confusion. diff --git a/pkg/cli/agent_download.go b/pkg/cli/agent_download.go index aee73049a74..d0a9e291cfc 100644 --- a/pkg/cli/agent_download.go +++ b/pkg/cli/agent_download.go @@ -8,9 +8,9 @@ import ( "os" "os/exec" "strings" + "time" "github.com/github/gh-aw/pkg/console" - "github.com/github/gh-aw/pkg/constants" "github.com/github/gh-aw/pkg/logger" "github.com/github/gh-aw/pkg/workflow" ) @@ -42,7 +42,7 @@ func downloadAgentFileFromGitHub(verbose bool) (string, error) { // Create HTTP client with timeout client := &http.Client{ - Timeout: constants.DefaultHTTPClientTimeout, + Timeout: 30 * time.Second, } // Download the file diff --git a/pkg/cli/deps_security.go b/pkg/cli/deps_security.go index 682cb54474c..a0599defe6f 100644 --- a/pkg/cli/deps_security.go +++ b/pkg/cli/deps_security.go @@ -9,9 +9,9 @@ import ( "os" "sort" "strings" + "time" "github.com/github/gh-aw/pkg/console" - "github.com/github/gh-aw/pkg/constants" "github.com/github/gh-aw/pkg/logger" ) @@ -136,7 +136,7 @@ func querySecurityAdvisories(ctx context.Context, depVersions map[string]string, url := "https://api.github.com/advisories?ecosystem=go&per_page=100" depsSecurityLog.Printf("Querying GitHub Security Advisory API: url=%s, dep_count=%d", url, len(depVersions)) - client := &http.Client{Timeout: constants.DefaultHTTPClientTimeout} + client := &http.Client{Timeout: 30 * time.Second} req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) if err != nil { return nil, err diff --git a/pkg/cli/logs_rate_limit_test.go b/pkg/cli/logs_rate_limit_test.go index 32976779845..66a544bef12 100644 --- a/pkg/cli/logs_rate_limit_test.go +++ b/pkg/cli/logs_rate_limit_test.go @@ -14,7 +14,7 @@ import ( // TestRateLimitResponseUnmarshal verifies that the rateLimitResponse struct correctly // unmarshals the JSON returned by `gh api rate_limit`. func TestRateLimitResponseUnmarshal(t *testing.T) { - now := time.Now().Add(time.Second * 30).Unix() + now := time.Now().Add(30 * time.Second).Unix() raw := []byte(`{ "resources": { "core": { diff --git a/pkg/cli/mcp_add_integration_test.go b/pkg/cli/mcp_add_integration_test.go index b29a8f14a67..a2e7d199343 100644 --- a/pkg/cli/mcp_add_integration_test.go +++ b/pkg/cli/mcp_add_integration_test.go @@ -14,8 +14,6 @@ import ( "strings" "testing" "time" - - "github.com/github/gh-aw/pkg/constants" ) // createMockMCPRegistry creates a mock MCP registry server for testing @@ -240,7 +238,7 @@ This is a test workflow for MCP server integration. addCmd.Dir = setup.tempDir // Set a timeout for each server addition - timeout := constants.DefaultHTTPClientTimeout + timeout := 30 * time.Second addCmd.Env = os.Environ() done := make(chan error, 1) diff --git a/pkg/cli/mcp_registry.go b/pkg/cli/mcp_registry.go index 7b144e0e7b5..5bea30e92ec 100644 --- a/pkg/cli/mcp_registry.go +++ b/pkg/cli/mcp_registry.go @@ -7,6 +7,7 @@ import ( "io" "net/http" "strings" + "time" "github.com/github/gh-aw/pkg/console" "github.com/github/gh-aw/pkg/constants" @@ -46,7 +47,7 @@ func NewMCPRegistryClient(registryURL string) *MCPRegistryClient { return &MCPRegistryClient{ registryURL: registryURL, httpClient: &http.Client{ - Timeout: constants.DefaultHTTPClientTimeout, + Timeout: 30 * time.Second, }, } } diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index 0ec3bbb7a6d..885cf94ae11 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -256,9 +256,6 @@ const DefaultToolTimeout = 60 * time.Second // DefaultMCPStartupTimeout is the default timeout for MCP server startup const DefaultMCPStartupTimeout = 120 * time.Second -// DefaultHTTPClientTimeout is the default timeout for internal HTTP clients -const DefaultHTTPClientTimeout = 30 * time.Second - // DefaultMaxEffectiveTokens is the default ET budget enforced by the AWF API proxy. const DefaultMaxEffectiveTokens int64 = 25000000 diff --git a/pkg/constants/constants_test.go b/pkg/constants/constants_test.go index 27ae7c77813..d1464447b41 100644 --- a/pkg/constants/constants_test.go +++ b/pkg/constants/constants_test.go @@ -351,16 +351,13 @@ func TestNumericConstants(t *testing.T) { func TestTimeoutConstants(t *testing.T) { // Test new time.Duration-based constants tests := []struct { - name string - value time.Duration - minValue time.Duration - checkExact bool - exactValue time.Duration + name string + value time.Duration + minValue time.Duration }{ - {"DefaultAgenticWorkflowTimeout", DefaultAgenticWorkflowTimeout, 1 * time.Minute, false, 0}, - {"DefaultToolTimeout", DefaultToolTimeout, 1 * time.Second, false, 0}, - {"DefaultMCPStartupTimeout", DefaultMCPStartupTimeout, 1 * time.Second, false, 0}, - {"DefaultHTTPClientTimeout", DefaultHTTPClientTimeout, 1 * time.Second, true, time.Second * 30}, + {"DefaultAgenticWorkflowTimeout", DefaultAgenticWorkflowTimeout, 1 * time.Minute}, + {"DefaultToolTimeout", DefaultToolTimeout, 1 * time.Second}, + {"DefaultMCPStartupTimeout", DefaultMCPStartupTimeout, 1 * time.Second}, } for _, tt := range tests { @@ -368,9 +365,6 @@ func TestTimeoutConstants(t *testing.T) { if tt.value < tt.minValue { t.Errorf("%s = %v, should be >= %v", tt.name, tt.value, tt.minValue) } - if tt.checkExact && tt.value != tt.exactValue { - t.Errorf("%s = %v, want %v", tt.name, tt.value, tt.exactValue) - } }) } } diff --git a/pkg/parser/remote_fetch.go b/pkg/parser/remote_fetch.go index 14f395d2d05..613c9d9d6ce 100644 --- a/pkg/parser/remote_fetch.go +++ b/pkg/parser/remote_fetch.go @@ -14,6 +14,7 @@ import ( pathpkg "path" "path/filepath" "strings" + "time" "github.com/cli/go-gh/v2" "github.com/cli/go-gh/v2/pkg/api" @@ -519,7 +520,7 @@ func downloadFileViaRawURL(owner, repo, filePath, ref string) ([]byte, error) { remoteLog.Printf("Attempting raw URL download: %s", rawURL) // Use a client with a timeout to prevent indefinite hangs on slow/unresponsive hosts. - rawClient := &http.Client{Timeout: constants.DefaultHTTPClientTimeout} + rawClient := &http.Client{Timeout: 30 * time.Second} // #nosec G107 -- rawURL is constructed from workflow import configuration authored by // the developer; the owner, repo, filePath, and ref are user-supplied workflow spec fields. diff --git a/pkg/parser/schemas/main_workflow_schema.json b/pkg/parser/schemas/main_workflow_schema.json index ea132d8fc80..3a75a3ae242 100644 --- a/pkg/parser/schemas/main_workflow_schema.json +++ b/pkg/parser/schemas/main_workflow_schema.json @@ -11199,11 +11199,6 @@ "type": "boolean", "description": "When true, clones the repository's wiki git instead of the regular repository. The effective repository becomes \"{repository}.wiki\" (e.g. \"owner/repo.wiki\"). Defaults to false.", "examples": [true, false] - }, - "force-clean-git-credentials": { - "type": "boolean", - "description": "When true, persist credentials during checkout, then immediately run a post-checkout cleanup step that removes credentials from root and submodule git configs. Useful for submodule-safe cleanup behavior.", - "examples": [true, false] } } }, diff --git a/pkg/workflow/checkout_config_parser.go b/pkg/workflow/checkout_config_parser.go index 54416a2350b..211bbb4d6e6 100644 --- a/pkg/workflow/checkout_config_parser.go +++ b/pkg/workflow/checkout_config_parser.go @@ -237,14 +237,6 @@ func checkoutConfigFromMap(m map[string]any) (*CheckoutConfig, error) { cfg.Wiki = b } - if v, ok := m["force-clean-git-credentials"]; ok { - b, ok := v.(bool) - if !ok { - return nil, errors.New("checkout.force-clean-git-credentials must be a boolean") - } - cfg.CleanGitCredentials = b - } - return cfg, nil } diff --git a/pkg/workflow/checkout_manager.go b/pkg/workflow/checkout_manager.go index 1381c82f313..c0ac0afa645 100644 --- a/pkg/workflow/checkout_manager.go +++ b/pkg/workflow/checkout_manager.go @@ -97,11 +97,6 @@ type CheckoutConfig struct { // When true, the effective repository becomes "{repository}.wiki" (e.g. "owner/repo.wiki"). // Defaults to false. Wiki bool `json:"wiki,omitempty"` - - // CleanGitCredentials keeps actions/checkout credential persistence enabled and - // injects a follow-up cleanup step that removes credentials from git config files - // (including submodule configs) without using git submodule foreach. - CleanGitCredentials bool `json:"force-clean-git-credentials,omitempty"` } // checkoutKey uniquely identifies a checkout target used for grouping/deduplication. @@ -127,7 +122,6 @@ type resolvedCheckout struct { lfs bool current bool // true if this checkout is the logical current repository fetchRefs []string // merged fetch ref patterns (see CheckoutConfig.Fetch) - cleanCreds bool // true enables persist-credentials + injected cleanup step // wiki is intentionally not stored here; use entry.key.wiki instead. } @@ -265,9 +259,6 @@ func (cm *CheckoutManager) add(cfg *CheckoutConfig) { if len(cfg.Fetch) > 0 { entry.fetchRefs = mergeFetchRefs(entry.fetchRefs, cfg.Fetch) } - if cfg.CleanGitCredentials { - entry.cleanCreds = true - } checkoutManagerLog.Printf("Merged checkout for path=%q repository=%q", key.path, key.repository) } else { entry := &resolvedCheckout{ @@ -279,7 +270,6 @@ func (cm *CheckoutManager) add(cfg *CheckoutConfig) { submodules: cfg.Submodules, lfs: cfg.LFS, current: cfg.Current, - cleanCreds: cfg.CleanGitCredentials, } if cfg.SparseCheckout != "" { entry.sparsePatterns = mergeSparsePatterns(nil, cfg.SparseCheckout) diff --git a/pkg/workflow/checkout_manager_test.go b/pkg/workflow/checkout_manager_test.go index d0c3b6a84d0..945641c0d35 100644 --- a/pkg/workflow/checkout_manager_test.go +++ b/pkg/workflow/checkout_manager_test.go @@ -180,20 +180,6 @@ func TestGenerateDefaultCheckoutStep(t *testing.T) { assert.Contains(t, combined, ".github/", "should include first pattern") assert.Contains(t, combined, "src/", "should include second pattern") }) - - t.Run("force-clean-git-credentials enables persist true and cleanup step", func(t *testing.T) { - cm := NewCheckoutManager([]*CheckoutConfig{ - {CleanGitCredentials: true}, - }) - lines := cm.GenerateDefaultCheckoutStep(false, "", getPin) - combined := strings.Join(lines, "") - assert.Contains(t, combined, "persist-credentials: true", "force-clean-git-credentials should switch persist-credentials to true") - assert.Contains(t, combined, "Clean git credentials after checkout", "should inject post-checkout clean step") - assert.Contains(t, combined, "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials_checkout.sh", "cleanup should call orchestrator helper") - assert.NotContains(t, combined, "${GITHUB_WORKSPACE}/actions/setup/sh/clean_git_credentials_pre_setup.sh", "cleanup must not execute helper from workspace") - assert.NotContains(t, combined, "WARNING: Checkout cleanup helper missing. Running inline fallback.", "cleanup should not include inline fallback path") - assert.NotContains(t, combined, "cleaned_configs=0", "cleanup should not include inline fallback logic") - }) } // TestGenerateAdditionalCheckoutSteps verifies that non-default checkouts are emitted correctly. @@ -248,16 +234,6 @@ func TestGenerateAdditionalCheckoutSteps(t *testing.T) { assert.Contains(t, combined, "token: ${{ secrets.MY_TOKEN }}", "actions/checkout input must be 'token' even when frontmatter uses 'github-token'") assert.NotContains(t, combined, "github-token:", "must not emit 'github-token' as actions/checkout input") }) - - t.Run("additional checkout supports force-clean-git-credentials", func(t *testing.T) { - cm := NewCheckoutManager([]*CheckoutConfig{ - {Path: "./libs", Repository: "owner/libs", CleanGitCredentials: true}, - }) - lines := cm.GenerateAdditionalCheckoutSteps(getPin) - combined := strings.Join(lines, "") - assert.Contains(t, combined, "persist-credentials: true", "force-clean-git-credentials should switch persist-credentials to true") - assert.Contains(t, combined, "Clean git credentials after checkout", "should inject post-checkout clean step") - }) } // TestParseCheckoutConfigs verifies parsing of raw frontmatter values. @@ -1115,25 +1091,6 @@ func TestWikiCheckout(t *testing.T) { assert.Contains(t, err.Error(), "checkout.wiki must be a boolean", "error message should mention wiki") }) - t.Run("parse force-clean-git-credentials true", func(t *testing.T) { - raw := map[string]any{ - "force-clean-git-credentials": true, - } - configs, err := ParseCheckoutConfigs(raw) - require.NoError(t, err, "should parse force-clean-git-credentials: true without error") - require.Len(t, configs, 1, "should produce one config") - assert.True(t, configs[0].CleanGitCredentials, "force-clean-git-credentials should be true") - }) - - t.Run("force-clean-git-credentials must be boolean", func(t *testing.T) { - raw := map[string]any{ - "force-clean-git-credentials": "true", - } - _, err := ParseCheckoutConfigs(raw) - require.Error(t, err, "non-boolean force-clean-git-credentials should return error") - assert.Contains(t, err.Error(), "checkout.force-clean-git-credentials must be a boolean", "error message should mention force-clean-git-credentials") - }) - t.Run("wiki and non-wiki checkouts of same repo and path are not merged", func(t *testing.T) { cm := NewCheckoutManager([]*CheckoutConfig{ {Repository: "owner/repo", Path: "./wiki", Wiki: true}, diff --git a/pkg/workflow/checkout_step_generator.go b/pkg/workflow/checkout_step_generator.go index 0a1c2235959..bbbfed0f5f5 100644 --- a/pkg/workflow/checkout_step_generator.go +++ b/pkg/workflow/checkout_step_generator.go @@ -164,14 +164,9 @@ func (cm *CheckoutManager) GenerateDefaultCheckoutStep( fmt.Fprintf(&sb, " uses: %s\n", getActionPin("actions/checkout")) sb.WriteString(" with:\n") - cleanCreds := override != nil && override.cleanCreds - if cleanCreds { - sb.WriteString(" persist-credentials: true\n") - } else { - // Security: default behavior disables credential persistence so the agent cannot - // exfiltrate credentials from disk. - sb.WriteString(" persist-credentials: false\n") - } + // Security: always disable credential persistence so the agent cannot + // exfiltrate credentials from disk. + sb.WriteString(" persist-credentials: false\n") // Apply trial mode overrides if trialMode { @@ -226,9 +221,6 @@ func (cm *CheckoutManager) GenerateDefaultCheckoutStep( } steps := []string{sb.String()} - if cleanCreds { - steps = append(steps, generateCheckoutCredentialsCleanupStep()) - } // Emit a git fetch step if the user requested additional refs. // In trial mode the fetch step is still emitted so the behaviour @@ -258,12 +250,8 @@ func generateCheckoutStepLines(entry *resolvedCheckout, index int, getActionPin fmt.Fprintf(&sb, " uses: %s\n", getActionPin("actions/checkout")) sb.WriteString(" with:\n") - if entry.cleanCreds { - sb.WriteString(" persist-credentials: true\n") - } else { - // Security: default behavior disables credential persistence - sb.WriteString(" persist-credentials: false\n") - } + // Security: always disable credential persistence + sb.WriteString(" persist-credentials: false\n") if entry.key.wiki { // Wiki checkout: use "{repository}.wiki" as the effective repository. @@ -304,22 +292,12 @@ func generateCheckoutStepLines(entry *resolvedCheckout, index int, getActionPin } steps := []string{sb.String()} - if entry.cleanCreds { - steps = append(steps, generateCheckoutCredentialsCleanupStep()) - } if fetchStep := generateFetchStepLines(entry, index); fetchStep != "" { steps = append(steps, fetchStep) } return steps } -func generateCheckoutCredentialsCleanupStep() string { - return ` - name: Clean git credentials after checkout - continue-on-error: true - run: bash "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials_checkout.sh" -` -} - // checkoutStepName returns a human-readable description for a checkout step. func checkoutStepName(key checkoutKey) string { if key.repository != "" && key.path != "" { diff --git a/scratchpad/chaos/night-owl-r21-main.md b/scratchpad/chaos/night-owl-r21-main.md new file mode 100644 index 00000000000..33f98b6e07d --- /dev/null +++ b/scratchpad/chaos/night-owl-r21-main.md @@ -0,0 +1,2 @@ +# Night Owl Main Branch (Run 21) +Work done at 2am - approach B diff --git a/scratchpad/chaos/night-owl-r21-side.md b/scratchpad/chaos/night-owl-r21-side.md new file mode 100644 index 00000000000..0008ff7b330 --- /dev/null +++ b/scratchpad/chaos/night-owl-r21-side.md @@ -0,0 +1,2 @@ +# Night Owl Side Branch (Run 21) +Work done at 2am - approach A