From f025068d4224990acc6a7a9974a6d329627adb1f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 20 Apr 2026 17:01:05 +0000 Subject: [PATCH 1/3] Initial plan From e260523f1092b0636198149b99d8649b98583d38 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 20 Apr 2026 17:17:15 +0000 Subject: [PATCH 2/3] optimize ci-coach prompt and pre-analysis data flow Agent-Logs-Url: https://github.com/github/gh-aw/sessions/231da9f0-236b-45e7-9f52-eeb3b0891152 Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com> --- .github/workflows/ci-coach.lock.yml | 80 ++++++----- .github/workflows/ci-coach.md | 132 ++++-------------- .github/workflows/shared/ci-data-analysis.md | 49 +++++-- .../shared/ci-optimization-strategies.md | 48 ++----- 4 files changed, 109 insertions(+), 200 deletions(-) diff --git a/.github/workflows/ci-coach.lock.yml b/.github/workflows/ci-coach.lock.yml index 1f53aa6dc73..0453194643a 100644 --- a/.github/workflows/ci-coach.lock.yml +++ b/.github/workflows/ci-coach.lock.yml @@ -1,5 +1,5 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"44bb3d00cb1a3cd1281e1d777096a17eec06b3b5a555a6efed0d71be8104ab9a","strict":true,"agent_id":"copilot"} -# gh-aw-manifest: {"version":1,"secrets":["GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"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":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/setup-go","sha":"4a3601121dd01d1626a1e23e37211e3254c1c06c","version":"v6.4.0"},{"repo":"actions/setup-node","sha":"53b83947a5a98c8d113130e565377fae1a50d02f","version":"v6.3.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.25"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.25"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.25"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.2.25"},{"image":"ghcr.io/github/github-mcp-server:v1.0.0"},{"image":"node:lts-alpine","digest":"sha256:01743339035a5c3c11a373cd7c83aeab6ed1457b55da6a69e014a95ac4e4700b","pinned_image":"node:lts-alpine@sha256:01743339035a5c3c11a373cd7c83aeab6ed1457b55da6a69e014a95ac4e4700b"}]} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"19bc5e230212b21af230f066f6272be299e08305be643afb28cea83d0e7a26ba","strict":true,"agent_id":"copilot"} +# gh-aw-manifest: {"version":1,"secrets":["GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"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":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/setup-go","sha":"4a3601121dd01d1626a1e23e37211e3254c1c06c","version":"v6.4.0"},{"repo":"actions/setup-node","sha":"53b83947a5a98c8d113130e565377fae1a50d02f","version":"v6.3.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.25"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.25"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.25"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.25"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.2.25"},{"image":"ghcr.io/github/github-mcp-server:v1.0.0"},{"image":"node:lts-alpine","digest":"sha256:01743339035a5c3c11a373cd7c83aeab6ed1457b55da6a69e014a95ac4e4700b","pinned_image":"node:lts-alpine@sha256:01743339035a5c3c11a373cd7c83aeab6ed1457b55da6a69e014a95ac4e4700b"}]} # ___ _ _ # / _ \ | | (_) # | |_| | __ _ ___ _ __ | |_ _ ___ @@ -52,6 +52,7 @@ # Container images used: # - ghcr.io/github/gh-aw-firewall/agent:0.25.25 # - ghcr.io/github/gh-aw-firewall/api-proxy:0.25.25 +# - ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.25 # - ghcr.io/github/gh-aw-firewall/squid:0.25.25 # - ghcr.io/github/gh-aw-mcpg:v0.2.25 # - ghcr.io/github/github-mcp-server:v1.0.0 @@ -178,24 +179,24 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_8ad8648990102438_EOF' + cat << 'GH_AW_PROMPT_ce21b547f02262d0_EOF' - GH_AW_PROMPT_8ad8648990102438_EOF + GH_AW_PROMPT_ce21b547f02262d0_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" cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_8ad8648990102438_EOF' + cat << 'GH_AW_PROMPT_ce21b547f02262d0_EOF' Tools: create_pull_request, missing_tool, missing_data, noop - GH_AW_PROMPT_8ad8648990102438_EOF + GH_AW_PROMPT_ce21b547f02262d0_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_create_pull_request.md" - cat << 'GH_AW_PROMPT_8ad8648990102438_EOF' + cat << 'GH_AW_PROMPT_ce21b547f02262d0_EOF' - GH_AW_PROMPT_8ad8648990102438_EOF + GH_AW_PROMPT_ce21b547f02262d0_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_8ad8648990102438_EOF' + cat << 'GH_AW_PROMPT_ce21b547f02262d0_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -224,16 +225,16 @@ jobs: {{/if}} - GH_AW_PROMPT_8ad8648990102438_EOF - cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_8ad8648990102438_EOF' + GH_AW_PROMPT_ce21b547f02262d0_EOF + cat "${RUNNER_TEMP}/gh-aw/prompts/cli_proxy_with_safeoutputs_prompt.md" + cat << 'GH_AW_PROMPT_ce21b547f02262d0_EOF' {{#runtime-import .github/workflows/shared/ci-data-analysis.md}} {{#runtime-import .github/workflows/shared/ci-optimization-strategies.md}} {{#runtime-import .github/workflows/shared/reporting.md}} {{#runtime-import .github/workflows/shared/jqschema.md}} {{#runtime-import .github/workflows/ci-coach.md}} - GH_AW_PROMPT_8ad8648990102438_EOF + GH_AW_PROMPT_ce21b547f02262d0_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 @@ -386,7 +387,9 @@ jobs: - env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} name: Download CI workflow runs from last 7 days - run: "# Download workflow runs for the ci workflow\ngh run list --repo \"$GITHUB_REPOSITORY\" --workflow=ci.yml --limit 100 --json databaseId,status,conclusion,createdAt,updatedAt,displayTitle,headBranch,event,url,workflowDatabaseId,number > /tmp/ci-runs.json\n\n# Create directory for artifacts\nmkdir -p /tmp/ci-artifacts\n\n# Download artifacts from recent runs (last 5 successful runs)\necho \"Downloading artifacts from recent CI runs...\"\ngh run list --repo \"$GITHUB_REPOSITORY\" --workflow=ci.yml --status success --limit 5 --json databaseId | jq -r '.[].databaseId' | while read -r run_id; do\n echo \"Processing run $run_id\"\n gh run download \"$run_id\" --repo \"$GITHUB_REPOSITORY\" --dir \"/tmp/ci-artifacts/$run_id\" 2>/dev/null || echo \"No artifacts for run $run_id\"\ndone\n\necho \"CI runs data saved to /tmp/ci-runs.json\"\necho \"Artifacts saved to /tmp/ci-artifacts/\"\n\n# Summarize downloaded artifacts\necho \"## Downloaded Artifacts\" >> \"$GITHUB_STEP_SUMMARY\"\nfind /tmp/ci-artifacts -type f -name \"*.txt\" -o -name \"*.html\" -o -name \"*.json\" | head -20 | while read -r f; do\n echo \"- $(basename \"$f\")\" >> \"$GITHUB_STEP_SUMMARY\"\ndone\n" + run: "# Download workflow runs for the ci workflow\ngh run list --repo \"$GITHUB_REPOSITORY\" --workflow=ci.yml --limit 60 --json databaseId,status,conclusion,createdAt,updatedAt,displayTitle,headBranch,event,url,workflowDatabaseId,number > /tmp/ci-runs.json\n\n# Create directory for artifacts\nmkdir -p /tmp/ci-artifacts\n\n# Download artifacts from recent runs (last 5 successful runs)\necho \"Downloading artifacts from recent CI runs...\"\ngh run list --repo \"$GITHUB_REPOSITORY\" --workflow=ci.yml --status success --limit 5 --json databaseId | jq -r '.[].databaseId' | while read -r run_id; do\n echo \"Processing run $run_id\"\n gh run download \"$run_id\" --repo \"$GITHUB_REPOSITORY\" --dir \"/tmp/ci-artifacts/$run_id\" 2>/dev/null || echo \"No artifacts for run $run_id\"\ndone\n\necho \"CI runs data saved to /tmp/ci-runs.json\"\necho \"Artifacts saved to /tmp/ci-artifacts/\"\n" + - name: Build CI summary for optimization analysis + run: "jq '\ndef safe_duration:\n if (.createdAt and .updatedAt) then\n ((.updatedAt | fromdateiso8601) - (.createdAt | fromdateiso8601))\n else null end;\n{\n generated_at: now | todateiso8601,\n total_runs: length,\n status_counts: (group_by(.status) | map({status: .[0].status, count: length})),\n conclusion_counts: (map(select(.conclusion != null)) | group_by(.conclusion) | map({conclusion: .[0].conclusion, count: length})),\n branch_counts: (group_by(.headBranch) | map({branch: .[0].headBranch, count: length}) | sort_by(-.count) | .[0:10]),\n avg_duration_seconds: ([.[] | safe_duration | select(. != null)] | if length > 0 then (add / length) else null end),\n top_recent_failures: ([.[] | select(.conclusion == \"failure\" or .conclusion == \"cancelled\") | {id: .databaseId, run_number: .number, title: .displayTitle, branch: .headBranch, event: .event, url: .url, updated_at: .updatedAt}] | sort_by(.updated_at) | reverse | .[0:10])\n}' /tmp/ci-runs.json > /tmp/ci-summary.json\n\necho \"## CI Summary\" >> \"$GITHUB_STEP_SUMMARY\"\njq -r '\"- runs analyzed: \\(.total_runs)\\n- avg duration (sec): \\(.avg_duration_seconds // \"n/a\")\\n- recent failure records: \\(.top_recent_failures | length)\"' /tmp/ci-summary.json >> \"$GITHUB_STEP_SUMMARY\"\n" - name: Setup Go uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 with: @@ -474,15 +477,15 @@ jobs: const determineAutomaticLockdown = require('${{ runner.temp }}/gh-aw/actions/determine_automatic_lockdown.cjs'); await determineAutomaticLockdown(github, context, core); - name: Download container images - run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.25 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.25 ghcr.io/github/gh-aw-firewall/squid:0.25.25 ghcr.io/github/gh-aw-mcpg:v0.2.25 ghcr.io/github/github-mcp-server:v1.0.0 node:lts-alpine@sha256:01743339035a5c3c11a373cd7c83aeab6ed1457b55da6a69e014a95ac4e4700b + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.25 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.25 ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.25 ghcr.io/github/gh-aw-firewall/squid:0.25.25 ghcr.io/github/gh-aw-mcpg:v0.2.25 ghcr.io/github/github-mcp-server:v1.0.0 node:lts-alpine@sha256:01743339035a5c3c11a373cd7c83aeab6ed1457b55da6a69e014a95ac4e4700b - name: Write Safe Outputs Config run: | 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_376ead9c323017bb_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_455f9fde8d733299_EOF' {"create_pull_request":{"expires":48,"max":1,"max_patch_size":1024,"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","AGENTS.md","CLAUDE.md","GEMINI.md"],"protected_files_policy":"fallback-to-issue","protected_path_prefixes":[".github/",".agents/"],"title_prefix":"[ci-coach] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_376ead9c323017bb_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_455f9fde8d733299_EOF - name: Write Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -663,9 +666,6 @@ jobs: GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} - GITHUB_MCP_GUARD_MIN_INTEGRITY: ${{ steps.determine-automatic-lockdown.outputs.min_integrity }} - GITHUB_MCP_GUARD_REPOS: ${{ steps.determine-automatic-lockdown.outputs.repos }} - GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} run: | set -eo pipefail mkdir -p "${RUNNER_TEMP}/gh-aw/mcp-config" @@ -689,25 +689,9 @@ jobs: mkdir -p /home/runner/.copilot GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_ce1c6a9825dc8198_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_0b5d46011b910f12_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { - "github": { - "type": "stdio", - "container": "ghcr.io/github/github-mcp-server:v1.0.0", - "env": { - "GITHUB_HOST": "\${GITHUB_SERVER_URL}", - "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", - "GITHUB_READ_ONLY": "1", - "GITHUB_TOOLSETS": "context,repos,issues,pull_requests" - }, - "guard-policies": { - "allow-only": { - "min-integrity": "$GITHUB_MCP_GUARD_MIN_INTEGRITY", - "repos": "$GITHUB_MCP_GUARD_REPOS" - } - } - }, "safeoutputs": { "type": "http", "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", @@ -730,7 +714,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_ce1c6a9825dc8198_EOF + GH_AW_MCP_CONFIG_0b5d46011b910f12_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true @@ -759,6 +743,14 @@ jobs: - name: Clean git credentials continue-on-error: true run: bash "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh" + - name: Start CLI Proxy + env: + GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + GITHUB_SERVER_URL: ${{ github.server_url }} + CLI_PROXY_POLICY: '{"allow-only":{"repos":"all","min-integrity":"none"}}' + CLI_PROXY_IMAGE: 'ghcr.io/github/gh-aw-mcpg:v0.2.25' + run: | + bash "${RUNNER_TEMP}/gh-aw/actions/start_cli_proxy.sh" - name: Execute GitHub Copilot CLI id: agentic_execution # Copilot CLI tool arguments (sorted): @@ -770,7 +762,7 @@ jobs: export GH_AW_NODE_BIN (umask 177 && touch /tmp/gh-aw/agent-stdio.log) # shellcheck disable=SC1003 - sudo -E awf --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --env-all --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --allow-domains api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --image-tag 0.25.25 --skip-pull --enable-api-proxy \ + sudo -E awf --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --env-all --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GH_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --allow-domains api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --image-tag 0.25.25 --skip-pull --enable-api-proxy --difc-proxy-host host.docker.internal:18443 --difc-proxy-ca-cert /tmp/gh-aw/difc-proxy-tls/ca.crt \ -- /bin/bash -c 'export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || echo node)"; fi; "$GH_AW_NODE_EXEC" ${RUNNER_TEMP}/gh-aw/actions/copilot_driver.cjs /usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-all-tools --add-dir /tmp/gh-aw/cache-memory/ --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE @@ -781,6 +773,7 @@ jobs: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} GH_AW_VERSION: dev + GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }} GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows @@ -796,6 +789,10 @@ jobs: GIT_COMMITTER_NAME: github-actions[bot] S2STOKENS: true XDG_CONFIG_HOME: /home/runner + - name: Stop CLI Proxy + if: always() + continue-on-error: true + run: bash "${RUNNER_TEMP}/gh-aw/actions/stop_cli_proxy.sh" - name: Detect Copilot errors id: detect-copilot-errors if: always() @@ -1156,7 +1153,7 @@ jobs: rm -rf /tmp/gh-aw/sandbox/firewall/logs rm -rf /tmp/gh-aw/sandbox/firewall/audit - name: Download container images - run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.25 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.25 ghcr.io/github/gh-aw-firewall/squid:0.25.25 + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.25 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.25 ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.25 ghcr.io/github/gh-aw-firewall/squid:0.25.25 - name: Check if detection needed id: detection_guard if: always() @@ -1227,7 +1224,7 @@ jobs: export GH_AW_NODE_BIN (umask 177 && touch /tmp/gh-aw/threat-detection/detection.log) # shellcheck disable=SC1003 - sudo -E awf --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --env-all --exclude-env COPILOT_GITHUB_TOKEN --allow-domains api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,github.com,host.docker.internal,telemetry.enterprise.githubcopilot.com --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --image-tag 0.25.25 --skip-pull --enable-api-proxy \ + sudo -E awf --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --env-all --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GH_TOKEN --allow-domains api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,github.com,host.docker.internal,telemetry.enterprise.githubcopilot.com --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --image-tag 0.25.25 --skip-pull --enable-api-proxy --difc-proxy-host host.docker.internal:18443 --difc-proxy-ca-cert /tmp/gh-aw/difc-proxy-tls/ca.crt \ -- /bin/bash -c 'GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || echo node)"; fi; "$GH_AW_NODE_EXEC" ${RUNNER_TEMP}/gh-aw/actions/copilot_driver.cjs /usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-all-tools --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE @@ -1236,6 +1233,7 @@ jobs: GH_AW_PHASE: detection GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_VERSION: dev + GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }} GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows diff --git a/.github/workflows/ci-coach.md b/.github/workflows/ci-coach.md index 74ea9b6cfe8..11a4e83b380 100644 --- a/.github/workflows/ci-coach.md +++ b/.github/workflows/ci-coach.md @@ -14,7 +14,7 @@ engine: copilot tools: mount-as-clis: true github: - toolsets: [default] + toolsets: [issues, pull_requests] edit: safe-outputs: create-pull-request: @@ -28,6 +28,7 @@ imports: - shared/reporting.md features: mcp-cli: true + cli-proxy: true copilot-requests: true --- @@ -49,14 +50,16 @@ Analyze the CI workflow daily to identify concrete optimization opportunities th The `ci-data-analysis` shared module has pre-downloaded CI run data and built the project. Available data: -1. **CI Runs**: `/tmp/ci-runs.json` - Last 100 workflow runs -2. **Artifacts**: `/tmp/ci-artifacts/` - Coverage reports, benchmarks, and **fuzz test results** -3. **CI Configuration**: `.github/workflows/ci.yml` - Current workflow -4. **Cache Memory**: `/tmp/cache-memory/` - Historical analysis data -5. **Test Results**: `/tmp/gh-aw/test-results.json` - Test performance data -6. **Fuzz Results**: `/tmp/ci-artifacts/*/fuzz-results/` - Fuzz test output and corpus data +1. **CI Runs**: `/tmp/ci-runs.json` - Last 60 workflow runs +2. **CI Summary**: `/tmp/ci-summary.json` - Pre-computed failure patterns, duration stats, and top opportunities +3. **Artifacts**: `/tmp/ci-artifacts/` - Coverage reports, benchmarks, and **fuzz test results** +4. **CI Configuration**: `.github/workflows/ci.yml` - Current workflow +5. **Cache Memory**: `/tmp/cache-memory/` - Historical analysis data +6. **Test Results**: `/tmp/gh-aw/test-results.json` - Test performance data +7. **Fuzz Results**: `/tmp/ci-artifacts/*/fuzz-results/` - Fuzz test output and corpus data The project has been **built, linted, and tested** so you can validate changes immediately. +Start from `/tmp/ci-summary.json` first and only read raw files if a summary metric needs verification. ## Analysis Framework @@ -85,6 +88,13 @@ Follow the optimization strategies defined in the `ci-optimization-strategies` s - Evaluate fuzz test duration (currently 10s per test) - Consider if fuzz time should be increased for security-critical tests +### Early Exit Gate (mandatory after Phase 2) + +If CI health is good and no actionable regression is found in Phases 1-2: +1. Save a short no-op summary to cache memory +2. Call `noop` with concise evidence +3. Stop immediately (do not continue to Phases 3-5) + ### Phase 3: Identify Optimization Opportunities (10 minutes) Apply the optimization strategies from the shared module: 1. **Job Parallelization** - Reduce critical path @@ -151,113 +161,21 @@ If no improvements are found or changes are too risky: ## Pull Request Structure (if created) -**Report Formatting**: Use h3 (###) or lower for all headers in your PR description to maintain proper document hierarchy. The PR title serves as h1, so start section headers at h3. +Use this compact structure (h3 or lower headers only): ```markdown ### CI Optimization Proposal - ### Summary -[Brief overview of proposed changes and expected benefits] - -### Optimizations - -#### 1. [Optimization Name] -**Type**: [Parallelization/Cache/Testing/Resource/etc.] -**Impact**: [Estimated time/cost savings] -**Risk**: [Low/Medium/High] -**Changes**: -- Line X: [Description of change] -- Line Y: [Description of change] - -**Rationale**: [Why this improves efficiency] - -#### Example: Test Suite Restructuring -**Type**: Test Suite Optimization -**Impact**: ~5 minutes per run (40% reduction in test phase) -**Risk**: Low -**Changes**: -- Lines 15-57: Split unit test job into 3 parallel jobs by package -- Lines 58-117: Rebalance integration test matrix groups -- Line 83: Split "Workflow" tests into separate groups with specific patterns - -**Rationale**: Current integration tests wait unnecessarily for unit tests to complete. Integration tests don't use unit test outputs, so they can run in parallel. Splitting unit tests by package and rebalancing integration matrix reduces the critical path by 52%. - -
-View Detailed Test Structure Comparison - -**Current Test Structure:** -```yaml -test: - needs: [lint] - run: go test -v -count=1 -timeout=3m -tags '!integration' ./... - # Takes ~2.5 minutes, runs all unit tests sequentially - -integration: - needs: [test] # Blocks on test completion - matrix: 6 groups (imbalanced: "Workflow" takes 8min, others 3-4min) -``` - -**Proposed Test Structure:** -```yaml -test-unit-cli: - needs: [lint] - run: go test -v -parallel=4 -timeout=2m -tags '!integration' ./pkg/cli/... - # ~1.5 minutes - -test-unit-workflow: - needs: [lint] - run: go test -v -parallel=4 -timeout=2m -tags '!integration' ./pkg/workflow/... - # ~1.5 minutes - -test-unit-parser: - needs: [lint] - run: go test -v -parallel=4 -timeout=2m -tags '!integration' ./pkg/parser/... - # ~1 minute - -integration: - needs: [lint] # Run in parallel with unit tests - matrix: 8 balanced groups (each ~4 minutes) - # Split "Workflow" into 3 groups: workflow-compile, workflow-safe-outputs, workflow-tools -``` - -**Benefits:** -- Unit tests run in parallel (1.5 min vs 2.5 min) -- Integration starts immediately after lint (no waiting for unit tests) -- Better matrix balance reduces longest job from 8 min to 4 min -- Critical path: lint (2 min) → integration (4 min) = 6 min total -- Previous path: lint (2 min) → test (2.5 min) → integration (8 min) = 12.5 min - -
- -#### 2. [Next optimization...] - +### Top 1-3 Optimizations +#### [Optimization Name] +- Type: +- Impact: +- Risk: +- Changes: +- Rationale: ### Expected Impact -- **Total Time Savings**: ~X minutes per run -- **Cost Reduction**: ~$Y per month (estimated) -- **Risk Level**: [Overall risk assessment] - ### Validation Results -✅ All validations passed: -- Linting: `make lint` - passed -- Build: `make build` - passed -- Unit tests: `make test-unit` - passed -- Lock file compilation: `make recompile` - passed - -### Testing Plan -- [ ] Verify workflow syntax -- [ ] Test on feature branch -- [ ] Monitor first few runs after merge -- [ ] Validate cache hit rates -- [ ] Compare run times before/after - ### Metrics Baseline -[Current metrics from analysis for future comparison] -- Average run time: X minutes -- Success rate: Y% -- Cache hit rate: Z% - ---- -*Proposed by CI Coach workflow run #${{ github.run_number }}* ``` ## Token Budget Guidelines diff --git a/.github/workflows/shared/ci-data-analysis.md b/.github/workflows/shared/ci-data-analysis.md index 458c5f462b7..b12638758fb 100644 --- a/.github/workflows/shared/ci-data-analysis.md +++ b/.github/workflows/shared/ci-data-analysis.md @@ -24,7 +24,7 @@ steps: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | # Download workflow runs for the ci workflow - gh run list --repo "$GITHUB_REPOSITORY" --workflow=ci.yml --limit 100 --json databaseId,status,conclusion,createdAt,updatedAt,displayTitle,headBranch,event,url,workflowDatabaseId,number > /tmp/ci-runs.json + gh run list --repo "$GITHUB_REPOSITORY" --workflow=ci.yml --limit 60 --json databaseId,status,conclusion,createdAt,updatedAt,displayTitle,headBranch,event,url,workflowDatabaseId,number > /tmp/ci-runs.json # Create directory for artifacts mkdir -p /tmp/ci-artifacts @@ -39,11 +39,25 @@ steps: echo "CI runs data saved to /tmp/ci-runs.json" echo "Artifacts saved to /tmp/ci-artifacts/" - # Summarize downloaded artifacts - echo "## Downloaded Artifacts" >> "$GITHUB_STEP_SUMMARY" - find /tmp/ci-artifacts -type f -name "*.txt" -o -name "*.html" -o -name "*.json" | head -20 | while read -r f; do - echo "- $(basename "$f")" >> "$GITHUB_STEP_SUMMARY" - done + - name: Build CI summary for optimization analysis + run: | + jq ' + def safe_duration: + if (.createdAt and .updatedAt) then + ((.updatedAt | fromdateiso8601) - (.createdAt | fromdateiso8601)) + else null end; + { + generated_at: now | todateiso8601, + total_runs: length, + status_counts: (group_by(.status) | map({status: .[0].status, count: length})), + conclusion_counts: (map(select(.conclusion != null)) | group_by(.conclusion) | map({conclusion: .[0].conclusion, count: length})), + branch_counts: (group_by(.headBranch) | map({branch: .[0].headBranch, count: length}) | sort_by(-.count) | .[0:10]), + avg_duration_seconds: ([.[] | safe_duration | select(. != null)] | if length > 0 then (add / length) else null end), + top_recent_failures: ([.[] | select(.conclusion == "failure" or .conclusion == "cancelled") | {id: .databaseId, run_number: .number, title: .displayTitle, branch: .headBranch, event: .event, url: .url, updated_at: .updatedAt}] | sort_by(.updated_at) | reverse | .[0:10]) + }' /tmp/ci-runs.json > /tmp/ci-summary.json + + echo "## CI Summary" >> "$GITHUB_STEP_SUMMARY" + jq -r '"- runs analyzed: \(.total_runs)\n- avg duration (sec): \(.avg_duration_seconds // "n/a")\n- recent failure records: \(.top_recent_failures | length)"' /tmp/ci-summary.json >> "$GITHUB_STEP_SUMMARY" - name: Setup Node.js uses: actions/setup-node@v6.3.0 @@ -93,20 +107,23 @@ Pre-downloaded CI run data and artifacts are available for analysis: ## Available Data 1. **CI Runs**: `/tmp/ci-runs.json` - - Last 100 workflow runs with status, timing, and metadata - -2. **Artifacts**: `/tmp/ci-artifacts/` + - Last 60 workflow runs with status, timing, and metadata + +2. **CI Summary**: `/tmp/ci-summary.json` + - Pre-computed totals, failure patterns, branch distribution, and average duration + +3. **Artifacts**: `/tmp/ci-artifacts/` - Coverage reports and benchmark results from recent successful runs - **Fuzz test results**: `*/fuzz-results/*.txt` - Output from fuzz tests - **Fuzz corpus data**: `*/fuzz-results/corpus/*` - Input corpus for each fuzz test -3. **CI Configuration**: `.github/workflows/ci.yml` +4. **CI Configuration**: `.github/workflows/ci.yml` - Current CI workflow configuration -4. **Cache Memory**: `/tmp/cache-memory/` +5. **Cache Memory**: `/tmp/cache-memory/` - Historical analysis data from previous runs -5. **Test Results**: `/tmp/gh-aw/test-results.json` +6. **Test Results**: `/tmp/gh-aw/test-results.json` - JSON output from Go unit tests with performance and timing data ## Test Case Locations @@ -133,7 +150,13 @@ This means you can: ## Analyzing Run Data -Parse the downloaded CI runs data: +Start with the pre-computed summary: + +```bash +cat /tmp/ci-summary.json | jq . +``` + +Only use raw run data for deeper validation: ```bash # Analyze run data diff --git a/.github/workflows/shared/ci-optimization-strategies.md b/.github/workflows/shared/ci-optimization-strategies.md index 77f57501d3f..280f813a1b3 100644 --- a/.github/workflows/shared/ci-optimization-strategies.md +++ b/.github/workflows/shared/ci-optimization-strategies.md @@ -42,52 +42,27 @@ cat .github/workflows/ci.yml ## Phase 2: Test Coverage Analysis -### Critical: Ensure ALL Tests are Executed +### Critical: Ensure ALL Tests are Executed (quick path) **Step 1: Get complete list of all tests** ```bash -# List all test functions in the repository go test -list='^Test' ./... 2>&1 | grep -E '^Test' > /tmp/all-tests.txt - -# Count total tests -TOTAL_TESTS=$(wc -l < /tmp/all-tests.txt) -echo "Total tests found: $TOTAL_TESTS" ``` -**Step 2: Analyze unit test coverage** +**Step 2: Analyze unit/integration split** ```bash -# Unit tests run all non-integration tests -# Verify the test job's command captures all non-integration tests -# Current: go test -v -parallel=8 -timeout=3m -tags '!integration' -run='^Test' ./... - -# Get list of integration tests (tests with integration build tag) grep -r "//go:build integration" --include="*_test.go" . | cut -d: -f1 | sort -u > /tmp/integration-test-files.txt - -# Estimate number of integration tests -echo "Files with integration tests:" -wc -l < /tmp/integration-test-files.txt ``` -**Step 3: Analyze integration test matrix coverage** +**Step 3: Analyze integration matrix coverage** ```bash -# The integration job has a matrix with specific patterns -# Each matrix entry targets specific packages and test patterns - -# CRITICAL CHECK: Are there tests that don't match ANY pattern? - -# Extract all integration test patterns from ci.yml cat .github/workflows/ci.yml | grep -A 2 'pattern:' | grep 'pattern:' > /tmp/matrix-patterns.txt - -# Check for catch-all groups cat .github/workflows/ci.yml | grep -B 2 'pattern: ""' | grep 'name:' > /tmp/catchall-groups.txt ``` **Step 4: Identify coverage gaps** -```bash -# Check if each package with tests is covered by at least one matrix group -# Compare packages with tests vs. packages in CI matrix -# Identify any "orphaned" tests not executed by any job -``` +- Compare test packages against matrix package patterns +- Flag orphaned tests not matched by any matrix rule **Required Action if Gaps Found:** If any tests are not covered by the CI matrix, propose adding: @@ -102,7 +77,7 @@ Example fix for missing catch-all (add to `.github/workflows/ci.yml`): pattern: "" # Empty pattern runs all remaining tests ``` -## Phase 3: Test Performance Optimization +## Phase 3: Test Performance Optimization (top 3 only) ### A. Test Splitting Analysis - Review current test matrix configuration @@ -118,20 +93,15 @@ Example fix for missing catch-all (add to `.github/workflows/ci.yml`): - Suggest path-based test filtering to skip irrelevant tests - Recommend running only affected tests for non-main branch pushes -### D. Test Timeout Optimization -- Review current timeout settings -- Check if timeouts are too conservative or too tight -- Suggest adjusting per-job timeouts based on historical data - -### E. Test Dependencies Analysis +### D. Test Dependencies Analysis - Examine test job dependencies - Suggest removing unnecessary dependencies to enable more parallelism -### F. Selective Test Execution +### E. Selective Test Execution - Suggest running expensive tests only on main branch or on-demand - Recommend running security scans conditionally -### G. Matrix Strategy Optimization +### F. Matrix Strategy Optimization - Analyze if all integration test matrix jobs are necessary - Check if some matrix jobs could be combined or run conditionally - Suggest reducing matrix size for PR builds vs. main branch builds From d73303945ecdadc126b26d6d17cfcaac83606acd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 20 Apr 2026 17:37:13 +0000 Subject: [PATCH 3/3] update ci-coach to analyze split ci workflows Agent-Logs-Url: https://github.com/github/gh-aw/sessions/9b3acc7d-c594-429e-abcf-8a33a2640408 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/ci-coach.lock.yml | 32 +++++++++---------- .github/workflows/ci-coach.md | 19 ++++++++--- .github/workflows/shared/ci-data-analysis.md | 25 ++++++++++----- .../shared/ci-optimization-strategies.md | 4 ++- 4 files changed, 50 insertions(+), 30 deletions(-) diff --git a/.github/workflows/ci-coach.lock.yml b/.github/workflows/ci-coach.lock.yml index 0453194643a..ec7b2b7684e 100644 --- a/.github/workflows/ci-coach.lock.yml +++ b/.github/workflows/ci-coach.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"19bc5e230212b21af230f066f6272be299e08305be643afb28cea83d0e7a26ba","strict":true,"agent_id":"copilot"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"87ef52d4045a4717505db1be172d02d8e8263433d50c75a27088775647fbc806","strict":true,"agent_id":"copilot"} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"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":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/setup-go","sha":"4a3601121dd01d1626a1e23e37211e3254c1c06c","version":"v6.4.0"},{"repo":"actions/setup-node","sha":"53b83947a5a98c8d113130e565377fae1a50d02f","version":"v6.3.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.25"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.25"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.25"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.25"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.2.25"},{"image":"ghcr.io/github/github-mcp-server:v1.0.0"},{"image":"node:lts-alpine","digest":"sha256:01743339035a5c3c11a373cd7c83aeab6ed1457b55da6a69e014a95ac4e4700b","pinned_image":"node:lts-alpine@sha256:01743339035a5c3c11a373cd7c83aeab6ed1457b55da6a69e014a95ac4e4700b"}]} # ___ _ _ # / _ \ | | (_) @@ -179,24 +179,24 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_ce21b547f02262d0_EOF' + cat << 'GH_AW_PROMPT_94a00665cb9be77b_EOF' - GH_AW_PROMPT_ce21b547f02262d0_EOF + GH_AW_PROMPT_94a00665cb9be77b_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" cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_ce21b547f02262d0_EOF' + cat << 'GH_AW_PROMPT_94a00665cb9be77b_EOF' Tools: create_pull_request, missing_tool, missing_data, noop - GH_AW_PROMPT_ce21b547f02262d0_EOF + GH_AW_PROMPT_94a00665cb9be77b_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_create_pull_request.md" - cat << 'GH_AW_PROMPT_ce21b547f02262d0_EOF' + cat << 'GH_AW_PROMPT_94a00665cb9be77b_EOF' - GH_AW_PROMPT_ce21b547f02262d0_EOF + GH_AW_PROMPT_94a00665cb9be77b_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_ce21b547f02262d0_EOF' + cat << 'GH_AW_PROMPT_94a00665cb9be77b_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -225,16 +225,16 @@ jobs: {{/if}} - GH_AW_PROMPT_ce21b547f02262d0_EOF + GH_AW_PROMPT_94a00665cb9be77b_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/cli_proxy_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_ce21b547f02262d0_EOF' + cat << 'GH_AW_PROMPT_94a00665cb9be77b_EOF' {{#runtime-import .github/workflows/shared/ci-data-analysis.md}} {{#runtime-import .github/workflows/shared/ci-optimization-strategies.md}} {{#runtime-import .github/workflows/shared/reporting.md}} {{#runtime-import .github/workflows/shared/jqschema.md}} {{#runtime-import .github/workflows/ci-coach.md}} - GH_AW_PROMPT_ce21b547f02262d0_EOF + GH_AW_PROMPT_94a00665cb9be77b_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 @@ -387,7 +387,7 @@ jobs: - env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} name: Download CI workflow runs from last 7 days - run: "# Download workflow runs for the ci workflow\ngh run list --repo \"$GITHUB_REPOSITORY\" --workflow=ci.yml --limit 60 --json databaseId,status,conclusion,createdAt,updatedAt,displayTitle,headBranch,event,url,workflowDatabaseId,number > /tmp/ci-runs.json\n\n# Create directory for artifacts\nmkdir -p /tmp/ci-artifacts\n\n# Download artifacts from recent runs (last 5 successful runs)\necho \"Downloading artifacts from recent CI runs...\"\ngh run list --repo \"$GITHUB_REPOSITORY\" --workflow=ci.yml --status success --limit 5 --json databaseId | jq -r '.[].databaseId' | while read -r run_id; do\n echo \"Processing run $run_id\"\n gh run download \"$run_id\" --repo \"$GITHUB_REPOSITORY\" --dir \"/tmp/ci-artifacts/$run_id\" 2>/dev/null || echo \"No artifacts for run $run_id\"\ndone\n\necho \"CI runs data saved to /tmp/ci-runs.json\"\necho \"Artifacts saved to /tmp/ci-artifacts/\"\n" + run: "# Download workflow runs for split CI workflows (ci, cgo, cjs)\ngh run list --repo \"$GITHUB_REPOSITORY\" --workflow=ci.yml --limit 30 --json databaseId,status,conclusion,createdAt,updatedAt,displayTitle,headBranch,event,url,workflowDatabaseId,number > /tmp/ci-runs-ci.json\ngh run list --repo \"$GITHUB_REPOSITORY\" --workflow=cgo.yml --limit 30 --json databaseId,status,conclusion,createdAt,updatedAt,displayTitle,headBranch,event,url,workflowDatabaseId,number > /tmp/ci-runs-cgo.json\ngh run list --repo \"$GITHUB_REPOSITORY\" --workflow=cjs.yml --limit 30 --json databaseId,status,conclusion,createdAt,updatedAt,displayTitle,headBranch,event,url,workflowDatabaseId,number > /tmp/ci-runs-cjs.json\njq -s 'add | sort_by(.createdAt) | reverse | .[0:60]' /tmp/ci-runs-ci.json /tmp/ci-runs-cgo.json /tmp/ci-runs-cjs.json > /tmp/ci-runs.json\n\n# Create directory for artifacts\nmkdir -p /tmp/ci-artifacts\n\n# Download artifacts from recent successful runs across split workflows\necho \"Downloading artifacts from recent CI/cgo/cjs runs...\"\n{\n gh run list --repo \"$GITHUB_REPOSITORY\" --workflow=ci.yml --status success --limit 2 --json databaseId\n gh run list --repo \"$GITHUB_REPOSITORY\" --workflow=cgo.yml --status success --limit 2 --json databaseId\n gh run list --repo \"$GITHUB_REPOSITORY\" --workflow=cjs.yml --status success --limit 2 --json databaseId\n} | jq -s 'add | .[].databaseId' -r | while read -r run_id; do\n echo \"Processing run $run_id\"\n gh run download \"$run_id\" --repo \"$GITHUB_REPOSITORY\" --dir \"/tmp/ci-artifacts/$run_id\" 2>/dev/null || echo \"No artifacts for run $run_id\"\ndone\n\necho \"CI runs data saved to /tmp/ci-runs.json\"\necho \"Artifacts saved to /tmp/ci-artifacts/\"\n" - name: Build CI summary for optimization analysis run: "jq '\ndef safe_duration:\n if (.createdAt and .updatedAt) then\n ((.updatedAt | fromdateiso8601) - (.createdAt | fromdateiso8601))\n else null end;\n{\n generated_at: now | todateiso8601,\n total_runs: length,\n status_counts: (group_by(.status) | map({status: .[0].status, count: length})),\n conclusion_counts: (map(select(.conclusion != null)) | group_by(.conclusion) | map({conclusion: .[0].conclusion, count: length})),\n branch_counts: (group_by(.headBranch) | map({branch: .[0].headBranch, count: length}) | sort_by(-.count) | .[0:10]),\n avg_duration_seconds: ([.[] | safe_duration | select(. != null)] | if length > 0 then (add / length) else null end),\n top_recent_failures: ([.[] | select(.conclusion == \"failure\" or .conclusion == \"cancelled\") | {id: .databaseId, run_number: .number, title: .displayTitle, branch: .headBranch, event: .event, url: .url, updated_at: .updatedAt}] | sort_by(.updated_at) | reverse | .[0:10])\n}' /tmp/ci-runs.json > /tmp/ci-summary.json\n\necho \"## CI Summary\" >> \"$GITHUB_STEP_SUMMARY\"\njq -r '\"- runs analyzed: \\(.total_runs)\\n- avg duration (sec): \\(.avg_duration_seconds // \"n/a\")\\n- recent failure records: \\(.top_recent_failures | length)\"' /tmp/ci-summary.json >> \"$GITHUB_STEP_SUMMARY\"\n" - name: Setup Go @@ -483,9 +483,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_455f9fde8d733299_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_cf6ad31dfdb35060_EOF' {"create_pull_request":{"expires":48,"max":1,"max_patch_size":1024,"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","AGENTS.md","CLAUDE.md","GEMINI.md"],"protected_files_policy":"fallback-to-issue","protected_path_prefixes":[".github/",".agents/"],"title_prefix":"[ci-coach] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_455f9fde8d733299_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_cf6ad31dfdb35060_EOF - name: Write Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -689,7 +689,7 @@ jobs: mkdir -p /home/runner/.copilot GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_0b5d46011b910f12_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_309bc2fefb7ad12f_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "safeoutputs": { @@ -714,7 +714,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_0b5d46011b910f12_EOF + GH_AW_MCP_CONFIG_309bc2fefb7ad12f_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true diff --git a/.github/workflows/ci-coach.md b/.github/workflows/ci-coach.md index 11a4e83b380..ac0c9ac0194 100644 --- a/.github/workflows/ci-coach.md +++ b/.github/workflows/ci-coach.md @@ -44,7 +44,10 @@ Analyze the CI workflow daily to identify concrete optimization opportunities th - **Repository**: ${{ github.repository }} - **Run Number**: #${{ github.run_number }} -- **Target Workflow**: `.github/workflows/ci.yml` +- **Target Workflows**: + - `.github/workflows/ci.yml` + - `.github/workflows/cgo.yml` + - `.github/workflows/cjs.yml` ## Data Available @@ -53,7 +56,10 @@ The `ci-data-analysis` shared module has pre-downloaded CI run data and built th 1. **CI Runs**: `/tmp/ci-runs.json` - Last 60 workflow runs 2. **CI Summary**: `/tmp/ci-summary.json` - Pre-computed failure patterns, duration stats, and top opportunities 3. **Artifacts**: `/tmp/ci-artifacts/` - Coverage reports, benchmarks, and **fuzz test results** -4. **CI Configuration**: `.github/workflows/ci.yml` - Current workflow +4. **CI Configuration**: + - `.github/workflows/ci.yml` + - `.github/workflows/cgo.yml` + - `.github/workflows/cjs.yml` 5. **Cache Memory**: `/tmp/cache-memory/` - Historical analysis data 6. **Test Results**: `/tmp/gh-aw/test-results.json` - Test performance data 7. **Fuzz Results**: `/tmp/ci-artifacts/*/fuzz-results/` - Fuzz test output and corpus data @@ -124,7 +130,10 @@ Prioritize optimizations with high impact, low risk, and low to medium effort. If you identify improvements worth implementing: -1. **Make focused changes** to `.github/workflows/ci.yml`: +1. **Make focused changes** to CI workflows as needed: + - `.github/workflows/ci.yml` + - `.github/workflows/cgo.yml` + - `.github/workflows/cjs.yml` - Use the `edit` tool to make precise modifications - Keep changes minimal and well-documented - Add comments explaining why changes improve efficiency @@ -256,8 +265,8 @@ The CI Coach workflow must NEVER alter test code (`*_test.go` files) in ways tha ## Success Criteria -✅ Analyzed CI workflow structure thoroughly -✅ Reviewed at least 100 recent workflow runs +✅ Analyzed CI workflow structure thoroughly (`ci.yml`, `cgo.yml`, `cjs.yml`) +✅ Reviewed recent workflow runs across split CI workflows ✅ Examined available artifacts and metrics ✅ Checked historical context from cache memory ✅ Identified concrete optimization opportunities OR confirmed CI is well-optimized diff --git a/.github/workflows/shared/ci-data-analysis.md b/.github/workflows/shared/ci-data-analysis.md index b12638758fb..c55d6d5f8c7 100644 --- a/.github/workflows/shared/ci-data-analysis.md +++ b/.github/workflows/shared/ci-data-analysis.md @@ -23,15 +23,22 @@ steps: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - # Download workflow runs for the ci workflow - gh run list --repo "$GITHUB_REPOSITORY" --workflow=ci.yml --limit 60 --json databaseId,status,conclusion,createdAt,updatedAt,displayTitle,headBranch,event,url,workflowDatabaseId,number > /tmp/ci-runs.json + # Download workflow runs for split CI workflows (ci, cgo, cjs) + gh run list --repo "$GITHUB_REPOSITORY" --workflow=ci.yml --limit 30 --json databaseId,status,conclusion,createdAt,updatedAt,displayTitle,headBranch,event,url,workflowDatabaseId,number > /tmp/ci-runs-ci.json + gh run list --repo "$GITHUB_REPOSITORY" --workflow=cgo.yml --limit 30 --json databaseId,status,conclusion,createdAt,updatedAt,displayTitle,headBranch,event,url,workflowDatabaseId,number > /tmp/ci-runs-cgo.json + gh run list --repo "$GITHUB_REPOSITORY" --workflow=cjs.yml --limit 30 --json databaseId,status,conclusion,createdAt,updatedAt,displayTitle,headBranch,event,url,workflowDatabaseId,number > /tmp/ci-runs-cjs.json + jq -s 'add | sort_by(.createdAt) | reverse | .[0:60]' /tmp/ci-runs-ci.json /tmp/ci-runs-cgo.json /tmp/ci-runs-cjs.json > /tmp/ci-runs.json # Create directory for artifacts mkdir -p /tmp/ci-artifacts - # Download artifacts from recent runs (last 5 successful runs) - echo "Downloading artifacts from recent CI runs..." - gh run list --repo "$GITHUB_REPOSITORY" --workflow=ci.yml --status success --limit 5 --json databaseId | jq -r '.[].databaseId' | while read -r run_id; do + # Download artifacts from recent successful runs across split workflows + echo "Downloading artifacts from recent CI/cgo/cjs runs..." + { + gh run list --repo "$GITHUB_REPOSITORY" --workflow=ci.yml --status success --limit 2 --json databaseId + gh run list --repo "$GITHUB_REPOSITORY" --workflow=cgo.yml --status success --limit 2 --json databaseId + gh run list --repo "$GITHUB_REPOSITORY" --workflow=cjs.yml --status success --limit 2 --json databaseId + } | jq -s 'add | .[].databaseId' -r | while read -r run_id; do echo "Processing run $run_id" gh run download "$run_id" --repo "$GITHUB_REPOSITORY" --dir "/tmp/ci-artifacts/$run_id" 2>/dev/null || echo "No artifacts for run $run_id" done @@ -107,7 +114,7 @@ Pre-downloaded CI run data and artifacts are available for analysis: ## Available Data 1. **CI Runs**: `/tmp/ci-runs.json` - - Last 60 workflow runs with status, timing, and metadata + - Last 60 workflow runs with status, timing, and metadata from `ci.yml`, `cgo.yml`, and `cjs.yml` 2. **CI Summary**: `/tmp/ci-summary.json` - Pre-computed totals, failure patterns, branch distribution, and average duration @@ -117,8 +124,10 @@ Pre-downloaded CI run data and artifacts are available for analysis: - **Fuzz test results**: `*/fuzz-results/*.txt` - Output from fuzz tests - **Fuzz corpus data**: `*/fuzz-results/corpus/*` - Input corpus for each fuzz test -4. **CI Configuration**: `.github/workflows/ci.yml` - - Current CI workflow configuration +4. **CI Configuration**: + - `.github/workflows/ci.yml` + - `.github/workflows/cgo.yml` + - `.github/workflows/cjs.yml` 5. **Cache Memory**: `/tmp/cache-memory/` - Historical analysis data from previous runs diff --git a/.github/workflows/shared/ci-optimization-strategies.md b/.github/workflows/shared/ci-optimization-strategies.md index 280f813a1b3..8f4449bcb26 100644 --- a/.github/workflows/shared/ci-optimization-strategies.md +++ b/.github/workflows/shared/ci-optimization-strategies.md @@ -21,8 +21,10 @@ Comprehensive strategies for analyzing CI workflows to identify optimization opp Read and understand the current CI workflow structure: ```bash -# Read the CI workflow configuration +# Read split CI workflow configurations cat .github/workflows/ci.yml +cat .github/workflows/cgo.yml +cat .github/workflows/cjs.yml # Understand the job structure # - lint (runs first)