From ce53b3950d0d0e9476ed8995f1bf106425c87b8c Mon Sep 17 00:00:00 2001 From: katriendg Date: Mon, 4 May 2026 18:31:51 +0000 Subject: [PATCH 1/9] refactor(agents): migrate dependabot AW review to workflow_run trigger MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Switch trigger from pull_request_target to workflow_run gated on PR Validation completion on main - Filter on workflow_run.actor.login == 'dependabot[bot]' (replacing pull_request_target bots:/roles: allowlists) - Hydrate PR_VALIDATION_CONCLUSION from workflow_run payload and PR_VALIDATION_FAILING_CHECKS via checks.listForRef - Tighten persona verdict rubric so non-success conclusions map to COMMENT with caution banner - Replace persona check-run API walk with resolver-supplied env vars - Regenerate aw-dependabot-pr-review.lock.yml 🤖 - Generated by Copilot Co-authored-by: Copilot --- .../agents/dependabot-pr-reviewer.agent.md | 82 +++--- .github/aw/actions-lock.json | 6 +- .../aw-dependabot-pr-review.lock.yml | 259 ++++++++++-------- .github/workflows/aw-dependabot-pr-review.md | 142 ++++++---- 4 files changed, 291 insertions(+), 198 deletions(-) diff --git a/.github/agents/dependabot-pr-reviewer.agent.md b/.github/agents/dependabot-pr-reviewer.agent.md index e31d0955..624f83df 100644 --- a/.github/agents/dependabot-pr-reviewer.agent.md +++ b/.github/agents/dependabot-pr-reviewer.agent.md @@ -93,21 +93,29 @@ Render the review body as markdown in this order: ## Validation Signal -The agent runs via `pull_request_target` and may execute BEFORE the -`PR Validation` orchestrator has completed. Treat the deterministic CI -conclusion as the canonical validation signal when it is available, and as -`pending` otherwise. Do not invoke `uv`, `pytest`, `npm ci`, `terraform`, -or `go` from the bash tool — those binaries live on the host runner and -are not visible inside the AWF firewall sandbox. +The agent runs via `workflow_run` AFTER the `PR Validation` orchestrator +has reached a terminal conclusion. The deterministic CI signal is therefore +always final — there is no `pending` or `in_progress:*` state to handle. +Do not invoke `uv`, `pytest`, `npm ci`, `terraform`, or `go` from the bash +tool — those binaries live on the host runner and are not visible inside +the AWF firewall sandbox. The orchestrator's overall conclusion is injected into the prompt as -`PR_VALIDATION_CONCLUSION` (one of `pending`, `in_progress:`, -`success`, `failure`, `cancelled`, `neutral`, `skipped`, `timed_out`, -`action_required`, or `unknown`). Map the touched surfaces to the -per-job check runs below and read each conclusion via the `github` MCP -`pull_requests` toolset (or `GET /repos/{owner}/{repo}/commits/{sha}/check-runs`). - -### Surface to Check Run Map +`PR_VALIDATION_CONCLUSION` (one of `success`, `failure`, `cancelled`, +`timed_out`, `neutral`, `skipped`, `action_required`, or `unknown`). +The list of failing per-surface check-runs (JSON array of +`{name, html_url, conclusion}`) is injected as `PR_VALIDATION_FAILING_CHECKS`. +Read both directly from the environment. Do NOT call +`checks.listForRef` or `GET /repos/{owner}/{repo}/commits/{sha}/check-runs` +— the workflow's resolver step already did that work. + +### Reference: Surface to Check Run Naming + +Informational reference for interpreting entries in +`PR_VALIDATION_FAILING_CHECKS`. The persona does NOT walk this map via the +checks API — the workflow's resolver step already enumerated failing +check-runs server-side. Use this table only to map a failing check name +back to the dependency surface it covers when composing the review body. | Surface | Authoritative check runs | | --- | --- | @@ -156,10 +164,10 @@ Include a `### Validation Signal` block in the per-package section of the review body with three parts: 1. **Deterministic CI:** quote the orchestrator conclusion as - `PR Validation: ` followed by a bullet list of the relevant - per-surface check runs from the map above with name, conclusion, and - `html_url`. When `conclusion != success`, list the failing job names - first. + `PR Validation: ` followed by a bullet list rendered from + `PR_VALIDATION_FAILING_CHECKS` (entries are `{name, html_url, conclusion}`). + When `conclusion != success`, list every failing entry. When + `conclusion == success`, state "all per-surface check-runs passed". 2. **Static impact reasoning:** one or two sentences citing the static checks above. Always include the Isaac Sim ABI line when `training/rl/requirements.txt` is in the diff, even on minor bumps. @@ -167,28 +175,34 @@ review body with three parts: violation, peer-dep conflict, breaking-changelog quote), prepend `⚠️ Maintainer review recommended` to the top of the review body once. -If the orchestrator conclusion is unavailable or still in progress -(`pending`, `in_progress:*`, or `unknown`; PR resolution failed; or the -check-runs API returns empty), state: -`⚠️ Deterministic CI conclusion not yet available; verdict is advisory only.` -and keep the verdict at `COMMENT`. +If `PR_VALIDATION_CONCLUSION` is `neutral`, `skipped`, or `unknown`, or if +`PR_DEPENDABOT_SKIP_REASON == 'pr-resolution-failed'`, prepend the caution +banner described in Verdict Adjustment and keep the verdict at `COMMENT`. ### Verdict Adjustment -* `PR_VALIDATION_CONCLUSION == success` AND every relevant per-surface check - is `success` AND no static check raises a concern → verdict MAY upgrade +Map every terminal conclusion explicitly. Under `workflow_run`, +`PR_VALIDATION_CONCLUSION` is always final — there are no `pending` or +`in_progress:*` branches to consider. + +* `PR_VALIDATION_CONCLUSION == success` AND no static check raises a + concern AND no sticky high-risk trigger fires → verdict MAY upgrade from `COMMENT` to `APPROVE`. Rationale must reference the orchestrator - conclusion plus the green per-surface checks by name. -* `PR_VALIDATION_CONCLUSION` is `failure`, `cancelled`, or `timed_out` → - verdict stays at `COMMENT`. Body MUST quote each failing per-surface - check name plus its `html_url`. Do NOT skip enrichment — maintainers rely - on the advisory output to triage which package in a grouped PR caused - the failure. -* `PR_VALIDATION_CONCLUSION` is `neutral`, `skipped`, `action_required`, - `pending`, `in_progress:*`, or `unknown` → verdict stays at `COMMENT`; - body explains the inconclusive or pending state. + conclusion plus a green `PR_VALIDATION_FAILING_CHECKS` (empty array). +* `PR_VALIDATION_CONCLUSION ∈ {failure, cancelled, timed_out, action_required}` + → verdict stays at `COMMENT`. Body MUST quote each entry from + `PR_VALIDATION_FAILING_CHECKS` (`name` plus `html_url`). Do NOT skip + enrichment — maintainers rely on the advisory output to triage which + package in a grouped PR caused the failure. +* `PR_VALIDATION_CONCLUSION ∈ {neutral, skipped, unknown}` OR + `PR_DEPENDABOT_SKIP_REASON == 'pr-resolution-failed'` → verdict stays + at `COMMENT`. Prepend the banner + `> [!CAUTION]` + `> Deterministic CI signal unavailable (\`{conclusion}\`); review is advisory only.` + to the top of the review body. * The Isaac Sim ABI guard is sticky: a `numpy` 2.x bump keeps the verdict - at `COMMENT` and forces the high-risk banner regardless of CI conclusion. + at `COMMENT` and forces the `⚠️ Maintainer review recommended` banner + regardless of CI conclusion. ## Forbidden Actions diff --git a/.github/aw/actions-lock.json b/.github/aw/actions-lock.json index 73df5e9d..c365a499 100644 --- a/.github/aw/actions-lock.json +++ b/.github/aw/actions-lock.json @@ -5,10 +5,10 @@ "version": "v9", "sha": "373c709c69115d41ff229c7e5df9f8788daa9553" }, - "github/gh-aw-actions/setup@v0.68.3": { + "github/gh-aw-actions/setup@v0.71.1": { "repo": "github/gh-aw-actions/setup", - "version": "v0.68.3", - "sha": "ba90f2186d7ad780ec640f364005fa24e797b360" + "version": "v0.71.1", + "sha": "239aec45b78c8799417efdd5bc6d8cc036629ec1" } } } diff --git a/.github/workflows/aw-dependabot-pr-review.lock.yml b/.github/workflows/aw-dependabot-pr-review.lock.yml index 03c50d9e..4c95e914 100644 --- a/.github/workflows/aw-dependabot-pr-review.lock.yml +++ b/.github/workflows/aw-dependabot-pr-review.lock.yml @@ -1,5 +1,5 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"46234d20433a81ce7491f5c6933eb4c75977de922d188a0253fa2392eff22580","compiler_version":"v0.68.3","strict":true,"agent_id":"copilot"} -# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"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/setup-python","sha":"a309ff8b426b58ec0e2a45f0f869d46889d02405","version":"v6.2.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"astral-sh/setup-uv","sha":"cec208311dfd045dd5311c1add060b2062131d57","version":"v8.0.0"},{"repo":"github/gh-aw-actions/setup","sha":"ba90f2186d7ad780ec640f364005fa24e797b360","version":"v0.68.3"},{"repo":"hashicorp/setup-terraform","sha":"5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85","version":"5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85"},{"repo":"terraform-linters/setup-tflint","sha":"b480b8fcdaa6f2c577f8e4fa799e89e756bb7c93","version":"b480b8fcdaa6f2c577f8e4fa799e89e756bb7c93"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.20"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.2.19"},{"image":"ghcr.io/github/github-mcp-server:v0.32.0"},{"image":"node:lts-alpine"}]} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"d765a65cb8fc977b55c35f02f3cd521ced75eb0169404d93ceeea0a3296d72db","compiler_version":"v0.71.1","strict":true,"agent_id":"copilot"} +# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"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":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/setup-python","sha":"a309ff8b426b58ec0e2a45f0f869d46889d02405","version":"v6.2.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"astral-sh/setup-uv","sha":"08807647e7069bb48b6ef5acd8ec9567f424441b","version":"v8.1.0"},{"repo":"github/gh-aw-actions/setup","sha":"239aec45b78c8799417efdd5bc6d8cc036629ec1","version":"v0.71.1"},{"repo":"hashicorp/setup-terraform","sha":"5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85","version":"5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85"},{"repo":"terraform-linters/setup-tflint","sha":"b480b8fcdaa6f2c577f8e4fa799e89e756bb7c93","version":"b480b8fcdaa6f2c577f8e4fa799e89e756bb7c93"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.28","digest":"sha256:a8834e285807654bf680154faa710d43fe4365a0868142f5c20e48c85e137a7a","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.28@sha256:a8834e285807654bf680154faa710d43fe4365a0868142f5c20e48c85e137a7a"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.28","digest":"sha256:93290f2393752252911bd7c39a047f776c0b53063575e7bde4e304962a9a61cb","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.28@sha256:93290f2393752252911bd7c39a047f776c0b53063575e7bde4e304962a9a61cb"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.28","digest":"sha256:844c18280f82cd1b06345eb2f4e91966b34185bfc51c9f237c3e022e848fb474","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.28@sha256:844c18280f82cd1b06345eb2f4e91966b34185bfc51c9f237c3e022e848fb474"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.0"},{"image":"ghcr.io/github/github-mcp-server:v1.0.2"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) # | |_| | __ _ ___ _ __ | |_ _ ___ @@ -14,7 +14,7 @@ # \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ # \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ # -# This file was automatically generated by gh-aw (v0.68.3). DO NOT EDIT. +# This file was automatically generated by gh-aw (v0.71.1). DO NOT EDIT. # # To update this file, edit the corresponding .md file and run: # gh aw compile @@ -37,73 +37,72 @@ # Custom actions used: # - actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 # - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 -# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 +# - actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 # - actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 # - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 # - actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 # - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 # - astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 -# - github/gh-aw-actions/setup@abea67e08ee83539ea33aaae67bf0cddaa0b03b5 # v0.68.3 +# - github/gh-aw-actions/setup@239aec45b78c8799417efdd5bc6d8cc036629ec1 # v0.71.1 # - hashicorp/setup-terraform@5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85 # 5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85 # - terraform-linters/setup-tflint@b480b8fcdaa6f2c577f8e4fa799e89e756bb7c93 # b480b8fcdaa6f2c577f8e4fa799e89e756bb7c93 # # Container images used: -# - ghcr.io/github/gh-aw-firewall/agent:0.25.20 -# - ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20 -# - ghcr.io/github/gh-aw-firewall/squid:0.25.20 -# - ghcr.io/github/gh-aw-mcpg:v0.2.19 -# - ghcr.io/github/github-mcp-server:v0.32.0 -# - node:lts-alpine +# - ghcr.io/github/gh-aw-firewall/agent:0.25.28@sha256:a8834e285807654bf680154faa710d43fe4365a0868142f5c20e48c85e137a7a +# - ghcr.io/github/gh-aw-firewall/api-proxy:0.25.28@sha256:93290f2393752252911bd7c39a047f776c0b53063575e7bde4e304962a9a61cb +# - ghcr.io/github/gh-aw-firewall/squid:0.25.28@sha256:844c18280f82cd1b06345eb2f4e91966b34185bfc51c9f237c3e022e848fb474 +# - ghcr.io/github/gh-aw-mcpg:v0.3.0 +# - ghcr.io/github/github-mcp-server:v1.0.2 +# - node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f name: "AW Dependabot PR Review" "on": # bots: # Bots processed as bot check in pre-activation job # - dependabot[bot] # Bots processed as bot check in pre-activation job - pull_request_target: - branches: - - main - types: - - opened - - synchronize - - reopened # roles: # Roles processed as role check in pre-activation job # - admin # Roles processed as role check in pre-activation job # - maintainer # Roles processed as role check in pre-activation job # - write # Roles processed as role check in pre-activation job + workflow_run: + # zizmor: ignore[dangerous-triggers] - workflow_run trigger is secured with role and fork validation + branches: + - main + types: + - completed + workflows: + - PR Validation permissions: {} concurrency: - group: "gh-aw-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref || github.run_id }}" - cancel-in-progress: true + group: "gh-aw-${{ github.workflow }}" run-name: "AW Dependabot PR Review" jobs: activation: needs: pre_activation + # zizmor: ignore[dangerous-triggers] - workflow_run trigger is secured with role and fork validation if: > - needs.pre_activation.outputs.activated == 'true' && (github.event.pull_request != null && startsWith(github.event.pull_request.head.ref, 'dependabot/') && - github.event.pull_request.user.login == 'dependabot[bot]' && !github.event.pull_request.draft) + (needs.pre_activation.outputs.activated == 'true' && (github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.actor.login == 'dependabot[bot]' && contains(fromJSON('["success","failure","cancelled","timed_out","neutral","skipped","action_required"]'), + github.event.workflow_run.conclusion))) && (github.event_name != 'workflow_run' || github.event.workflow_run.repository.id == github.repository_id && (!(github.event.workflow_run.repository.fork))) runs-on: ubuntu-slim permissions: actions: read contents: read outputs: - body: ${{ steps.sanitized.outputs.body }} comment_id: "" comment_repo: "" + engine_id: ${{ steps.generate_aw_info.outputs.engine_id }} lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }} model: ${{ steps.generate_aw_info.outputs.model }} secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} setup-trace-id: ${{ steps.setup.outputs.trace-id }} stale_lock_file_failed: ${{ steps.check-lock-file.outputs.stale_lock_file_failed == 'true' }} - text: ${{ steps.sanitized.outputs.text }} - title: ${{ steps.sanitized.outputs.title }} steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@abea67e08ee83539ea33aaae67bf0cddaa0b03b5 # v0.68.3 + uses: github/gh-aw-actions/setup@239aec45b78c8799417efdd5bc6d8cc036629ec1 # v0.71.1 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} @@ -114,20 +113,20 @@ jobs: GH_AW_INFO_ENGINE_ID: "copilot" GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI" GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || 'auto' }} - GH_AW_INFO_VERSION: "1.0.21" - GH_AW_INFO_AGENT_VERSION: "1.0.21" - GH_AW_INFO_CLI_VERSION: "v0.68.3" + GH_AW_INFO_VERSION: "1.0.35" + GH_AW_INFO_AGENT_VERSION: "1.0.35" + GH_AW_INFO_CLI_VERSION: "v0.71.1" GH_AW_INFO_WORKFLOW_NAME: "AW Dependabot PR Review" GH_AW_INFO_EXPERIMENTAL: "false" GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" GH_AW_INFO_STAGED: "false" GH_AW_INFO_ALLOWED_DOMAINS: '["defaults","github","python","node","go","terraform","containers","api.osv.dev","services.nvd.nist.gov"]' GH_AW_INFO_FIREWALL_ENABLED: "true" - GH_AW_INFO_AWF_VERSION: "v0.25.20" + GH_AW_INFO_AWF_VERSION: "v0.25.28" GH_AW_INFO_AWMG_VERSION: "" GH_AW_INFO_FIREWALL_TYPE: "squid" GH_AW_COMPILED_STRICT: "true" - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -146,11 +145,22 @@ jobs: sparse-checkout: | .github .agents + .claude + .codex + .crush + .gemini + .opencode sparse-checkout-cone-mode: true fetch-depth: 1 + - name: Save agent config folders for base branch restoration + env: + GH_AW_AGENT_FOLDERS: ".agents .claude .codex .crush .gemini .github .opencode" + GH_AW_AGENT_FILES: ".crush.json AGENTS.md CLAUDE.md GEMINI.md opencode.jsonc" + # poutine:ignore untrusted_checkout_exec + run: bash "${RUNNER_TEMP}/gh-aw/actions/save_base_github_folders.sh" - name: Check workflow lock file id: check-lock-file - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 env: GH_AW_WORKFLOW_FILE: "aw-dependabot-pr-review.lock.yml" GH_AW_CONTEXT_WORKFLOW_REF: "${{ github.workflow_ref }}" @@ -161,26 +171,15 @@ jobs: const { main } = require('${{ runner.temp }}/gh-aw/actions/check_workflow_timestamp_api.cjs'); await main(); - name: Check compile-agentic version - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 env: - GH_AW_COMPILED_VERSION: "v0.68.3" + GH_AW_COMPILED_VERSION: "v0.71.1" with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require('${{ runner.temp }}/gh-aw/actions/check_version_updates.cjs'); await main(); - - name: Compute current body text - id: sanitized - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 - env: - GH_AW_ALLOWED_BOTS: "dependabot[bot]" - with: - script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/compute_text.cjs'); - await main(); - name: Create prompt with built-in context env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt @@ -197,14 +196,14 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_5734b58a8c868ede_EOF' + cat << 'GH_AW_PROMPT_a3ef5c02f19e834e_EOF' - GH_AW_PROMPT_5734b58a8c868ede_EOF + GH_AW_PROMPT_a3ef5c02f19e834e_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/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_5734b58a8c868ede_EOF' + cat << 'GH_AW_PROMPT_a3ef5c02f19e834e_EOF' Tools: add_comment(max:2), create_pull_request_review_comment(max:5), submit_pull_request_review, missing_tool, missing_data, noop @@ -236,16 +235,16 @@ jobs: {{/if}} - GH_AW_PROMPT_5734b58a8c868ede_EOF + GH_AW_PROMPT_a3ef5c02f19e834e_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_5734b58a8c868ede_EOF' + cat << 'GH_AW_PROMPT_a3ef5c02f19e834e_EOF' {{#runtime-import .github/agents/dependabot-pr-reviewer.agent.md}} {{#runtime-import .github/workflows/aw-dependabot-pr-review.md}} - GH_AW_PROMPT_5734b58a8c868ede_EOF + GH_AW_PROMPT_a3ef5c02f19e834e_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt with: @@ -255,7 +254,7 @@ jobs: const { main } = require('${{ runner.temp }}/gh-aw/actions/interpolate_prompt.cjs'); await main(); - name: Substitute placeholders - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_GITHUB_ACTOR: ${{ github.actor }} @@ -308,6 +307,7 @@ jobs: /tmp/gh-aw/aw_info.json /tmp/gh-aw/aw-prompts/prompt.txt /tmp/gh-aw/github_rate_limits.jsonl + /tmp/gh-aw/base if-no-files-found: ignore retention-days: 1 @@ -316,8 +316,11 @@ jobs: runs-on: ubuntu-latest permissions: actions: read + checks: read contents: read pull-requests: read + concurrency: + group: "gh-aw-copilot-${{ github.workflow }}" env: DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} GH_AW_ASSETS_ALLOWED_EXTS: "" @@ -340,7 +343,7 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@abea67e08ee83539ea33aaae67bf0cddaa0b03b5 # v0.68.3 + uses: github/gh-aw-actions/setup@239aec45b78c8799417efdd5bc6d8cc036629ec1 # v0.71.1 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} @@ -358,7 +361,7 @@ jobs: with: persist-credentials: false - name: Merge remote .github folder - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 env: GH_AW_AGENT_FILE: ".github/agents/dependabot-pr-reviewer.agent.md" GH_AW_AGENT_IMPORT_SPEC: "../agents/dependabot-pr-reviewer.agent.md" @@ -411,10 +414,10 @@ jobs: with: tflint_version: latest - id: resolve-pr - name: Resolve Dependabot PR context and fetch PR Validation status - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + name: Resolve Dependabot PR context from workflow_run + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 with: - script: "const pr = context.payload.pull_request;\nif (!pr) {\n core.setFailed('pull_request payload missing');\n return;\n}\nif (pr.user.login !== 'dependabot[bot]') {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'not-dependabot');\n return;\n}\nif (pr.draft) {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'draft');\n return;\n}\ncore.exportVariable('PR_NUMBER', String(pr.number));\ncore.exportVariable('PR_TITLE', pr.title);\ncore.exportVariable('PR_HEAD_REF', pr.head.ref);\ncore.exportVariable('PR_BASE_REF', pr.base.ref);\ncore.exportVariable('PR_AUTHOR', pr.user.login);\ncore.exportVariable('PR_HEAD_SHA', pr.head.sha);\n\n// Look up the most recent PR Validation workflow run for this head SHA.\n// It may still be in progress when pull_request_target fires.\nlet conclusion = 'pending';\nlet runUrl = '';\ntry {\n const { data } = await github.rest.actions.listWorkflowRunsForRepo({\n owner: context.repo.owner,\n repo: context.repo.repo,\n head_sha: pr.head.sha,\n event: 'pull_request',\n per_page: 30,\n });\n const validation = (data.workflow_runs || []).find(r => r.name === 'PR Validation');\n if (validation) {\n runUrl = validation.html_url || '';\n conclusion = validation.status === 'completed'\n ? (validation.conclusion || 'unknown')\n : `in_progress:${validation.status}`;\n }\n} catch (err) {\n core.warning(`Failed to look up PR Validation run: ${err.message}`);\n}\ncore.exportVariable('PR_VALIDATION_CONCLUSION', conclusion);\ncore.exportVariable('PR_VALIDATION_RUN_URL', runUrl);\ncore.info(`Resolved PR #${pr.number} (${pr.title}); PR Validation conclusion: ${conclusion}`);\n" + script: "const run = context.payload.workflow_run;\nif (!run) {\n core.setFailed('workflow_run payload missing');\n return;\n}\nif (run.event !== 'pull_request') {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'not-a-pr-run');\n return;\n}\n\nlet pr = (run.pull_requests || [])[0];\nif (!pr) {\n // Fork PRs do not appear in workflow_run.pull_requests; fall back to search.\n const q = `repo:${context.repo.owner}/${context.repo.repo} is:pr sha:${run.head_sha}`;\n const { data } = await github.rest.search.issuesAndPullRequests({ q });\n const hit = (data.items || [])[0];\n if (!hit) {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'pr-resolution-failed');\n return;\n }\n const { data: full } = await github.rest.pulls.get({\n owner: context.repo.owner,\n repo: context.repo.repo,\n pull_number: hit.number,\n });\n pr = full;\n} else {\n // Hydrate the full PR object so fields like `body` and `draft` are reliable.\n const { data: full } = await github.rest.pulls.get({\n owner: context.repo.owner,\n repo: context.repo.repo,\n pull_number: pr.number,\n });\n pr = full;\n}\n\nif (pr.user.login !== 'dependabot[bot]') {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'not-dependabot');\n return;\n}\nif (pr.draft) {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'draft');\n return;\n}\n\ncore.exportVariable('PR_NUMBER', String(pr.number));\ncore.exportVariable('PR_TITLE', pr.title);\ncore.exportVariable('PR_HEAD_REF', pr.head.ref);\ncore.exportVariable('PR_BASE_REF', pr.base.ref);\ncore.exportVariable('PR_AUTHOR', pr.user.login);\ncore.exportVariable('PR_HEAD_SHA', pr.head.sha);\n\n// PR Validation conclusion comes directly from the triggering workflow_run payload;\n// it is always final under `types: [completed]`.\ncore.exportVariable('PR_VALIDATION_CONCLUSION', run.conclusion || 'unknown');\ncore.exportVariable('PR_VALIDATION_RUN_URL', run.html_url || '');\n\n// Resolve per-surface check-runs ONCE here so the persona does not re-walk them.\nlet failing = [];\ntry {\n const { data: checks } = await github.rest.checks.listForRef({\n owner: context.repo.owner,\n repo: context.repo.repo,\n ref: pr.head.sha,\n per_page: 100,\n });\n failing = (checks.check_runs || [])\n .filter(c => c.status === 'completed'\n && !['success', 'neutral', 'skipped'].includes(c.conclusion))\n .map(c => ({ name: c.name, html_url: c.html_url, conclusion: c.conclusion }));\n} catch (err) {\n core.warning(`Failed to enumerate check-runs: ${err.message}`);\n}\ncore.exportVariable('PR_VALIDATION_FAILING_CHECKS', JSON.stringify(failing));\n\n// Hydrate Dependabot enrichment input from REST so the agent does not depend on\n// the integrity-filtered MCP read of the PR body.\ncore.exportVariable('PR_BODY', pr.body || '');\n\ncore.info(`Resolved PR #${pr.number} (${pr.title}); PR Validation conclusion: ${run.conclusion}; failing checks: ${failing.length}`);\n" - name: Configure Git credentials env: @@ -433,7 +436,7 @@ jobs: id: checkout-pr if: | github.event.pull_request || github.event.issue.pull_request - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 env: GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} with: @@ -444,14 +447,14 @@ jobs: const { main } = require('${{ runner.temp }}/gh-aw/actions/checkout_pr_branch.cjs'); await main(); - name: Install GitHub Copilot CLI - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.21 + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.35 env: GH_HOST: github.com - name: Install AWF binary - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.20 + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.28 - name: Determine automatic lockdown mode for GitHub MCP Server id: determine-automatic-lockdown - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 env: GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} @@ -459,22 +462,33 @@ jobs: script: | const determineAutomaticLockdown = require('${{ runner.temp }}/gh-aw/actions/determine_automatic_lockdown.cjs'); await determineAutomaticLockdown(github, context, core); + - name: Download activation artifact + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: activation + path: /tmp/gh-aw + - name: Restore agent config folders from base branch + if: steps.checkout-pr.outcome == 'success' + env: + GH_AW_AGENT_FOLDERS: ".agents .claude .codex .crush .gemini .github .opencode" + GH_AW_AGENT_FILES: ".crush.json AGENTS.md CLAUDE.md GEMINI.md opencode.jsonc" + run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_base_github_folders.sh" - name: Download container images - run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.20 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20 ghcr.io/github/gh-aw-firewall/squid:0.25.20 ghcr.io/github/gh-aw-mcpg:v0.2.19 ghcr.io/github/github-mcp-server:v0.32.0 node:lts-alpine + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.28@sha256:a8834e285807654bf680154faa710d43fe4365a0868142f5c20e48c85e137a7a ghcr.io/github/gh-aw-firewall/api-proxy:0.25.28@sha256:93290f2393752252911bd7c39a047f776c0b53063575e7bde4e304962a9a61cb ghcr.io/github/gh-aw-firewall/squid:0.25.28@sha256:844c18280f82cd1b06345eb2f4e91966b34185bfc51c9f237c3e022e848fb474 ghcr.io/github/gh-aw-mcpg:v0.3.0 ghcr.io/github/github-mcp-server:v1.0.2 node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f - 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_a6000a4bbc0dff64_EOF' - {"add_comment":{"max":2,"target":"triggering"},"create_pull_request_review_comment":{"max":5,"side":"RIGHT"},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{},"submit_pull_request_review":{"max":1}} - GH_AW_SAFE_OUTPUTS_CONFIG_a6000a4bbc0dff64_EOF + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_c4c98d11a3160b0e_EOF' + {"add_comment":{"max":2,"target":"${{ env.PR_NUMBER }}"},"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"},"report_incomplete":{},"submit_pull_request_review":{"max":1,"target":"${{ env.PR_NUMBER }}"}} + GH_AW_SAFE_OUTPUTS_CONFIG_c4c98d11a3160b0e_EOF - name: Write Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | { "description_suffixes": { - "add_comment": " CONSTRAINTS: Maximum 2 comment(s) can be added. Target: triggering. Supports reply_to_id for discussion threading.", + "add_comment": " CONSTRAINTS: Maximum 2 comment(s) can be added. Target: ${{ env.PR_NUMBER }}. Supports reply_to_id for discussion threading.", "create_pull_request_review_comment": " CONSTRAINTS: Maximum 5 review comment(s) can be created. Comments will be on the RIGHT side of the diff.", "submit_pull_request_review": " CONSTRAINTS: Maximum 1 review(s) can be submitted." }, @@ -634,7 +648,7 @@ jobs: } } } - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -692,10 +706,10 @@ jobs: 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 /tmp/gh-aw/mcp-config + mkdir -p "${RUNNER_TEMP}/gh-aw/mcp-config" # Export gateway environment variables for MCP config and gateway script - export MCP_GATEWAY_PORT="80" + export MCP_GATEWAY_PORT="8080" export MCP_GATEWAY_DOMAIN="host.docker.internal" MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') echo "::add-mask::${MCP_GATEWAY_API_KEY}" @@ -706,15 +720,19 @@ jobs: export DEBUG="*" export GH_AW_ENGINE="copilot" - export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.2.19' + MCP_GATEWAY_UID=$(id -u 2>/dev/null || echo '0') + MCP_GATEWAY_GID=$(id -g 2>/dev/null || echo '0') + DOCKER_SOCK_GID=$(stat -c '%g' /var/run/docker.sock 2>/dev/null || echo '0') + export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -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.0' mkdir -p /home/runner/.copilot - cat << GH_AW_MCP_CONFIG_658c528aa9fae3bb_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" + GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) + cat << GH_AW_MCP_CONFIG_dee3a570647104f0_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "github": { "type": "stdio", - "container": "ghcr.io/github/github-mcp-server:v0.32.0", + "container": "ghcr.io/github/github-mcp-server:v1.0.2", "env": { "GITHUB_HOST": "\${GITHUB_SERVER_URL}", "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", @@ -750,12 +768,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_658c528aa9fae3bb_EOF - - name: Download activation artifact - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: activation - path: /tmp/gh-aw + GH_AW_MCP_CONFIG_dee3a570647104f0_EOF - name: Clean git credentials continue-on-error: true run: bash "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh" @@ -791,21 +804,25 @@ jobs: run: | set -o pipefail touch /tmp/gh-aw/agent-step-summary.md + GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true) + 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 '*.docker.com,*.docker.io,*.githubusercontent.com,*.pythonhosted.org,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.osv.dev,api.snapcraft.io,apt.releases.hashicorp.com,archive.ubuntu.com,auth.docker.io,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,cdn.jsdelivr.net,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,dl.k8s.io,docs.github.com,esm.sh,files.pythonhosted.org,gcr.io,get.pnpm.io,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,mcr.microsoft.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,objects.githubusercontent.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,pip.pypa.io,pkg.go.dev,pkgs.k8s.io,ppa.launchpad.net,production.cloudflare.docker.com,proxy.golang.org,pypi.org,pypi.python.org,quay.io,raw.githubusercontent.com,registry.bower.io,registry.hub.docker.com,registry.npmjs.com,registry.npmjs.org,registry.terraform.io,registry.yarnpkg.com,releases.hashicorp.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,s.symcb.com,s.symcd.com,security.ubuntu.com,services.nvd.nist.gov,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com,www.npmjs.com,www.npmjs.org,yarnpkg.com,yum.releases.hashicorp.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --image-tag 0.25.20 --skip-pull --enable-api-proxy \ - -- /bin/bash -c 'node ${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-tool github --allow-tool safeoutputs --allow-tool '\''shell(cat **/*.json)'\'' --allow-tool '\''shell(cat **/*.tf)'\'' --allow-tool '\''shell(cat **/*.toml)'\'' --allow-tool '\''shell(cat **/go.mod)'\'' --allow-tool '\''shell(cat training/rl/requirements.txt)'\'' --allow-tool '\''shell(cat training/rl/scripts/train.sh)'\'' --allow-tool '\''shell(cat)'\'' --allow-tool '\''shell(date)'\'' --allow-tool '\''shell(echo)'\'' --allow-tool '\''shell(grep -R --line-number * -- :!node_modules :!.venv :!external)'\'' --allow-tool '\''shell(grep)'\'' --allow-tool '\''shell(head)'\'' --allow-tool '\''shell(jq . **/*.json)'\'' --allow-tool '\''shell(ls)'\'' --allow-tool '\''shell(npm view *)'\'' --allow-tool '\''shell(pwd)'\'' --allow-tool '\''shell(sort)'\'' --allow-tool '\''shell(tail)'\'' --allow-tool '\''shell(uniq)'\'' --allow-tool '\''shell(wc)'\'' --allow-tool '\''shell(yq)'\'' --allow-tool web_fetch --allow-tool write --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + 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 '*.docker.com,*.docker.io,*.githubusercontent.com,*.pythonhosted.org,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.osv.dev,api.snapcraft.io,apt.releases.hashicorp.com,archive.ubuntu.com,auth.docker.io,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,cdn.jsdelivr.net,codeload.github.com,conda.anaconda.org,conda.binstar.org,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,deb.nodesource.com,deno.land,dl.k8s.io,docs.github.com,esm.sh,files.pythonhosted.org,gcr.io,get.pnpm.io,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,mcr.microsoft.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,objects.githubusercontent.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,pip.pypa.io,pkg.go.dev,pkgs.k8s.io,ppa.launchpad.net,production.cloudflare.docker.com,proxy.golang.org,pypi.org,pypi.python.org,quay.io,raw.githubusercontent.com,registry.bower.io,registry.hub.docker.com,registry.npmjs.com,registry.npmjs.org,registry.terraform.io,registry.yarnpkg.com,releases.hashicorp.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,s.symcb.com,s.symcd.com,security.ubuntu.com,services.nvd.nist.gov,skimdb.npmjs.com,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com,www.npmjs.com,www.npmjs.org,yarnpkg.com,yum.releases.hashicorp.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.28,squid=sha256:844c18280f82cd1b06345eb2f4e91966b34185bfc51c9f237c3e022e848fb474,agent=sha256:a8834e285807654bf680154faa710d43fe4365a0868142f5c20e48c85e137a7a,api-proxy=sha256:93290f2393752252911bd7c39a047f776c0b53063575e7bde4e304962a9a61cb,cli-proxy=sha256:fdf310e4678ce58d248c466b89399e9680a3003038fd19322c388559016aaac7 --skip-pull --enable-api-proxy \ + -- /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-tool github --allow-tool safeoutputs --allow-tool '\''shell(cat **/*.json)'\'' --allow-tool '\''shell(cat **/*.tf)'\'' --allow-tool '\''shell(cat **/*.toml)'\'' --allow-tool '\''shell(cat **/go.mod)'\'' --allow-tool '\''shell(cat training/rl/requirements.txt)'\'' --allow-tool '\''shell(cat training/rl/scripts/train.sh)'\'' --allow-tool '\''shell(cat)'\'' --allow-tool '\''shell(date)'\'' --allow-tool '\''shell(echo)'\'' --allow-tool '\''shell(grep -R --line-number * -- :!node_modules :!.venv :!external)'\'' --allow-tool '\''shell(grep)'\'' --allow-tool '\''shell(head)'\'' --allow-tool '\''shell(jq . **/*.json)'\'' --allow-tool '\''shell(ls)'\'' --allow-tool '\''shell(npm view *)'\'' --allow-tool '\''shell(pwd)'\'' --allow-tool '\''shell(sort)'\'' --allow-tool '\''shell(tail)'\'' --allow-tool '\''shell(uniq)'\'' --allow-tool '\''shell(wc)'\'' --allow-tool '\''shell(yq)'\'' --allow-tool web_fetch --allow-tool write --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 + COPILOT_API_KEY: dummy-byok-key-for-offline-mode COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - COPILOT_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || '' }} + COPILOT_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || 'claude-sonnet-4.6' }} GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PHASE: agent 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: v0.68.3 + GH_AW_VERSION: v0.71.1 GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true + GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -850,7 +867,7 @@ jobs: bash "${RUNNER_TEMP}/gh-aw/actions/stop_mcp_gateway.sh" "$GATEWAY_PID" - name: Redact secrets in logs if: always() - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -876,10 +893,10 @@ jobs: - name: Ingest agent output id: collect_output if: always() - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 env: GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} - GH_AW_ALLOWED_DOMAINS: "*.docker.com,*.docker.io,*.githubusercontent.com,*.pythonhosted.org,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.osv.dev,api.snapcraft.io,apt.releases.hashicorp.com,archive.ubuntu.com,auth.docker.io,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,cdn.jsdelivr.net,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,dl.k8s.io,docs.github.com,esm.sh,files.pythonhosted.org,gcr.io,get.pnpm.io,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,mcr.microsoft.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,objects.githubusercontent.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,pip.pypa.io,pkg.go.dev,pkgs.k8s.io,ppa.launchpad.net,production.cloudflare.docker.com,proxy.golang.org,pypi.org,pypi.python.org,quay.io,raw.githubusercontent.com,registry.bower.io,registry.hub.docker.com,registry.npmjs.com,registry.npmjs.org,registry.terraform.io,registry.yarnpkg.com,releases.hashicorp.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,s.symcb.com,s.symcd.com,security.ubuntu.com,services.nvd.nist.gov,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com,www.npmjs.com,www.npmjs.org,yarnpkg.com,yum.releases.hashicorp.com" + GH_AW_ALLOWED_DOMAINS: "*.docker.com,*.docker.io,*.githubusercontent.com,*.pythonhosted.org,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.osv.dev,api.snapcraft.io,apt.releases.hashicorp.com,archive.ubuntu.com,auth.docker.io,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,cdn.jsdelivr.net,codeload.github.com,conda.anaconda.org,conda.binstar.org,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,deb.nodesource.com,deno.land,dl.k8s.io,docs.github.com,esm.sh,files.pythonhosted.org,gcr.io,get.pnpm.io,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,mcr.microsoft.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,objects.githubusercontent.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,pip.pypa.io,pkg.go.dev,pkgs.k8s.io,ppa.launchpad.net,production.cloudflare.docker.com,proxy.golang.org,pypi.org,pypi.python.org,quay.io,raw.githubusercontent.com,registry.bower.io,registry.hub.docker.com,registry.npmjs.com,registry.npmjs.org,registry.terraform.io,registry.yarnpkg.com,releases.hashicorp.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,s.symcb.com,s.symcd.com,security.ubuntu.com,services.nvd.nist.gov,skimdb.npmjs.com,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com,www.npmjs.com,www.npmjs.org,yarnpkg.com,yum.releases.hashicorp.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} with: @@ -890,7 +907,7 @@ jobs: await main(); - name: Parse agent logs for step summary if: always() - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 env: GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ with: @@ -902,7 +919,7 @@ jobs: - name: Parse MCP Gateway logs for step summary if: always() id: parse-mcp-gateway - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -915,9 +932,9 @@ jobs: env: AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs run: | - # Fix permissions on firewall logs so they can be uploaded as artifacts + # Fix permissions on firewall logs/audit dirs so they can be uploaded as artifacts # AWF runs with sudo, creating files owned by root - sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true + sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall 2>/dev/null || true # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step) if command -v awf &> /dev/null; then awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" @@ -927,7 +944,7 @@ jobs: - name: Parse token usage for step summary if: always() continue-on-error: true - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -989,7 +1006,7 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@abea67e08ee83539ea33aaae67bf0cddaa0b03b5 # v0.68.3 + uses: github/gh-aw-actions/setup@239aec45b78c8799417efdd5bc6d8cc036629ec1 # v0.71.1 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} @@ -1010,7 +1027,7 @@ jobs: echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" - name: Process no-op messages id: noop - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_NOOP_MAX: "1" @@ -1027,7 +1044,7 @@ jobs: await main(); - name: Log detection run id: detection_runs - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_WORKFLOW_NAME: "AW Dependabot PR Review" @@ -1043,7 +1060,7 @@ jobs: await main(); - name: Record missing tool id: missing_tool - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_MISSING_TOOL_CREATE_ISSUE: "true" @@ -1057,7 +1074,7 @@ jobs: await main(); - name: Record incomplete id: report_incomplete - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_REPORT_INCOMPLETE_CREATE_ISSUE: "true" @@ -1072,13 +1089,14 @@ jobs: - name: Handle agent failure id: handle_agent_failure if: always() - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_WORKFLOW_NAME: "AW Dependabot PR Review" GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} GH_AW_WORKFLOW_ID: "aw-dependabot-pr-review" + GH_AW_ACTION_FAILURE_ISSUE_EXPIRES_HOURS: "168" GH_AW_ENGINE_ID: "copilot" GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.activation.outputs.secret_verification_result }} GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} @@ -1115,7 +1133,7 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@abea67e08ee83539ea33aaae67bf0cddaa0b03b5 # v0.68.3 + uses: github/gh-aw-actions/setup@239aec45b78c8799417efdd5bc6d8cc036629ec1 # v0.71.1 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} @@ -1145,7 +1163,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.20 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20 ghcr.io/github/gh-aw-firewall/squid:0.25.20 + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.28@sha256:a8834e285807654bf680154faa710d43fe4365a0868142f5c20e48c85e137a7a ghcr.io/github/gh-aw-firewall/api-proxy:0.25.28@sha256:93290f2393752252911bd7c39a047f776c0b53063575e7bde4e304962a9a61cb ghcr.io/github/gh-aw-firewall/squid:0.25.28@sha256:844c18280f82cd1b06345eb2f4e91966b34185bfc51c9f237c3e022e848fb474 - name: Check if detection needed id: detection_guard if: always() @@ -1163,7 +1181,7 @@ jobs: - name: Clear MCP configuration for detection if: always() && steps.detection_guard.outputs.run_detection == 'true' run: | - rm -f /tmp/gh-aw/mcp-config/mcp-servers.json + rm -f "${RUNNER_TEMP}/gh-aw/mcp-config/mcp-servers.json" rm -f /home/runner/.copilot/mcp-config.json rm -f "$GITHUB_WORKSPACE/.gemini/settings.json" - name: Prepare threat detection files @@ -1182,7 +1200,7 @@ jobs: ls -la /tmp/gh-aw/threat-detection/ 2>/dev/null || true - name: Setup threat detection if: always() && steps.detection_guard.outputs.run_detection == 'true' - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 env: WORKFLOW_NAME: "AW Dependabot PR Review" WORKFLOW_DESCRIPTION: "Advisory agentic review of Dependabot dependency update PRs for physical-ai-toolchain" @@ -1198,12 +1216,17 @@ jobs: run: | mkdir -p /tmp/gh-aw/threat-detection touch /tmp/gh-aw/threat-detection/detection.log + - name: Setup Node.js + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version: '24' + package-manager-cache: false - name: Install GitHub Copilot CLI - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.21 + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.35 env: GH_HOST: github.com - name: Install AWF binary - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.20 + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.28 - name: Execute GitHub Copilot CLI if: always() && steps.detection_guard.outputs.run_detection == 'true' id: detection_agentic_execution @@ -1212,19 +1235,23 @@ jobs: run: | set -o pipefail touch /tmp/gh-aw/agent-step-summary.md + GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true) + 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 --image-tag 0.25.20 --skip-pull --enable-api-proxy \ - -- /bin/bash -c 'node ${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 "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log + 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.28,squid=sha256:844c18280f82cd1b06345eb2f4e91966b34185bfc51c9f237c3e022e848fb474,agent=sha256:a8834e285807654bf680154faa710d43fe4365a0868142f5c20e48c85e137a7a,api-proxy=sha256:93290f2393752252911bd7c39a047f776c0b53063575e7bde4e304962a9a61cb,cli-proxy=sha256:fdf310e4678ce58d248c466b89399e9680a3003038fd19322c388559016aaac7 --skip-pull --enable-api-proxy \ + -- /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 + COPILOT_API_KEY: dummy-byok-key-for-offline-mode COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - COPILOT_MODEL: ${{ vars.GH_AW_MODEL_DETECTION_COPILOT || '' }} + COPILOT_MODEL: ${{ vars.GH_AW_MODEL_DETECTION_COPILOT || 'claude-sonnet-4.6' }} GH_AW_PHASE: detection GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_VERSION: v0.68.3 + GH_AW_VERSION: v0.71.1 GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true + GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} GITHUB_SERVER_URL: ${{ github.server_url }} @@ -1245,7 +1272,7 @@ jobs: - name: Parse and conclude threat detection id: detection_conclusion if: always() - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 env: RUN_DETECTION: ${{ steps.detection_guard.outputs.run_detection }} GH_AW_DETECTION_CONTINUE_ON_ERROR: "true" @@ -1258,7 +1285,8 @@ jobs: pre_activation: if: > - github.event.pull_request != null && startsWith(github.event.pull_request.head.ref, 'dependabot/') && github.event.pull_request.user.login == 'dependabot[bot]' && !github.event.pull_request.draft + github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.actor.login == 'dependabot[bot]' && contains(fromJSON('["success","failure","cancelled","timed_out","neutral","skipped","action_required"]'), + github.event.workflow_run.conclusion) runs-on: ubuntu-slim outputs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} @@ -1267,13 +1295,13 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@abea67e08ee83539ea33aaae67bf0cddaa0b03b5 # v0.68.3 + uses: github/gh-aw-actions/setup@239aec45b78c8799417efdd5bc6d8cc036629ec1 # v0.71.1 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} - name: Check team membership for workflow id: check_membership - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 env: GH_AW_REQUIRED_ROLES: "admin,maintainer,write" GH_AW_ALLOWED_BOTS: "dependabot[bot]" @@ -1305,6 +1333,7 @@ jobs: GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }} GH_AW_ENGINE_ID: "copilot" GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }} + GH_AW_ENGINE_VERSION: "1.0.35" GH_AW_WORKFLOW_ID: "aw-dependabot-pr-review" GH_AW_WORKFLOW_NAME: "AW Dependabot PR Review" outputs: @@ -1319,7 +1348,7 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@abea67e08ee83539ea33aaae67bf0cddaa0b03b5 # v0.68.3 + uses: github/gh-aw-actions/setup@239aec45b78c8799417efdd5bc6d8cc036629ec1 # v0.71.1 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} @@ -1349,13 +1378,13 @@ jobs: echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV" - name: Process Safe Outputs id: process_safe_outputs - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} - GH_AW_ALLOWED_DOMAINS: "*.docker.com,*.docker.io,*.githubusercontent.com,*.pythonhosted.org,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.osv.dev,api.snapcraft.io,apt.releases.hashicorp.com,archive.ubuntu.com,auth.docker.io,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,cdn.jsdelivr.net,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,dl.k8s.io,docs.github.com,esm.sh,files.pythonhosted.org,gcr.io,get.pnpm.io,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,mcr.microsoft.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,objects.githubusercontent.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,pip.pypa.io,pkg.go.dev,pkgs.k8s.io,ppa.launchpad.net,production.cloudflare.docker.com,proxy.golang.org,pypi.org,pypi.python.org,quay.io,raw.githubusercontent.com,registry.bower.io,registry.hub.docker.com,registry.npmjs.com,registry.npmjs.org,registry.terraform.io,registry.yarnpkg.com,releases.hashicorp.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,s.symcb.com,s.symcd.com,security.ubuntu.com,services.nvd.nist.gov,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com,www.npmjs.com,www.npmjs.org,yarnpkg.com,yum.releases.hashicorp.com" + GH_AW_ALLOWED_DOMAINS: "*.docker.com,*.docker.io,*.githubusercontent.com,*.pythonhosted.org,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.osv.dev,api.snapcraft.io,apt.releases.hashicorp.com,archive.ubuntu.com,auth.docker.io,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,cdn.jsdelivr.net,codeload.github.com,conda.anaconda.org,conda.binstar.org,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,deb.nodesource.com,deno.land,dl.k8s.io,docs.github.com,esm.sh,files.pythonhosted.org,gcr.io,get.pnpm.io,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,mcr.microsoft.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,objects.githubusercontent.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,pip.pypa.io,pkg.go.dev,pkgs.k8s.io,ppa.launchpad.net,production.cloudflare.docker.com,proxy.golang.org,pypi.org,pypi.python.org,quay.io,raw.githubusercontent.com,registry.bower.io,registry.hub.docker.com,registry.npmjs.com,registry.npmjs.org,registry.terraform.io,registry.yarnpkg.com,releases.hashicorp.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,s.symcb.com,s.symcd.com,security.ubuntu.com,services.nvd.nist.gov,skimdb.npmjs.com,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com,www.npmjs.com,www.npmjs.org,yarnpkg.com,yum.releases.hashicorp.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":2,\"target\":\"triggering\"},\"create_pull_request_review_comment\":{\"max\":5,\"side\":\"RIGHT\"},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{},\"submit_pull_request_review\":{\"max\":1}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":2,\"target\":\"${{ env.PR_NUMBER }}\"},\"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\"},\"report_incomplete\":{},\"submit_pull_request_review\":{\"max\":1,\"target\":\"${{ env.PR_NUMBER }}\"}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/aw-dependabot-pr-review.md b/.github/workflows/aw-dependabot-pr-review.md index d9b7f701..c123c24d 100644 --- a/.github/workflows/aw-dependabot-pr-review.md +++ b/.github/workflows/aw-dependabot-pr-review.md @@ -4,21 +4,22 @@ description: Advisory agentic review of Dependabot dependency update PRs for phy engine: copilot timeout-minutes: 15 if: > - github.event.pull_request != null && - startsWith(github.event.pull_request.head.ref, 'dependabot/') && - github.event.pull_request.user.login == 'dependabot[bot]' && - !github.event.pull_request.draft + github.event.workflow_run.event == 'pull_request' && + github.event.workflow_run.actor.login == 'dependabot[bot]' && + contains(fromJSON('["success","failure","cancelled","timed_out","neutral","skipped","action_required"]'), + github.event.workflow_run.conclusion) on: - pull_request_target: - types: [opened, synchronize, reopened] - branches: - - main + workflow_run: + workflows: ["PR Validation"] + types: [completed] + branches: [main] bots: ["dependabot[bot]"] roles: [admin, maintainer, write] permissions: contents: read pull-requests: read actions: read + checks: read network: allowed: - defaults @@ -64,16 +65,47 @@ steps: uses: terraform-linters/setup-tflint@b480b8fcdaa6f2c577f8e4fa799e89e756bb7c93 # v6.2.2 with: tflint_version: latest - - name: Resolve Dependabot PR context and fetch PR Validation status + - name: Resolve Dependabot PR context from workflow_run id: resolve-pr uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9.0.0 with: script: | - const pr = context.payload.pull_request; - if (!pr) { - core.setFailed('pull_request payload missing'); + const run = context.payload.workflow_run; + if (!run) { + core.setFailed('workflow_run payload missing'); + return; + } + if (run.event !== 'pull_request') { + core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'not-a-pr-run'); return; } + + let pr = (run.pull_requests || [])[0]; + if (!pr) { + // Fork PRs do not appear in workflow_run.pull_requests; fall back to search. + const q = `repo:${context.repo.owner}/${context.repo.repo} is:pr sha:${run.head_sha}`; + const { data } = await github.rest.search.issuesAndPullRequests({ q }); + const hit = (data.items || [])[0]; + if (!hit) { + core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'pr-resolution-failed'); + return; + } + const { data: full } = await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: hit.number, + }); + pr = full; + } else { + // Hydrate the full PR object so fields like `body` and `draft` are reliable. + const { data: full } = await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: pr.number, + }); + pr = full; + } + if (pr.user.login !== 'dependabot[bot]') { core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'not-dependabot'); return; @@ -82,6 +114,7 @@ steps: core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'draft'); return; } + core.exportVariable('PR_NUMBER', String(pr.number)); core.exportVariable('PR_TITLE', pr.title); core.exportVariable('PR_HEAD_REF', pr.head.ref); @@ -89,31 +122,34 @@ steps: core.exportVariable('PR_AUTHOR', pr.user.login); core.exportVariable('PR_HEAD_SHA', pr.head.sha); - // Look up the most recent PR Validation workflow run for this head SHA. - // It may still be in progress when pull_request_target fires. - let conclusion = 'pending'; - let runUrl = ''; + // PR Validation conclusion comes directly from the triggering workflow_run payload; + // it is always final under `types: [completed]`. + core.exportVariable('PR_VALIDATION_CONCLUSION', run.conclusion || 'unknown'); + core.exportVariable('PR_VALIDATION_RUN_URL', run.html_url || ''); + + // Resolve per-surface check-runs ONCE here so the persona does not re-walk them. + let failing = []; try { - const { data } = await github.rest.actions.listWorkflowRunsForRepo({ + const { data: checks } = await github.rest.checks.listForRef({ owner: context.repo.owner, repo: context.repo.repo, - head_sha: pr.head.sha, - event: 'pull_request', - per_page: 30, + ref: pr.head.sha, + per_page: 100, }); - const validation = (data.workflow_runs || []).find(r => r.name === 'PR Validation'); - if (validation) { - runUrl = validation.html_url || ''; - conclusion = validation.status === 'completed' - ? (validation.conclusion || 'unknown') - : `in_progress:${validation.status}`; - } + failing = (checks.check_runs || []) + .filter(c => c.status === 'completed' + && !['success', 'neutral', 'skipped'].includes(c.conclusion)) + .map(c => ({ name: c.name, html_url: c.html_url, conclusion: c.conclusion })); } catch (err) { - core.warning(`Failed to look up PR Validation run: ${err.message}`); + core.warning(`Failed to enumerate check-runs: ${err.message}`); } - core.exportVariable('PR_VALIDATION_CONCLUSION', conclusion); - core.exportVariable('PR_VALIDATION_RUN_URL', runUrl); - core.info(`Resolved PR #${pr.number} (${pr.title}); PR Validation conclusion: ${conclusion}`); + core.exportVariable('PR_VALIDATION_FAILING_CHECKS', JSON.stringify(failing)); + + // Hydrate Dependabot enrichment input from REST so the agent does not depend on + // the integrity-filtered MCP read of the PR body. + core.exportVariable('PR_BODY', pr.body || ''); + + core.info(`Resolved PR #${pr.number} (${pr.title}); PR Validation conclusion: ${run.conclusion}; failing checks: ${failing.length}`); tools: github: toolsets: [context, repos, pull_requests] @@ -131,11 +167,13 @@ tools: safe-outputs: create-pull-request-review-comment: max: 5 + target: "*" submit-pull-request-review: max: 1 + target: ${{ env.PR_NUMBER }} add-comment: max: 2 - target: triggering + target: ${{ env.PR_NUMBER }} noop: max: 1 imports: @@ -148,20 +186,32 @@ Advisory-only review of Dependabot-authored pull requests in microsoft/physical- ## Trigger Posture -This workflow runs via `pull_request_target` on Dependabot PRs targeting `main` (head branch matching `dependabot/**`). -It executes in the base-repository context so safe-output handlers receive a real `github.event.pull_request` payload -and can post inline review comments and a single submitted review. The `PR Validation` orchestrator runs in parallel — -its conclusion is queried at runtime by the resolver step and may be `pending` if the orchestrator has not finished yet. -The agent must never attempt to run validation tooling (`uv`, `pytest`, `npm ci`, `terraform`, `go`) from the bash tool -because those binaries are not visible inside the AWF firewall sandbox. +This workflow runs via `workflow_run` after the `PR Validation` orchestrator completes on `main` for a +`pull_request` event. Because `workflow_run` evaluates the workflow file from the default branch, the +agent step always uses the trusted, merged definition rather than fork content. The gh-aw compiler +auto-injects fork-PR exclusion and a `repository.id` guard into the lock file. The workflow-level +`if:` short-circuits any non-PR triggering event, any PR not authored by `dependabot[bot]` (gated on +`workflow_run.actor.login`), and any non-terminal conclusion before the resolver runs. The resolver then +reads the orchestrator's terminal conclusion directly from `context.payload.workflow_run.conclusion`, +which under `types: [completed]` is always one of `success`, `failure`, `cancelled`, `timed_out`, +`neutral`, `skipped`, or `action_required`. + +The resolver step exports `PR Validation`'s final conclusion directly from +`context.payload.workflow_run.conclusion` (no separate `listWorkflowRunsForRepo` call), then enumerates +per-surface check-runs once via `checks.listForRef` so the agent never has to walk the checks API itself. +The `checks: read` permission grants exactly that scope and nothing more. The agent must never attempt +to run validation tooling (`uv`, `pytest`, `npm ci`, `terraform`, `go`) from the bash tool because those +binaries are not visible inside the AWF firewall sandbox. The resolver step exports these environment variables for the agent to read: * `PR_NUMBER` — the Dependabot PR number under review * `PR_TITLE`, `PR_HEAD_REF`, `PR_BASE_REF`, `PR_AUTHOR`, `PR_HEAD_SHA` -* `PR_VALIDATION_CONCLUSION` — `pending`, `in_progress:`, `success`, `failure`, `cancelled`, `neutral`, `skipped`, `timed_out`, `action_required`, or `unknown` -* `PR_VALIDATION_RUN_URL` — direct link to the `PR Validation` run, or empty when no run exists yet -* `PR_DEPENDABOT_SKIP_REASON` (optional) — set when the resolver determined the trigger should be skipped (`not-dependabot`, `draft`) +* `PR_VALIDATION_CONCLUSION` — final terminal conclusion: `success`, `failure`, `cancelled`, `timed_out`, `neutral`, `skipped`, `action_required`, or `unknown` +* `PR_VALIDATION_RUN_URL` — direct link to the `PR Validation` run +* `PR_VALIDATION_FAILING_CHECKS` — JSON array of `{name, html_url, conclusion}` for non-success/non-neutral/non-skipped check-runs on `PR_HEAD_SHA` +* `PR_BODY` — the PR body, hydrated server-side so enrichment does not depend on the integrity-filtered MCP read +* `PR_DEPENDABOT_SKIP_REASON` (optional) — set when the resolver determined the trigger should be skipped (`not-a-pr-run`, `pr-resolution-failed`, `not-dependabot`, `draft`) When `PR_DEPENDABOT_SKIP_REASON` is set, emit a `noop` with the reason as the rationale and stop. @@ -185,13 +235,13 @@ The full reviewer persona, risk rubric, ecosystem-specific checks, and enrichmen ## Step-by-Step -1. **Resolve context.** Read `PR_NUMBER`, `PR_HEAD_SHA`, `PR_VALIDATION_CONCLUSION`, and `PR_VALIDATION_RUN_URL` from the environment. If `PR_DEPENDABOT_SKIP_REASON` is set, emit `noop` and stop. -2. **Read CI signal.** Use the `github` MCP `pull_requests` toolset (or `GET /repos/{owner}/{repo}/commits/{sha}/check-runs`) on `PR_HEAD_SHA` to enumerate per-surface check-run conclusions. Map them through the surface table in the persona. -3. **Parse.** Read the pull request title, body, and file diff. Extract package name, ecosystem, old/new versions, `GHSA-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}` and `CVE-\d{4}-\d{4,7}` identifiers from the Dependabot body. +1. **Resolve context.** Read `PR_NUMBER`, `PR_HEAD_SHA`, `PR_VALIDATION_CONCLUSION`, `PR_VALIDATION_RUN_URL`, `PR_VALIDATION_FAILING_CHECKS`, and `PR_BODY` from the environment. If `PR_DEPENDABOT_SKIP_REASON` is set, emit `noop` and stop. +2. **Read CI signal.** Treat `PR_VALIDATION_CONCLUSION` as the final, non-stale conclusion. Parse `PR_VALIDATION_FAILING_CHECKS` (JSON) for the list of failing per-surface check-runs. Do NOT call `checks.listForRef` or `commits/{sha}/check-runs` — the resolver already did. +3. **Parse.** Read `PR_BODY` plus the file diff. Extract package name, ecosystem, old/new versions, `GHSA-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}` and `CVE-\d{4}-\d{4,7}` identifiers from the Dependabot body. 4. **Enrich.** Query GHSA (preferred), fall back to OSV (`api.osv.dev`) and NVD (`services.nvd.nist.gov`) for severity, affected ranges, and fixed versions. Fetch release notes or changelog via the relevant package registry (npm, PyPI, Go module proxy, Terraform registry). 5. **Classify.** Apply the persona's per-surface rubric. Flag ABI-sensitive pins (for example `numpy >=1.26.0,<2.0.0` in Isaac Sim training), pre-1.0 bumps, major version jumps, and missing upstream advisories. -6. **Review.** Post up to five inline `create-pull-request-review-comment` entries for specific risks, up to two `add-comment` status updates on the triggering PR, and exactly one `submit-pull-request-review` with `APPROVE` or `COMMENT`. - When `PR_VALIDATION_CONCLUSION` is anything other than `success`, the verdict MUST be `COMMENT` and the body MUST quote the failing per-surface check-run names plus their `html_url`. +6. **Review.** Post up to five inline `create-pull-request-review-comment` entries for specific risks, up to two `add-comment` status updates on the resolved PR, and exactly one `submit-pull-request-review` with `APPROVE` or `COMMENT`. + When `PR_VALIDATION_CONCLUSION` is anything other than `success`, the verdict MUST be `COMMENT` and the body MUST quote each entry from `PR_VALIDATION_FAILING_CHECKS` (`name` plus `html_url`). Never skip enrichment on red CI — maintainers rely on advisory output to triage which package in a grouped PR caused the failure. Keep comments factual and concise. Cite the advisory identifier, affected versions, and the Dependabot PR URL. From db20d20214f31e45a0cad3622ba7678c641022cc Mon Sep 17 00:00:00 2001 From: katriendg Date: Tue, 5 May 2026 06:16:47 +0000 Subject: [PATCH 2/9] chore(workflows): update Dependabot PR review triggers to match dependabot branches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - change workflow_run branches from main to dependabot/** - clarify workflow execution context for Dependabot PRs 🔧 - Generated by Copilot --- .../aw-dependabot-pr-review.lock.yml | 24 +++++++++---------- .github/workflows/aw-dependabot-pr-review.md | 9 ++++--- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/.github/workflows/aw-dependabot-pr-review.lock.yml b/.github/workflows/aw-dependabot-pr-review.lock.yml index 4c95e914..9dd70610 100644 --- a/.github/workflows/aw-dependabot-pr-review.lock.yml +++ b/.github/workflows/aw-dependabot-pr-review.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"d765a65cb8fc977b55c35f02f3cd521ced75eb0169404d93ceeea0a3296d72db","compiler_version":"v0.71.1","strict":true,"agent_id":"copilot"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"0f5fea32ec1f48ddaadf3f6a3f03489c94e534b6586c836609faf06143f65b84","compiler_version":"v0.71.1","strict":true,"agent_id":"copilot"} # gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"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":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/setup-python","sha":"a309ff8b426b58ec0e2a45f0f869d46889d02405","version":"v6.2.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"astral-sh/setup-uv","sha":"08807647e7069bb48b6ef5acd8ec9567f424441b","version":"v8.1.0"},{"repo":"github/gh-aw-actions/setup","sha":"239aec45b78c8799417efdd5bc6d8cc036629ec1","version":"v0.71.1"},{"repo":"hashicorp/setup-terraform","sha":"5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85","version":"5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85"},{"repo":"terraform-linters/setup-tflint","sha":"b480b8fcdaa6f2c577f8e4fa799e89e756bb7c93","version":"b480b8fcdaa6f2c577f8e4fa799e89e756bb7c93"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.28","digest":"sha256:a8834e285807654bf680154faa710d43fe4365a0868142f5c20e48c85e137a7a","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.28@sha256:a8834e285807654bf680154faa710d43fe4365a0868142f5c20e48c85e137a7a"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.28","digest":"sha256:93290f2393752252911bd7c39a047f776c0b53063575e7bde4e304962a9a61cb","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.28@sha256:93290f2393752252911bd7c39a047f776c0b53063575e7bde4e304962a9a61cb"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.28","digest":"sha256:844c18280f82cd1b06345eb2f4e91966b34185bfc51c9f237c3e022e848fb474","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.28@sha256:844c18280f82cd1b06345eb2f4e91966b34185bfc51c9f237c3e022e848fb474"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.0"},{"image":"ghcr.io/github/github-mcp-server:v1.0.2"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -66,7 +66,7 @@ name: "AW Dependabot PR Review" workflow_run: # zizmor: ignore[dangerous-triggers] - workflow_run trigger is secured with role and fork validation branches: - - main + - dependabot/** types: - completed workflows: @@ -196,14 +196,14 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_a3ef5c02f19e834e_EOF' + cat << 'GH_AW_PROMPT_01d946cee57ecd3c_EOF' - GH_AW_PROMPT_a3ef5c02f19e834e_EOF + GH_AW_PROMPT_01d946cee57ecd3c_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/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_a3ef5c02f19e834e_EOF' + cat << 'GH_AW_PROMPT_01d946cee57ecd3c_EOF' Tools: add_comment(max:2), create_pull_request_review_comment(max:5), submit_pull_request_review, missing_tool, missing_data, noop @@ -235,13 +235,13 @@ jobs: {{/if}} - GH_AW_PROMPT_a3ef5c02f19e834e_EOF + GH_AW_PROMPT_01d946cee57ecd3c_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_a3ef5c02f19e834e_EOF' + cat << 'GH_AW_PROMPT_01d946cee57ecd3c_EOF' {{#runtime-import .github/agents/dependabot-pr-reviewer.agent.md}} {{#runtime-import .github/workflows/aw-dependabot-pr-review.md}} - GH_AW_PROMPT_a3ef5c02f19e834e_EOF + GH_AW_PROMPT_01d946cee57ecd3c_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 @@ -480,9 +480,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_c4c98d11a3160b0e_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_cdf8fd249694c33c_EOF' {"add_comment":{"max":2,"target":"${{ env.PR_NUMBER }}"},"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"},"report_incomplete":{},"submit_pull_request_review":{"max":1,"target":"${{ env.PR_NUMBER }}"}} - GH_AW_SAFE_OUTPUTS_CONFIG_c4c98d11a3160b0e_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_cdf8fd249694c33c_EOF - name: Write Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -727,7 +727,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_dee3a570647104f0_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_da05e78b12a00655_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "github": { @@ -768,7 +768,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_dee3a570647104f0_EOF + GH_AW_MCP_CONFIG_da05e78b12a00655_EOF - name: Clean git credentials continue-on-error: true run: bash "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh" diff --git a/.github/workflows/aw-dependabot-pr-review.md b/.github/workflows/aw-dependabot-pr-review.md index c123c24d..441af081 100644 --- a/.github/workflows/aw-dependabot-pr-review.md +++ b/.github/workflows/aw-dependabot-pr-review.md @@ -12,7 +12,7 @@ on: workflow_run: workflows: ["PR Validation"] types: [completed] - branches: [main] + branches: ["dependabot/**"] bots: ["dependabot[bot]"] roles: [admin, maintainer, write] permissions: @@ -186,8 +186,11 @@ Advisory-only review of Dependabot-authored pull requests in microsoft/physical- ## Trigger Posture -This workflow runs via `workflow_run` after the `PR Validation` orchestrator completes on `main` for a -`pull_request` event. Because `workflow_run` evaluates the workflow file from the default branch, the +This workflow runs via `workflow_run` after the `PR Validation` orchestrator completes on a Dependabot +PR's head branch (`dependabot/**`) for a `pull_request` event. The `branches:` filter on `workflow_run` +matches the *triggering run's `head_branch`*, not its base — using `main` here would silently never fire +for Dependabot PRs (regression observed in #583, fixed in #584; do not change without re-reading those). +Because `workflow_run` evaluates the workflow file from the default branch, the agent step always uses the trusted, merged definition rather than fork content. The gh-aw compiler auto-injects fork-PR exclusion and a `repository.id` guard into the lock file. The workflow-level `if:` short-circuits any non-PR triggering event, any PR not authored by `dependabot[bot]` (gated on From eec026b4871620c0812f7559870e963676fdb145 Mon Sep 17 00:00:00 2001 From: katriendg Date: Fri, 8 May 2026 09:33:02 +0000 Subject: [PATCH 3/9] build(agents): regenerate lock file with gh-aw v0.71.5 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Merge main to resolve lock file conflict - Upgrade gh-aw from v0.71.1 to v0.71.5 - Recompile aw-dependabot-pr-review workflow 🤖 - Generated by Copilot --- .github/aw/actions-lock.json | 11 +- .../aw-dependabot-pr-review.lock.yml | 368 ++++++++++++------ .github/workflows/aw-dependabot-pr-review.md | 2 - scripts/linting/Invoke-YamlLint.ps1 | 3 + 4 files changed, 251 insertions(+), 133 deletions(-) diff --git a/.github/aw/actions-lock.json b/.github/aw/actions-lock.json index c365a499..f8a50086 100644 --- a/.github/aw/actions-lock.json +++ b/.github/aw/actions-lock.json @@ -5,10 +5,15 @@ "version": "v9", "sha": "373c709c69115d41ff229c7e5df9f8788daa9553" }, - "github/gh-aw-actions/setup@v0.71.1": { + "actions/github-script@v9.0.0": { + "repo": "actions/github-script", + "version": "v9.0.0", + "sha": "3a2844b7e9c422d3c10d287c895573f7108da1b3" + }, + "github/gh-aw-actions/setup@v0.71.5": { "repo": "github/gh-aw-actions/setup", - "version": "v0.71.1", - "sha": "239aec45b78c8799417efdd5bc6d8cc036629ec1" + "version": "v0.71.5", + "sha": "b8068426813005612b960b5ab0b8bd2c27142323" } } } diff --git a/.github/workflows/aw-dependabot-pr-review.lock.yml b/.github/workflows/aw-dependabot-pr-review.lock.yml index 8704ab18..07bddf87 100644 --- a/.github/workflows/aw-dependabot-pr-review.lock.yml +++ b/.github/workflows/aw-dependabot-pr-review.lock.yml @@ -1,5 +1,5 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"46234d20433a81ce7491f5c6933eb4c75977de922d188a0253fa2392eff22580","compiler_version":"v0.68.3","strict":true,"agent_id":"copilot"} -# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"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/setup-python","sha":"a309ff8b426b58ec0e2a45f0f869d46889d02405","version":"v6.2.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"astral-sh/setup-uv","sha":"cec208311dfd045dd5311c1add060b2062131d57","version":"v8.0.0"},{"repo":"github/gh-aw-actions/setup","sha":"ba90f2186d7ad780ec640f364005fa24e797b360","version":"v0.68.3"},{"repo":"hashicorp/setup-terraform","sha":"5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85","version":"5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85"},{"repo":"terraform-linters/setup-tflint","sha":"b480b8fcdaa6f2c577f8e4fa799e89e756bb7c93","version":"b480b8fcdaa6f2c577f8e4fa799e89e756bb7c93"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.20"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.2.19"},{"image":"ghcr.io/github/github-mcp-server:v0.32.0"},{"image":"node:lts-alpine"}]} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"cfc76a9382771b49f7a1c754e06a15c3c365b0cc269ac1203bec149b73fbc281","compiler_version":"v0.71.5","strict":true,"agent_id":"copilot"} +# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"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":"373c709c69115d41ff229c7e5df9f8788daa9553"},{"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/setup-python","sha":"a309ff8b426b58ec0e2a45f0f869d46889d02405","version":"v6.2.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"astral-sh/setup-uv","sha":"08807647e7069bb48b6ef5acd8ec9567f424441b","version":"v8.1.0"},{"repo":"github/gh-aw-actions/setup","sha":"b8068426813005612b960b5ab0b8bd2c27142323","version":"v0.71.5"},{"repo":"hashicorp/setup-terraform","sha":"5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85","version":"5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85"},{"repo":"terraform-linters/setup-tflint","sha":"b480b8fcdaa6f2c577f8e4fa799e89e756bb7c93","version":"b480b8fcdaa6f2c577f8e4fa799e89e756bb7c93"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.40","digest":"sha256:14ff567e8d9d4c2fbc5e55c973488381c71d7e0fdbe72d30ee7b8a738fd86504","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.40@sha256:14ff567e8d9d4c2fbc5e55c973488381c71d7e0fdbe72d30ee7b8a738fd86504"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.40","digest":"sha256:2883ca3e5ae9f330cafdd9345bfd4ae17fc8da36c96d4c9a1f76e922b4c45280","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.40@sha256:2883ca3e5ae9f330cafdd9345bfd4ae17fc8da36c96d4c9a1f76e922b4c45280"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.40","digest":"sha256:b084f4a2c771f584ee68084ced52fa6b3245197a1889645d817462d307d3ac51","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.40@sha256:b084f4a2c771f584ee68084ced52fa6b3245197a1889645d817462d307d3ac51"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) # | |_| | __ _ ___ _ __ | |_ _ ___ @@ -14,7 +14,7 @@ # \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ # \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ # -# This file was automatically generated by gh-aw (v0.68.3). DO NOT EDIT. +# This file was automatically generated by gh-aw (v0.71.5). DO NOT EDIT. # # To update this file, edit the corresponding .md file and run: # gh aw compile @@ -37,97 +37,96 @@ # Custom actions used: # - actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 # - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 -# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 +# - actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # 373c709c69115d41ff229c7e5df9f8788daa9553 +# - actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 +# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 # - actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 # - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 # - actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 # - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 # - astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 -# - github/gh-aw-actions/setup@bc56a0cad2f450c562810785ef38649c04db812a # v0.72.1 +# - github/gh-aw-actions/setup@b8068426813005612b960b5ab0b8bd2c27142323 # v0.71.5 # - hashicorp/setup-terraform@5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85 # 5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85 # - terraform-linters/setup-tflint@b480b8fcdaa6f2c577f8e4fa799e89e756bb7c93 # b480b8fcdaa6f2c577f8e4fa799e89e756bb7c93 # # Container images used: -# - ghcr.io/github/gh-aw-firewall/agent:0.25.20 -# - ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20 -# - ghcr.io/github/gh-aw-firewall/squid:0.25.20 -# - ghcr.io/github/gh-aw-mcpg:v0.2.19 -# - ghcr.io/github/github-mcp-server:v0.32.0 -# - node:lts-alpine +# - ghcr.io/github/gh-aw-firewall/agent:0.25.40@sha256:14ff567e8d9d4c2fbc5e55c973488381c71d7e0fdbe72d30ee7b8a738fd86504 +# - ghcr.io/github/gh-aw-firewall/api-proxy:0.25.40@sha256:2883ca3e5ae9f330cafdd9345bfd4ae17fc8da36c96d4c9a1f76e922b4c45280 +# - ghcr.io/github/gh-aw-firewall/squid:0.25.40@sha256:b084f4a2c771f584ee68084ced52fa6b3245197a1889645d817462d307d3ac51 +# - ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c +# - ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959 +# - node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f name: "AW Dependabot PR Review" "on": - # bots: # Bots processed as bot check in pre-activation job - # - dependabot[bot] # Bots processed as bot check in pre-activation job - pull_request_target: + workflow_run: + # zizmor: ignore[dangerous-triggers] - workflow_run trigger is secured with role and fork validation branches: - - main + - dependabot/** types: - - opened - - synchronize - - reopened - # roles: # Roles processed as role check in pre-activation job - # - admin # Roles processed as role check in pre-activation job - # - maintainer # Roles processed as role check in pre-activation job - # - write # Roles processed as role check in pre-activation job + - completed + workflows: + - PR Validation permissions: {} concurrency: - group: "gh-aw-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref || github.run_id }}" - cancel-in-progress: true + group: "gh-aw-${{ github.workflow }}" run-name: "AW Dependabot PR Review" jobs: activation: needs: pre_activation + # zizmor: ignore[dangerous-triggers] - workflow_run trigger is secured with role and fork validation if: > - needs.pre_activation.outputs.activated == 'true' && (github.event.pull_request != null && startsWith(github.event.pull_request.head.ref, 'dependabot/') && - github.event.pull_request.user.login == 'dependabot[bot]' && !github.event.pull_request.draft) + (needs.pre_activation.outputs.activated == 'true' && (github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.actor.login == 'dependabot[bot]' && contains(fromJSON('["success","failure","cancelled","timed_out","neutral","skipped","action_required"]'), + github.event.workflow_run.conclusion))) && (github.event_name != 'workflow_run' || github.event.workflow_run.repository.id == github.repository_id && (!(github.event.workflow_run.repository.fork))) runs-on: ubuntu-slim permissions: actions: read contents: read outputs: - body: ${{ steps.sanitized.outputs.body }} comment_id: "" comment_repo: "" + engine_id: ${{ steps.generate_aw_info.outputs.engine_id }} lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }} model: ${{ steps.generate_aw_info.outputs.model }} secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} setup-trace-id: ${{ steps.setup.outputs.trace-id }} stale_lock_file_failed: ${{ steps.check-lock-file.outputs.stale_lock_file_failed == 'true' }} - text: ${{ steps.sanitized.outputs.text }} - title: ${{ steps.sanitized.outputs.title }} steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@bc56a0cad2f450c562810785ef38649c04db812a # v0.72.1 + uses: github/gh-aw-actions/setup@b8068426813005612b960b5ab0b8bd2c27142323 # v0.71.5 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} trace-id: ${{ needs.pre_activation.outputs.setup-trace-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "AW Dependabot PR Review" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/aw-dependabot-pr-review.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.40" - name: Generate agentic run info id: generate_aw_info env: GH_AW_INFO_ENGINE_ID: "copilot" GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI" - GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || 'auto' }} - GH_AW_INFO_VERSION: "1.0.21" - GH_AW_INFO_AGENT_VERSION: "1.0.21" - GH_AW_INFO_CLI_VERSION: "v0.68.3" + GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || 'claude-sonnet-4.6' }} + GH_AW_INFO_VERSION: "1.0.40" + GH_AW_INFO_AGENT_VERSION: "1.0.40" + GH_AW_INFO_CLI_VERSION: "v0.71.5" GH_AW_INFO_WORKFLOW_NAME: "AW Dependabot PR Review" GH_AW_INFO_EXPERIMENTAL: "false" GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" GH_AW_INFO_STAGED: "false" GH_AW_INFO_ALLOWED_DOMAINS: '["defaults","github","python","node","go","terraform","containers","api.osv.dev","services.nvd.nist.gov"]' GH_AW_INFO_FIREWALL_ENABLED: "true" - GH_AW_INFO_AWF_VERSION: "v0.25.20" + GH_AW_INFO_AWF_VERSION: "v0.25.40" GH_AW_INFO_AWMG_VERSION: "" GH_AW_INFO_FIREWALL_TYPE: "squid" GH_AW_COMPILED_STRICT: "true" - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -146,11 +145,23 @@ jobs: sparse-checkout: | .github .agents + .claude + .codex + .crush + .gemini + .opencode + .pi sparse-checkout-cone-mode: true fetch-depth: 1 + - name: Save agent config folders for base branch restoration + env: + GH_AW_AGENT_FOLDERS: ".agents .claude .codex .crush .gemini .github .opencode .pi" + GH_AW_AGENT_FILES: ".crush.json AGENTS.md CLAUDE.md GEMINI.md PI.md opencode.jsonc" + # poutine:ignore untrusted_checkout_exec + run: bash "${RUNNER_TEMP}/gh-aw/actions/save_base_github_folders.sh" - name: Check workflow lock file id: check-lock-file - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_WORKFLOW_FILE: "aw-dependabot-pr-review.lock.yml" GH_AW_CONTEXT_WORKFLOW_REF: "${{ github.workflow_ref }}" @@ -161,26 +172,15 @@ jobs: const { main } = require('${{ runner.temp }}/gh-aw/actions/check_workflow_timestamp_api.cjs'); await main(); - name: Check compile-agentic version - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_COMPILED_VERSION: "v0.68.3" + GH_AW_COMPILED_VERSION: "v0.71.5" with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require('${{ runner.temp }}/gh-aw/actions/check_version_updates.cjs'); await main(); - - name: Compute current body text - id: sanitized - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 - env: - GH_AW_ALLOWED_BOTS: "dependabot[bot]" - with: - script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/compute_text.cjs'); - await main(); - name: Create prompt with built-in context env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt @@ -197,17 +197,20 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_5734b58a8c868ede_EOF' + cat << 'GH_AW_PROMPT_a27685d308878644_EOF' - GH_AW_PROMPT_5734b58a8c868ede_EOF + GH_AW_PROMPT_a27685d308878644_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/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_5734b58a8c868ede_EOF' + cat << 'GH_AW_PROMPT_a27685d308878644_EOF' Tools: add_comment(max:2), create_pull_request_review_comment(max:5), submit_pull_request_review, missing_tool, missing_data, noop + GH_AW_PROMPT_a27685d308878644_EOF + cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" + cat << 'GH_AW_PROMPT_a27685d308878644_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -236,18 +239,19 @@ jobs: {{/if}} - GH_AW_PROMPT_5734b58a8c868ede_EOF + GH_AW_PROMPT_a27685d308878644_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_5734b58a8c868ede_EOF' + cat << 'GH_AW_PROMPT_a27685d308878644_EOF' {{#runtime-import .github/agents/dependabot-pr-reviewer.agent.md}} {{#runtime-import .github/workflows/aw-dependabot-pr-review.md}} - GH_AW_PROMPT_5734b58a8c868ede_EOF + GH_AW_PROMPT_a27685d308878644_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_ENGINE_ID: "copilot" with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -255,7 +259,7 @@ jobs: const { main } = require('${{ runner.temp }}/gh-aw/actions/interpolate_prompt.cjs'); await main(); - name: Substitute placeholders - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_GITHUB_ACTOR: ${{ github.actor }} @@ -266,6 +270,7 @@ jobs: GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + GH_AW_MCP_CLI_SERVERS_LIST: '- `safeoutputs` — run `safeoutputs --help` to see available tools' GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: ${{ needs.pre_activation.outputs.activated }} with: script: | @@ -286,6 +291,7 @@ jobs: GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY, GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID, GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE, + GH_AW_MCP_CLI_SERVERS_LIST: process.env.GH_AW_MCP_CLI_SERVERS_LIST, GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: process.env.GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED } }); @@ -304,10 +310,12 @@ jobs: uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: activation + include-hidden-files: true path: | /tmp/gh-aw/aw_info.json /tmp/gh-aw/aw-prompts/prompt.txt /tmp/gh-aw/github_rate_limits.jsonl + /tmp/gh-aw/base if-no-files-found: ignore retention-days: 1 @@ -316,8 +324,11 @@ jobs: runs-on: ubuntu-latest permissions: actions: read + checks: read contents: read pull-requests: read + concurrency: + group: "gh-aw-copilot-${{ github.workflow }}" env: DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} GH_AW_ASSETS_ALLOWED_EXTS: "" @@ -340,11 +351,15 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@bc56a0cad2f450c562810785ef38649c04db812a # v0.72.1 + uses: github/gh-aw-actions/setup@b8068426813005612b960b5ab0b8bd2c27142323 # v0.71.5 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} trace-id: ${{ needs.activation.outputs.setup-trace-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "AW Dependabot PR Review" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/aw-dependabot-pr-review.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.40" - name: Set runtime paths id: set-runtime-paths run: | @@ -358,7 +373,7 @@ jobs: with: persist-credentials: false - name: Merge remote .github folder - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_FILE: ".github/agents/dependabot-pr-reviewer.agent.md" GH_AW_AGENT_IMPORT_SPEC: "../agents/dependabot-pr-reviewer.agent.md" @@ -411,10 +426,10 @@ jobs: with: tflint_version: latest - id: resolve-pr - name: Resolve Dependabot PR context and fetch PR Validation status - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + name: Resolve Dependabot PR context from workflow_run + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # 373c709c69115d41ff229c7e5df9f8788daa9553 with: - script: "const pr = context.payload.pull_request;\nif (!pr) {\n core.setFailed('pull_request payload missing');\n return;\n}\nif (pr.user.login !== 'dependabot[bot]') {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'not-dependabot');\n return;\n}\nif (pr.draft) {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'draft');\n return;\n}\ncore.exportVariable('PR_NUMBER', String(pr.number));\ncore.exportVariable('PR_TITLE', pr.title);\ncore.exportVariable('PR_HEAD_REF', pr.head.ref);\ncore.exportVariable('PR_BASE_REF', pr.base.ref);\ncore.exportVariable('PR_AUTHOR', pr.user.login);\ncore.exportVariable('PR_HEAD_SHA', pr.head.sha);\n\n// Look up the most recent PR Validation workflow run for this head SHA.\n// It may still be in progress when pull_request_target fires.\nlet conclusion = 'pending';\nlet runUrl = '';\ntry {\n const { data } = await github.rest.actions.listWorkflowRunsForRepo({\n owner: context.repo.owner,\n repo: context.repo.repo,\n head_sha: pr.head.sha,\n event: 'pull_request',\n per_page: 30,\n });\n const validation = (data.workflow_runs || []).find(r => r.name === 'PR Validation');\n if (validation) {\n runUrl = validation.html_url || '';\n conclusion = validation.status === 'completed'\n ? (validation.conclusion || 'unknown')\n : `in_progress:${validation.status}`;\n }\n} catch (err) {\n core.warning(`Failed to look up PR Validation run: ${err.message}`);\n}\ncore.exportVariable('PR_VALIDATION_CONCLUSION', conclusion);\ncore.exportVariable('PR_VALIDATION_RUN_URL', runUrl);\ncore.info(`Resolved PR #${pr.number} (${pr.title}); PR Validation conclusion: ${conclusion}`);\n" + script: "const run = context.payload.workflow_run;\nif (!run) {\n core.setFailed('workflow_run payload missing');\n return;\n}\nif (run.event !== 'pull_request') {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'not-a-pr-run');\n return;\n}\n\nlet pr = (run.pull_requests || [])[0];\nif (!pr) {\n // Fork PRs do not appear in workflow_run.pull_requests; fall back to search.\n const q = `repo:${context.repo.owner}/${context.repo.repo} is:pr sha:${run.head_sha}`;\n const { data } = await github.rest.search.issuesAndPullRequests({ q });\n const hit = (data.items || [])[0];\n if (!hit) {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'pr-resolution-failed');\n return;\n }\n const { data: full } = await github.rest.pulls.get({\n owner: context.repo.owner,\n repo: context.repo.repo,\n pull_number: hit.number,\n });\n pr = full;\n} else {\n // Hydrate the full PR object so fields like `body` and `draft` are reliable.\n const { data: full } = await github.rest.pulls.get({\n owner: context.repo.owner,\n repo: context.repo.repo,\n pull_number: pr.number,\n });\n pr = full;\n}\n\nif (pr.user.login !== 'dependabot[bot]') {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'not-dependabot');\n return;\n}\nif (pr.draft) {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'draft');\n return;\n}\n\ncore.exportVariable('PR_NUMBER', String(pr.number));\ncore.exportVariable('PR_TITLE', pr.title);\ncore.exportVariable('PR_HEAD_REF', pr.head.ref);\ncore.exportVariable('PR_BASE_REF', pr.base.ref);\ncore.exportVariable('PR_AUTHOR', pr.user.login);\ncore.exportVariable('PR_HEAD_SHA', pr.head.sha);\n\n// PR Validation conclusion comes directly from the triggering workflow_run payload;\n// it is always final under `types: [completed]`.\ncore.exportVariable('PR_VALIDATION_CONCLUSION', run.conclusion || 'unknown');\ncore.exportVariable('PR_VALIDATION_RUN_URL', run.html_url || '');\n\n// Resolve per-surface check-runs ONCE here so the persona does not re-walk them.\nlet failing = [];\ntry {\n const { data: checks } = await github.rest.checks.listForRef({\n owner: context.repo.owner,\n repo: context.repo.repo,\n ref: pr.head.sha,\n per_page: 100,\n });\n failing = (checks.check_runs || [])\n .filter(c => c.status === 'completed'\n && !['success', 'neutral', 'skipped'].includes(c.conclusion))\n .map(c => ({ name: c.name, html_url: c.html_url, conclusion: c.conclusion }));\n} catch (err) {\n core.warning(`Failed to enumerate check-runs: ${err.message}`);\n}\ncore.exportVariable('PR_VALIDATION_FAILING_CHECKS', JSON.stringify(failing));\n\n// Hydrate Dependabot enrichment input from REST so the agent does not depend on\n// the integrity-filtered MCP read of the PR body.\ncore.exportVariable('PR_BODY', pr.body || '');\n\ncore.info(`Resolved PR #${pr.number} (${pr.title}); PR Validation conclusion: ${run.conclusion}; failing checks: ${failing.length}`);\n" - name: Configure Git credentials env: @@ -433,7 +448,7 @@ jobs: id: checkout-pr if: | github.event.pull_request || github.event.issue.pull_request - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} with: @@ -444,14 +459,14 @@ jobs: const { main } = require('${{ runner.temp }}/gh-aw/actions/checkout_pr_branch.cjs'); await main(); - name: Install GitHub Copilot CLI - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.21 + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.40 env: GH_HOST: github.com - name: Install AWF binary - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.20 + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.40 - name: Determine automatic lockdown mode for GitHub MCP Server id: determine-automatic-lockdown - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 env: GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} @@ -459,22 +474,33 @@ jobs: script: | const determineAutomaticLockdown = require('${{ runner.temp }}/gh-aw/actions/determine_automatic_lockdown.cjs'); await determineAutomaticLockdown(github, context, core); + - name: Download activation artifact + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: activation + path: /tmp/gh-aw + - name: Restore agent config folders from base branch + if: steps.checkout-pr.outcome == 'success' + env: + GH_AW_AGENT_FOLDERS: ".agents .claude .codex .crush .gemini .github .opencode .pi" + GH_AW_AGENT_FILES: ".crush.json AGENTS.md CLAUDE.md GEMINI.md PI.md opencode.jsonc" + run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_base_github_folders.sh" - name: Download container images - run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.20 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20 ghcr.io/github/gh-aw-firewall/squid:0.25.20 ghcr.io/github/gh-aw-mcpg:v0.2.19 ghcr.io/github/github-mcp-server:v0.32.0 node:lts-alpine - - name: Write Safe Outputs Config + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.40@sha256:14ff567e8d9d4c2fbc5e55c973488381c71d7e0fdbe72d30ee7b8a738fd86504 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.40@sha256:2883ca3e5ae9f330cafdd9345bfd4ae17fc8da36c96d4c9a1f76e922b4c45280 ghcr.io/github/gh-aw-firewall/squid:0.25.40@sha256:b084f4a2c771f584ee68084ced52fa6b3245197a1889645d817462d307d3ac51 ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959 node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f + - name: Generate 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_a6000a4bbc0dff64_EOF' - {"add_comment":{"max":2,"target":"triggering"},"create_pull_request_review_comment":{"max":5,"side":"RIGHT"},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{},"submit_pull_request_review":{"max":1}} - GH_AW_SAFE_OUTPUTS_CONFIG_a6000a4bbc0dff64_EOF - - name: Write Safe Outputs Tools + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_1092981f5bf7e3ab_EOF' + {"add_comment":{"max":2,"target":"${{ env.PR_NUMBER }}"},"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"},"report_incomplete":{},"submit_pull_request_review":{"max":1,"target":"${{ env.PR_NUMBER }}"}} + GH_AW_SAFE_OUTPUTS_CONFIG_1092981f5bf7e3ab_EOF + - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | { "description_suffixes": { - "add_comment": " CONSTRAINTS: Maximum 2 comment(s) can be added. Target: triggering. Supports reply_to_id for discussion threading.", + "add_comment": " CONSTRAINTS: Maximum 2 comment(s) can be added. Target: ${{ env.PR_NUMBER }}. Supports reply_to_id for discussion threading.", "create_pull_request_review_comment": " CONSTRAINTS: Maximum 5 review comment(s) can be created. Comments will be on the RIGHT side of the diff.", "submit_pull_request_review": " CONSTRAINTS: Maximum 1 review(s) can be submitted." }, @@ -634,7 +660,7 @@ jobs: } } } - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -692,11 +718,12 @@ jobs: 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 /tmp/gh-aw/mcp-config + mkdir -p "${RUNNER_TEMP}/gh-aw/mcp-config" # Export gateway environment variables for MCP config and gateway script - export MCP_GATEWAY_PORT="80" + export MCP_GATEWAY_PORT="8080" export MCP_GATEWAY_DOMAIN="host.docker.internal" + export MCP_GATEWAY_HOST_DOMAIN="localhost" MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') echo "::add-mask::${MCP_GATEWAY_API_KEY}" export MCP_GATEWAY_API_KEY @@ -706,15 +733,19 @@ jobs: export DEBUG="*" export GH_AW_ENGINE="copilot" - export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.2.19' + MCP_GATEWAY_UID=$(id -u 2>/dev/null || echo '0') + MCP_GATEWAY_GID=$(id -g 2>/dev/null || echo '0') + DOCKER_SOCK_GID=$(stat -c '%g' /var/run/docker.sock 2>/dev/null || echo '0') + export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -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.6' mkdir -p /home/runner/.copilot - cat << GH_AW_MCP_CONFIG_658c528aa9fae3bb_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" + GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) + cat << GH_AW_MCP_CONFIG_85a1043331f22ef5_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "github": { "type": "stdio", - "container": "ghcr.io/github/github-mcp-server:v0.32.0", + "container": "ghcr.io/github/github-mcp-server:v1.0.3", "env": { "GITHUB_HOST": "\${GITHUB_SERVER_URL}", "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", @@ -750,15 +781,28 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_658c528aa9fae3bb_EOF - - name: Download activation artifact - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + GH_AW_MCP_CONFIG_85a1043331f22ef5_EOF + - name: Mount MCP servers as CLIs + id: mount-mcp-clis + continue-on-error: true + env: + MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} + MCP_GATEWAY_DOMAIN: ${{ steps.start-mcp-gateway.outputs.gateway-domain }} + MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: - name: activation - path: /tmp/gh-aw - - name: Clean git credentials + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('${{ runner.temp }}/gh-aw/actions/mount_mcp_as_cli.cjs'); + await main(); + - name: Clean credentials continue-on-error: true run: bash "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh" + - name: Audit pre-agent workspace + id: pre_agent_audit + continue-on-error: true + run: bash "${RUNNER_TEMP}/gh-aw/actions/audit_pre_agent_workspace.sh" - name: Execute GitHub Copilot CLI id: agentic_execution # Copilot CLI tool arguments (sorted): @@ -780,6 +824,7 @@ jobs: # --allow-tool shell(ls) # --allow-tool shell(npm view *) # --allow-tool shell(pwd) + # --allow-tool shell(safeoutputs:*) # --allow-tool shell(sort) # --allow-tool shell(tail) # --allow-tool shell(uniq) @@ -791,21 +836,26 @@ jobs: run: | set -o pipefail touch /tmp/gh-aw/agent-step-summary.md + GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true) + export GH_AW_NODE_BIN (umask 177 && touch /tmp/gh-aw/agent-stdio.log) + printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.40/awf-config.schema.json","network":{"allowDomains":["*.docker.com","*.docker.io","*.githubusercontent.com","*.pythonhosted.org","anaconda.org","api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","api.npms.io","api.osv.dev","api.snapcraft.io","apt.releases.hashicorp.com","archive.ubuntu.com","auth.docker.io","azure.archive.ubuntu.com","binstar.org","bootstrap.pypa.io","bun.sh","cdn.jsdelivr.net","codeload.github.com","conda.anaconda.org","conda.binstar.org","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","deb.nodesource.com","deno.land","dl.k8s.io","docs.github.com","esm.sh","files.pythonhosted.org","gcr.io","get.pnpm.io","ghcr.io","github-cloud.githubusercontent.com","github-cloud.s3.amazonaws.com","github.blog","github.com","github.githubassets.com","go.dev","golang.org","googleapis.deno.dev","googlechromelabs.github.io","goproxy.io","host.docker.internal","json-schema.org","json.schemastore.org","jsr.io","keyserver.ubuntu.com","lfs.github.com","mcr.microsoft.com","nodejs.org","npm.pkg.github.com","npmjs.com","npmjs.org","objects.githubusercontent.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","pip.pypa.io","pkg.go.dev","pkgs.k8s.io","ppa.launchpad.net","production.cloudflare.docker.com","proxy.golang.org","pypi.org","pypi.python.org","quay.io","raw.githubusercontent.com","registry.bower.io","registry.hub.docker.com","registry.npmjs.com","registry.npmjs.org","registry.terraform.io","registry.yarnpkg.com","releases.hashicorp.com","repo.anaconda.com","repo.continuum.io","repo.yarnpkg.com","s.symcb.com","s.symcd.com","security.ubuntu.com","services.nvd.nist.gov","skimdb.npmjs.com","storage.googleapis.com","sum.golang.org","telemetry.enterprise.githubcopilot.com","telemetry.vercel.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com","www.npmjs.com","www.npmjs.org","yarnpkg.com","yum.releases.hashicorp.com"]},"apiProxy":{"enabled":true,"models":{"auto":["large"],"deep-research":["copilot/deep-research*","google/deep-research*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*"],"gpt-4.1":["copilot/gpt-4.1*","openai/gpt-4.1*"],"gpt-5":["copilot/gpt-5*","openai/gpt-5*"],"gpt-5-codex":["copilot/gpt-5*codex*","openai/gpt-5*codex*"],"gpt-5-mini":["copilot/gpt-5*mini*","openai/gpt-5*mini*"],"gpt-5-nano":["copilot/gpt-5*nano*","openai/gpt-5*nano*"],"gpt-5-pro":["copilot/gpt-5*pro*","openai/gpt-5*pro*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash"],"opus":["copilot/*opus*","anthropic/*opus*"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"small":["mini"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"]}},"container":{"imageTag":"0.25.40,squid=sha256:b084f4a2c771f584ee68084ced52fa6b3245197a1889645d817462d307d3ac51,agent=sha256:14ff567e8d9d4c2fbc5e55c973488381c71d7e0fdbe72d30ee7b8a738fd86504,api-proxy=sha256:2883ca3e5ae9f330cafdd9345bfd4ae17fc8da36c96d4c9a1f76e922b4c45280,cli-proxy=sha256:3e7152911d4b4b7b97beef9d3d7d924ff7902227e86001ef3838fb728d5d514c"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" && cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json # 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 '*.docker.com,*.docker.io,*.githubusercontent.com,*.pythonhosted.org,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.osv.dev,api.snapcraft.io,apt.releases.hashicorp.com,archive.ubuntu.com,auth.docker.io,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,cdn.jsdelivr.net,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,dl.k8s.io,docs.github.com,esm.sh,files.pythonhosted.org,gcr.io,get.pnpm.io,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,mcr.microsoft.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,objects.githubusercontent.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,pip.pypa.io,pkg.go.dev,pkgs.k8s.io,ppa.launchpad.net,production.cloudflare.docker.com,proxy.golang.org,pypi.org,pypi.python.org,quay.io,raw.githubusercontent.com,registry.bower.io,registry.hub.docker.com,registry.npmjs.com,registry.npmjs.org,registry.terraform.io,registry.yarnpkg.com,releases.hashicorp.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,s.symcb.com,s.symcd.com,security.ubuntu.com,services.nvd.nist.gov,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com,www.npmjs.com,www.npmjs.org,yarnpkg.com,yum.releases.hashicorp.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --image-tag 0.25.20 --skip-pull --enable-api-proxy \ - -- /bin/bash -c 'node ${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-tool github --allow-tool safeoutputs --allow-tool '\''shell(cat **/*.json)'\'' --allow-tool '\''shell(cat **/*.tf)'\'' --allow-tool '\''shell(cat **/*.toml)'\'' --allow-tool '\''shell(cat **/go.mod)'\'' --allow-tool '\''shell(cat training/rl/requirements.txt)'\'' --allow-tool '\''shell(cat training/rl/scripts/train.sh)'\'' --allow-tool '\''shell(cat)'\'' --allow-tool '\''shell(date)'\'' --allow-tool '\''shell(echo)'\'' --allow-tool '\''shell(grep -R --line-number * -- :!node_modules :!.venv :!external)'\'' --allow-tool '\''shell(grep)'\'' --allow-tool '\''shell(head)'\'' --allow-tool '\''shell(jq . **/*.json)'\'' --allow-tool '\''shell(ls)'\'' --allow-tool '\''shell(npm view *)'\'' --allow-tool '\''shell(pwd)'\'' --allow-tool '\''shell(sort)'\'' --allow-tool '\''shell(tail)'\'' --allow-tool '\''shell(uniq)'\'' --allow-tool '\''shell(wc)'\'' --allow-tool '\''shell(yq)'\'' --allow-tool web_fetch --allow-tool write --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + sudo -E awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --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 --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 --skip-pull \ + -- /bin/bash -c 'export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && 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_harness.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-tool github --allow-tool safeoutputs --allow-tool '\''shell(cat **/*.json)'\'' --allow-tool '\''shell(cat **/*.tf)'\'' --allow-tool '\''shell(cat **/*.toml)'\'' --allow-tool '\''shell(cat **/go.mod)'\'' --allow-tool '\''shell(cat training/rl/requirements.txt)'\'' --allow-tool '\''shell(cat training/rl/scripts/train.sh)'\'' --allow-tool '\''shell(cat)'\'' --allow-tool '\''shell(date)'\'' --allow-tool '\''shell(echo)'\'' --allow-tool '\''shell(grep -R --line-number * -- :!node_modules :!.venv :!external)'\'' --allow-tool '\''shell(grep)'\'' --allow-tool '\''shell(head)'\'' --allow-tool '\''shell(jq . **/*.json)'\'' --allow-tool '\''shell(ls)'\'' --allow-tool '\''shell(npm view *)'\'' --allow-tool '\''shell(pwd)'\'' --allow-tool '\''shell(safeoutputs:*)'\'' --allow-tool '\''shell(sort)'\'' --allow-tool '\''shell(tail)'\'' --allow-tool '\''shell(uniq)'\'' --allow-tool '\''shell(wc)'\'' --allow-tool '\''shell(yq)'\'' --allow-tool web_fetch --allow-tool write --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 + COPILOT_API_KEY: dummy-byok-key-for-offline-mode COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - COPILOT_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || '' }} + COPILOT_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || 'claude-sonnet-4.6' }} GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PHASE: agent 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: v0.68.3 + GH_AW_VERSION: v0.71.5 GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true + GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -850,7 +900,7 @@ jobs: bash "${RUNNER_TEMP}/gh-aw/actions/stop_mcp_gateway.sh" "$GATEWAY_PID" - name: Redact secrets in logs if: always() - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -876,10 +926,10 @@ jobs: - name: Ingest agent output id: collect_output if: always() - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} - GH_AW_ALLOWED_DOMAINS: "*.docker.com,*.docker.io,*.githubusercontent.com,*.pythonhosted.org,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.osv.dev,api.snapcraft.io,apt.releases.hashicorp.com,archive.ubuntu.com,auth.docker.io,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,cdn.jsdelivr.net,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,dl.k8s.io,docs.github.com,esm.sh,files.pythonhosted.org,gcr.io,get.pnpm.io,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,mcr.microsoft.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,objects.githubusercontent.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,pip.pypa.io,pkg.go.dev,pkgs.k8s.io,ppa.launchpad.net,production.cloudflare.docker.com,proxy.golang.org,pypi.org,pypi.python.org,quay.io,raw.githubusercontent.com,registry.bower.io,registry.hub.docker.com,registry.npmjs.com,registry.npmjs.org,registry.terraform.io,registry.yarnpkg.com,releases.hashicorp.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,s.symcb.com,s.symcd.com,security.ubuntu.com,services.nvd.nist.gov,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com,www.npmjs.com,www.npmjs.org,yarnpkg.com,yum.releases.hashicorp.com" + GH_AW_ALLOWED_DOMAINS: "*.docker.com,*.docker.io,*.githubusercontent.com,*.pythonhosted.org,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.osv.dev,api.snapcraft.io,apt.releases.hashicorp.com,archive.ubuntu.com,auth.docker.io,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,cdn.jsdelivr.net,codeload.github.com,conda.anaconda.org,conda.binstar.org,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,deb.nodesource.com,deno.land,dl.k8s.io,docs.github.com,esm.sh,files.pythonhosted.org,gcr.io,get.pnpm.io,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,mcr.microsoft.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,objects.githubusercontent.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,pip.pypa.io,pkg.go.dev,pkgs.k8s.io,ppa.launchpad.net,production.cloudflare.docker.com,proxy.golang.org,pypi.org,pypi.python.org,quay.io,raw.githubusercontent.com,registry.bower.io,registry.hub.docker.com,registry.npmjs.com,registry.npmjs.org,registry.terraform.io,registry.yarnpkg.com,releases.hashicorp.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,s.symcb.com,s.symcd.com,security.ubuntu.com,services.nvd.nist.gov,skimdb.npmjs.com,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com,www.npmjs.com,www.npmjs.org,yarnpkg.com,yum.releases.hashicorp.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} with: @@ -890,7 +940,7 @@ jobs: await main(); - name: Parse agent logs for step summary if: always() - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ with: @@ -902,7 +952,7 @@ jobs: - name: Parse MCP Gateway logs for step summary if: always() id: parse-mcp-gateway - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -915,9 +965,9 @@ jobs: env: AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs run: | - # Fix permissions on firewall logs so they can be uploaded as artifacts + # Fix permissions on firewall logs/audit dirs so they can be uploaded as artifacts # AWF runs with sudo, creating files owned by root - sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true + sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall 2>/dev/null || true # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step) if command -v awf &> /dev/null; then awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" @@ -927,13 +977,23 @@ jobs: - name: Parse token usage for step summary if: always() continue-on-error: true - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_token_usage.cjs'); await main(); + - name: Print AWF reflect summary + if: always() + continue-on-error: true + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/awf_reflect_summary.cjs'); + await main(); - name: Write agent output placeholder if missing if: always() run: | @@ -953,14 +1013,17 @@ jobs: /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/agent_usage.json /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/pre-agent-audit.txt /tmp/gh-aw/agent/ /tmp/gh-aw/github_rate_limits.jsonl /tmp/gh-aw/safeoutputs.jsonl /tmp/gh-aw/agent_output.json /tmp/gh-aw/aw-*.patch /tmp/gh-aw/aw-*.bundle + /tmp/gh-aw/awf-config.json /tmp/gh-aw/sandbox/firewall/logs/ /tmp/gh-aw/sandbox/firewall/audit/ + /tmp/gh-aw/sandbox/firewall/awf-reflect.json if-no-files-found: ignore conclusion: @@ -989,11 +1052,15 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@bc56a0cad2f450c562810785ef38649c04db812a # v0.72.1 + uses: github/gh-aw-actions/setup@b8068426813005612b960b5ab0b8bd2c27142323 # v0.71.5 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} trace-id: ${{ needs.activation.outputs.setup-trace-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "AW Dependabot PR Review" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/aw-dependabot-pr-review.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.40" - name: Download agent output artifact id: download-agent-output continue-on-error: true @@ -1010,7 +1077,7 @@ jobs: echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" - name: Process no-op messages id: noop - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_NOOP_MAX: "1" @@ -1027,7 +1094,7 @@ jobs: await main(); - name: Log detection run id: detection_runs - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_WORKFLOW_NAME: "AW Dependabot PR Review" @@ -1043,7 +1110,7 @@ jobs: await main(); - name: Record missing tool id: missing_tool - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_MISSING_TOOL_CREATE_ISSUE: "true" @@ -1057,7 +1124,7 @@ jobs: await main(); - name: Record incomplete id: report_incomplete - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_REPORT_INCOMPLETE_CREATE_ISSUE: "true" @@ -1072,13 +1139,14 @@ jobs: - name: Handle agent failure id: handle_agent_failure if: always() - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_WORKFLOW_NAME: "AW Dependabot PR Review" GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} GH_AW_WORKFLOW_ID: "aw-dependabot-pr-review" + GH_AW_ACTION_FAILURE_ISSUE_EXPIRES_HOURS: "168" GH_AW_ENGINE_ID: "copilot" GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.activation.outputs.secret_verification_result }} GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} @@ -1086,10 +1154,13 @@ jobs: GH_AW_MCP_POLICY_ERROR: ${{ needs.agent.outputs.mcp_policy_error }} GH_AW_AGENTIC_ENGINE_TIMEOUT: ${{ needs.agent.outputs.agentic_engine_timeout }} GH_AW_MODEL_NOT_SUPPORTED_ERROR: ${{ needs.agent.outputs.model_not_supported_error }} + GH_AW_ENGINE_API_HOSTS: "api.enterprise.githubcopilot.com,api.githubcopilot.com,api.business.githubcopilot.com,api.individual.githubcopilot.com" GH_AW_LOCKDOWN_CHECK_FAILED: ${{ needs.activation.outputs.lockdown_check_failed }} GH_AW_STALE_LOCK_FILE_FAILED: ${{ needs.activation.outputs.stale_lock_file_failed }} GH_AW_GROUP_REPORTS: "false" GH_AW_FAILURE_REPORT_AS_ISSUE: "true" + GH_AW_MISSING_TOOL_REPORT_AS_FAILURE: "true" + GH_AW_MISSING_DATA_REPORT_AS_FAILURE: "true" GH_AW_TIMEOUT_MINUTES: "15" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} @@ -1115,11 +1186,15 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@bc56a0cad2f450c562810785ef38649c04db812a # v0.72.1 + uses: github/gh-aw-actions/setup@b8068426813005612b960b5ab0b8bd2c27142323 # v0.71.5 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} trace-id: ${{ needs.activation.outputs.setup-trace-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "AW Dependabot PR Review" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/aw-dependabot-pr-review.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.40" - name: Download agent output artifact id: download-agent-output continue-on-error: true @@ -1145,7 +1220,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.20 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20 ghcr.io/github/gh-aw-firewall/squid:0.25.20 + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.40@sha256:14ff567e8d9d4c2fbc5e55c973488381c71d7e0fdbe72d30ee7b8a738fd86504 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.40@sha256:2883ca3e5ae9f330cafdd9345bfd4ae17fc8da36c96d4c9a1f76e922b4c45280 ghcr.io/github/gh-aw-firewall/squid:0.25.40@sha256:b084f4a2c771f584ee68084ced52fa6b3245197a1889645d817462d307d3ac51 - name: Check if detection needed id: detection_guard if: always() @@ -1160,10 +1235,10 @@ jobs: echo "run_detection=false" >> "$GITHUB_OUTPUT" echo "Detection skipped: no agent outputs or patches to analyze" fi - - name: Clear MCP configuration for detection + - name: Clear MCP Config for detection if: always() && steps.detection_guard.outputs.run_detection == 'true' run: | - rm -f /tmp/gh-aw/mcp-config/mcp-servers.json + rm -f "${RUNNER_TEMP}/gh-aw/mcp-config/mcp-servers.json" rm -f /home/runner/.copilot/mcp-config.json rm -f "$GITHUB_WORKSPACE/.gemini/settings.json" - name: Prepare threat detection files @@ -1182,7 +1257,7 @@ jobs: ls -la /tmp/gh-aw/threat-detection/ 2>/dev/null || true - name: Setup threat detection if: always() && steps.detection_guard.outputs.run_detection == 'true' - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: WORKFLOW_NAME: "AW Dependabot PR Review" WORKFLOW_DESCRIPTION: "Advisory agentic review of Dependabot dependency update PRs for physical-ai-toolchain" @@ -1198,33 +1273,44 @@ jobs: run: | mkdir -p /tmp/gh-aw/threat-detection touch /tmp/gh-aw/threat-detection/detection.log + - name: Setup Node.js + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version: '24' + package-manager-cache: false - name: Install GitHub Copilot CLI - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.21 + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.40 env: GH_HOST: github.com - name: Install AWF binary - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.20 + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.40 - name: Execute GitHub Copilot CLI if: always() && steps.detection_guard.outputs.run_detection == 'true' + continue-on-error: true id: detection_agentic_execution # Copilot CLI tool arguments (sorted): timeout-minutes: 20 run: | set -o pipefail touch /tmp/gh-aw/agent-step-summary.md + GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true) + export GH_AW_NODE_BIN (umask 177 && touch /tmp/gh-aw/threat-detection/detection.log) + printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.40/awf-config.schema.json","network":{"allowDomains":["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"]},"apiProxy":{"enabled":true},"container":{"imageTag":"0.25.40,squid=sha256:b084f4a2c771f584ee68084ced52fa6b3245197a1889645d817462d307d3ac51,agent=sha256:14ff567e8d9d4c2fbc5e55c973488381c71d7e0fdbe72d30ee7b8a738fd86504,api-proxy=sha256:2883ca3e5ae9f330cafdd9345bfd4ae17fc8da36c96d4c9a1f76e922b4c45280,cli-proxy=sha256:3e7152911d4b4b7b97beef9d3d7d924ff7902227e86001ef3838fb728d5d514c"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" && cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json # 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 --image-tag 0.25.20 --skip-pull --enable-api-proxy \ - -- /bin/bash -c 'node ${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 "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log + sudo -E awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --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 --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 --skip-pull \ + -- /bin/bash -c 'export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && 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_harness.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 + COPILOT_API_KEY: dummy-byok-key-for-offline-mode COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - COPILOT_MODEL: ${{ vars.GH_AW_MODEL_DETECTION_COPILOT || '' }} + COPILOT_MODEL: ${{ vars.GH_AW_MODEL_DETECTION_COPILOT || 'claude-sonnet-4.6' }} GH_AW_PHASE: detection GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_VERSION: v0.68.3 + GH_AW_VERSION: v0.71.5 GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true + GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} GITHUB_SERVER_URL: ${{ github.server_url }} @@ -1245,20 +1331,38 @@ jobs: - name: Parse and conclude threat detection id: detection_conclusion if: always() - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + continue-on-error: true + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: RUN_DETECTION: ${{ steps.detection_guard.outputs.run_detection }} GH_AW_DETECTION_CONTINUE_ON_ERROR: "true" with: script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_threat_detection_results.cjs'); - await main(); + try { + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_threat_detection_results.cjs'); + await main(); + } catch (loadErr) { + const continueOnError = process.env.GH_AW_DETECTION_CONTINUE_ON_ERROR !== 'false'; + const msg = 'ERR_SYSTEM: \u274C Unexpected error loading threat detection module: ' + (loadErr && loadErr.message ? loadErr.message : String(loadErr)); + core.error(msg); + core.setOutput('reason', 'parse_error'); + if (continueOnError) { + core.warning('\u26A0\uFE0F ' + msg); + core.setOutput('conclusion', 'warning'); + core.setOutput('success', 'false'); + } else { + core.setOutput('conclusion', 'failure'); + core.setOutput('success', 'false'); + core.setFailed(msg); + } + } pre_activation: if: > - github.event.pull_request != null && startsWith(github.event.pull_request.head.ref, 'dependabot/') && github.event.pull_request.user.login == 'dependabot[bot]' && !github.event.pull_request.draft + github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.actor.login == 'dependabot[bot]' && contains(fromJSON('["success","failure","cancelled","timed_out","neutral","skipped","action_required"]'), + github.event.workflow_run.conclusion) runs-on: ubuntu-slim outputs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} @@ -1267,16 +1371,19 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@bc56a0cad2f450c562810785ef38649c04db812a # v0.72.1 + uses: github/gh-aw-actions/setup@b8068426813005612b960b5ab0b8bd2c27142323 # v0.71.5 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "AW Dependabot PR Review" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/aw-dependabot-pr-review.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.40" - name: Check team membership for workflow id: check_membership - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_REQUIRED_ROLES: "admin,maintainer,write" - GH_AW_ALLOWED_BOTS: "dependabot[bot]" with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | @@ -1305,6 +1412,7 @@ jobs: GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }} GH_AW_ENGINE_ID: "copilot" GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }} + GH_AW_ENGINE_VERSION: "1.0.40" GH_AW_WORKFLOW_ID: "aw-dependabot-pr-review" GH_AW_WORKFLOW_NAME: "AW Dependabot PR Review" outputs: @@ -1319,11 +1427,15 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@bc56a0cad2f450c562810785ef38649c04db812a # v0.72.1 + uses: github/gh-aw-actions/setup@b8068426813005612b960b5ab0b8bd2c27142323 # v0.71.5 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} trace-id: ${{ needs.activation.outputs.setup-trace-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "AW Dependabot PR Review" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/aw-dependabot-pr-review.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.40" - name: Download agent output artifact id: download-agent-output continue-on-error: true @@ -1349,13 +1461,13 @@ jobs: echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV" - name: Process Safe Outputs id: process_safe_outputs - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} - GH_AW_ALLOWED_DOMAINS: "*.docker.com,*.docker.io,*.githubusercontent.com,*.pythonhosted.org,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.osv.dev,api.snapcraft.io,apt.releases.hashicorp.com,archive.ubuntu.com,auth.docker.io,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,cdn.jsdelivr.net,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,dl.k8s.io,docs.github.com,esm.sh,files.pythonhosted.org,gcr.io,get.pnpm.io,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,mcr.microsoft.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,objects.githubusercontent.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,pip.pypa.io,pkg.go.dev,pkgs.k8s.io,ppa.launchpad.net,production.cloudflare.docker.com,proxy.golang.org,pypi.org,pypi.python.org,quay.io,raw.githubusercontent.com,registry.bower.io,registry.hub.docker.com,registry.npmjs.com,registry.npmjs.org,registry.terraform.io,registry.yarnpkg.com,releases.hashicorp.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,s.symcb.com,s.symcd.com,security.ubuntu.com,services.nvd.nist.gov,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com,www.npmjs.com,www.npmjs.org,yarnpkg.com,yum.releases.hashicorp.com" + GH_AW_ALLOWED_DOMAINS: "*.docker.com,*.docker.io,*.githubusercontent.com,*.pythonhosted.org,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.osv.dev,api.snapcraft.io,apt.releases.hashicorp.com,archive.ubuntu.com,auth.docker.io,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,cdn.jsdelivr.net,codeload.github.com,conda.anaconda.org,conda.binstar.org,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,deb.nodesource.com,deno.land,dl.k8s.io,docs.github.com,esm.sh,files.pythonhosted.org,gcr.io,get.pnpm.io,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,mcr.microsoft.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,objects.githubusercontent.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,pip.pypa.io,pkg.go.dev,pkgs.k8s.io,ppa.launchpad.net,production.cloudflare.docker.com,proxy.golang.org,pypi.org,pypi.python.org,quay.io,raw.githubusercontent.com,registry.bower.io,registry.hub.docker.com,registry.npmjs.com,registry.npmjs.org,registry.terraform.io,registry.yarnpkg.com,releases.hashicorp.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,s.symcb.com,s.symcd.com,security.ubuntu.com,services.nvd.nist.gov,skimdb.npmjs.com,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com,www.npmjs.com,www.npmjs.org,yarnpkg.com,yum.releases.hashicorp.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":2,\"target\":\"triggering\"},\"create_pull_request_review_comment\":{\"max\":5,\"side\":\"RIGHT\"},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{},\"submit_pull_request_review\":{\"max\":1}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":2,\"target\":\"${{ env.PR_NUMBER }}\"},\"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\"},\"report_incomplete\":{},\"submit_pull_request_review\":{\"max\":1,\"target\":\"${{ env.PR_NUMBER }}\"}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/aw-dependabot-pr-review.md b/.github/workflows/aw-dependabot-pr-review.md index 441af081..bdcb9186 100644 --- a/.github/workflows/aw-dependabot-pr-review.md +++ b/.github/workflows/aw-dependabot-pr-review.md @@ -13,8 +13,6 @@ on: workflows: ["PR Validation"] types: [completed] branches: ["dependabot/**"] - bots: ["dependabot[bot]"] - roles: [admin, maintainer, write] permissions: contents: read pull-requests: read diff --git a/scripts/linting/Invoke-YamlLint.ps1 b/scripts/linting/Invoke-YamlLint.ps1 index 4d4bcdd1..fd3f58b6 100644 --- a/scripts/linting/Invoke-YamlLint.ps1 +++ b/scripts/linting/Invoke-YamlLint.ps1 @@ -78,6 +78,9 @@ function Invoke-YamlLintCore { } } + # Exclude gh-aw compiler-generated lock files (machine-generated, not editable) + $filesToLint = @($filesToLint | Where-Object { $_ -notmatch '\.lock\.(yml|yaml)$' }) + Write-Host "Found $(@($filesToLint).Count) workflow file(s) to lint" if (@($filesToLint).Count -gt 0) { $filesToLint | ForEach-Object { Write-Host " - $_" } From 0eaa3da2105c819807c4cc020dd9cb0a34348ccc Mon Sep 17 00:00:00 2001 From: katriendg Date: Fri, 8 May 2026 13:51:22 +0000 Subject: [PATCH 4/9] build(agents): recompile dependabot AW lock file after merge --- .../aw-dependabot-pr-review.lock.yml | 84 ++++++++----------- 1 file changed, 33 insertions(+), 51 deletions(-) diff --git a/.github/workflows/aw-dependabot-pr-review.lock.yml b/.github/workflows/aw-dependabot-pr-review.lock.yml index 36da8614..07bddf87 100644 --- a/.github/workflows/aw-dependabot-pr-review.lock.yml +++ b/.github/workflows/aw-dependabot-pr-review.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"46234d20433a81ce7491f5c6933eb4c75977de922d188a0253fa2392eff22580","compiler_version":"v0.71.5","strict":true,"agent_id":"copilot"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"cfc76a9382771b49f7a1c754e06a15c3c365b0cc269ac1203bec149b73fbc281","compiler_version":"v0.71.5","strict":true,"agent_id":"copilot"} # gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"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":"373c709c69115d41ff229c7e5df9f8788daa9553"},{"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/setup-python","sha":"a309ff8b426b58ec0e2a45f0f869d46889d02405","version":"v6.2.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"astral-sh/setup-uv","sha":"08807647e7069bb48b6ef5acd8ec9567f424441b","version":"v8.1.0"},{"repo":"github/gh-aw-actions/setup","sha":"b8068426813005612b960b5ab0b8bd2c27142323","version":"v0.71.5"},{"repo":"hashicorp/setup-terraform","sha":"5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85","version":"5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85"},{"repo":"terraform-linters/setup-tflint","sha":"b480b8fcdaa6f2c577f8e4fa799e89e756bb7c93","version":"b480b8fcdaa6f2c577f8e4fa799e89e756bb7c93"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.40","digest":"sha256:14ff567e8d9d4c2fbc5e55c973488381c71d7e0fdbe72d30ee7b8a738fd86504","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.40@sha256:14ff567e8d9d4c2fbc5e55c973488381c71d7e0fdbe72d30ee7b8a738fd86504"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.40","digest":"sha256:2883ca3e5ae9f330cafdd9345bfd4ae17fc8da36c96d4c9a1f76e922b4c45280","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.40@sha256:2883ca3e5ae9f330cafdd9345bfd4ae17fc8da36c96d4c9a1f76e922b4c45280"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.40","digest":"sha256:b084f4a2c771f584ee68084ced52fa6b3245197a1889645d817462d307d3ac51","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.40@sha256:b084f4a2c771f584ee68084ced52fa6b3245197a1889645d817462d307d3ac51"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -59,40 +59,34 @@ name: "AW Dependabot PR Review" "on": - # bots: # Bots processed as bot check in pre-activation job - # - dependabot[bot] # Bots processed as bot check in pre-activation job - pull_request_target: + workflow_run: + # zizmor: ignore[dangerous-triggers] - workflow_run trigger is secured with role and fork validation branches: - - main + - dependabot/** types: - - opened - - synchronize - - reopened - # roles: # Roles processed as role check in pre-activation job - # - admin # Roles processed as role check in pre-activation job - # - maintainer # Roles processed as role check in pre-activation job - # - write # Roles processed as role check in pre-activation job + - completed + workflows: + - PR Validation permissions: {} concurrency: - group: "gh-aw-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref || github.run_id }}" - cancel-in-progress: true + group: "gh-aw-${{ github.workflow }}" run-name: "AW Dependabot PR Review" jobs: activation: needs: pre_activation + # zizmor: ignore[dangerous-triggers] - workflow_run trigger is secured with role and fork validation if: > - needs.pre_activation.outputs.activated == 'true' && (github.event.pull_request != null && startsWith(github.event.pull_request.head.ref, 'dependabot/') && - github.event.pull_request.user.login == 'dependabot[bot]' && !github.event.pull_request.draft) + (needs.pre_activation.outputs.activated == 'true' && (github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.actor.login == 'dependabot[bot]' && contains(fromJSON('["success","failure","cancelled","timed_out","neutral","skipped","action_required"]'), + github.event.workflow_run.conclusion))) && (github.event_name != 'workflow_run' || github.event.workflow_run.repository.id == github.repository_id && (!(github.event.workflow_run.repository.fork))) runs-on: ubuntu-slim permissions: actions: read contents: read outputs: - body: ${{ steps.sanitized.outputs.body }} comment_id: "" comment_repo: "" engine_id: ${{ steps.generate_aw_info.outputs.engine_id }} @@ -101,8 +95,6 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} setup-trace-id: ${{ steps.setup.outputs.trace-id }} stale_lock_file_failed: ${{ steps.check-lock-file.outputs.stale_lock_file_failed == 'true' }} - text: ${{ steps.sanitized.outputs.text }} - title: ${{ steps.sanitized.outputs.title }} steps: - name: Setup Scripts id: setup @@ -189,18 +181,6 @@ jobs: setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require('${{ runner.temp }}/gh-aw/actions/check_version_updates.cjs'); await main(); - - name: Compute current body text - id: sanitized - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 - env: - GH_AW_ALLOWED_BOTS: "dependabot[bot]" - GH_AW_ALLOWED_DOMAINS: "*.docker.com,*.docker.io,*.githubusercontent.com,*.pythonhosted.org,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.osv.dev,api.snapcraft.io,apt.releases.hashicorp.com,archive.ubuntu.com,auth.docker.io,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,cdn.jsdelivr.net,codeload.github.com,conda.anaconda.org,conda.binstar.org,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,deb.nodesource.com,deno.land,dl.k8s.io,docs.github.com,esm.sh,files.pythonhosted.org,gcr.io,get.pnpm.io,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,mcr.microsoft.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,objects.githubusercontent.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,pip.pypa.io,pkg.go.dev,pkgs.k8s.io,ppa.launchpad.net,production.cloudflare.docker.com,proxy.golang.org,pypi.org,pypi.python.org,quay.io,raw.githubusercontent.com,registry.bower.io,registry.hub.docker.com,registry.npmjs.com,registry.npmjs.org,registry.terraform.io,registry.yarnpkg.com,releases.hashicorp.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,s.symcb.com,s.symcd.com,security.ubuntu.com,services.nvd.nist.gov,skimdb.npmjs.com,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com,www.npmjs.com,www.npmjs.org,yarnpkg.com,yum.releases.hashicorp.com" - with: - script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/compute_text.cjs'); - await main(); - name: Create prompt with built-in context env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt @@ -217,20 +197,20 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_5734b58a8c868ede_EOF' + cat << 'GH_AW_PROMPT_a27685d308878644_EOF' - GH_AW_PROMPT_5734b58a8c868ede_EOF + GH_AW_PROMPT_a27685d308878644_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/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_5734b58a8c868ede_EOF' + cat << 'GH_AW_PROMPT_a27685d308878644_EOF' Tools: add_comment(max:2), create_pull_request_review_comment(max:5), submit_pull_request_review, missing_tool, missing_data, noop - GH_AW_PROMPT_5734b58a8c868ede_EOF + GH_AW_PROMPT_a27685d308878644_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_5734b58a8c868ede_EOF' + cat << 'GH_AW_PROMPT_a27685d308878644_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -259,13 +239,13 @@ jobs: {{/if}} - GH_AW_PROMPT_5734b58a8c868ede_EOF + GH_AW_PROMPT_a27685d308878644_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_5734b58a8c868ede_EOF' + cat << 'GH_AW_PROMPT_a27685d308878644_EOF' {{#runtime-import .github/agents/dependabot-pr-reviewer.agent.md}} {{#runtime-import .github/workflows/aw-dependabot-pr-review.md}} - GH_AW_PROMPT_5734b58a8c868ede_EOF + GH_AW_PROMPT_a27685d308878644_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -344,8 +324,11 @@ jobs: runs-on: ubuntu-latest permissions: actions: read + checks: read contents: read pull-requests: read + concurrency: + group: "gh-aw-copilot-${{ github.workflow }}" env: DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} GH_AW_ASSETS_ALLOWED_EXTS: "" @@ -443,10 +426,10 @@ jobs: with: tflint_version: latest - id: resolve-pr - name: Resolve Dependabot PR context and fetch PR Validation status + name: Resolve Dependabot PR context from workflow_run uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # 373c709c69115d41ff229c7e5df9f8788daa9553 with: - script: "const pr = context.payload.pull_request;\nif (!pr) {\n core.setFailed('pull_request payload missing');\n return;\n}\nif (pr.user.login !== 'dependabot[bot]') {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'not-dependabot');\n return;\n}\nif (pr.draft) {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'draft');\n return;\n}\ncore.exportVariable('PR_NUMBER', String(pr.number));\ncore.exportVariable('PR_TITLE', pr.title);\ncore.exportVariable('PR_HEAD_REF', pr.head.ref);\ncore.exportVariable('PR_BASE_REF', pr.base.ref);\ncore.exportVariable('PR_AUTHOR', pr.user.login);\ncore.exportVariable('PR_HEAD_SHA', pr.head.sha);\n\n// Look up the most recent PR Validation workflow run for this head SHA.\n// It may still be in progress when pull_request_target fires.\nlet conclusion = 'pending';\nlet runUrl = '';\ntry {\n const { data } = await github.rest.actions.listWorkflowRunsForRepo({\n owner: context.repo.owner,\n repo: context.repo.repo,\n head_sha: pr.head.sha,\n event: 'pull_request',\n per_page: 30,\n });\n const validation = (data.workflow_runs || []).find(r => r.name === 'PR Validation');\n if (validation) {\n runUrl = validation.html_url || '';\n conclusion = validation.status === 'completed'\n ? (validation.conclusion || 'unknown')\n : `in_progress:${validation.status}`;\n }\n} catch (err) {\n core.warning(`Failed to look up PR Validation run: ${err.message}`);\n}\ncore.exportVariable('PR_VALIDATION_CONCLUSION', conclusion);\ncore.exportVariable('PR_VALIDATION_RUN_URL', runUrl);\ncore.info(`Resolved PR #${pr.number} (${pr.title}); PR Validation conclusion: ${conclusion}`);\n" + script: "const run = context.payload.workflow_run;\nif (!run) {\n core.setFailed('workflow_run payload missing');\n return;\n}\nif (run.event !== 'pull_request') {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'not-a-pr-run');\n return;\n}\n\nlet pr = (run.pull_requests || [])[0];\nif (!pr) {\n // Fork PRs do not appear in workflow_run.pull_requests; fall back to search.\n const q = `repo:${context.repo.owner}/${context.repo.repo} is:pr sha:${run.head_sha}`;\n const { data } = await github.rest.search.issuesAndPullRequests({ q });\n const hit = (data.items || [])[0];\n if (!hit) {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'pr-resolution-failed');\n return;\n }\n const { data: full } = await github.rest.pulls.get({\n owner: context.repo.owner,\n repo: context.repo.repo,\n pull_number: hit.number,\n });\n pr = full;\n} else {\n // Hydrate the full PR object so fields like `body` and `draft` are reliable.\n const { data: full } = await github.rest.pulls.get({\n owner: context.repo.owner,\n repo: context.repo.repo,\n pull_number: pr.number,\n });\n pr = full;\n}\n\nif (pr.user.login !== 'dependabot[bot]') {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'not-dependabot');\n return;\n}\nif (pr.draft) {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'draft');\n return;\n}\n\ncore.exportVariable('PR_NUMBER', String(pr.number));\ncore.exportVariable('PR_TITLE', pr.title);\ncore.exportVariable('PR_HEAD_REF', pr.head.ref);\ncore.exportVariable('PR_BASE_REF', pr.base.ref);\ncore.exportVariable('PR_AUTHOR', pr.user.login);\ncore.exportVariable('PR_HEAD_SHA', pr.head.sha);\n\n// PR Validation conclusion comes directly from the triggering workflow_run payload;\n// it is always final under `types: [completed]`.\ncore.exportVariable('PR_VALIDATION_CONCLUSION', run.conclusion || 'unknown');\ncore.exportVariable('PR_VALIDATION_RUN_URL', run.html_url || '');\n\n// Resolve per-surface check-runs ONCE here so the persona does not re-walk them.\nlet failing = [];\ntry {\n const { data: checks } = await github.rest.checks.listForRef({\n owner: context.repo.owner,\n repo: context.repo.repo,\n ref: pr.head.sha,\n per_page: 100,\n });\n failing = (checks.check_runs || [])\n .filter(c => c.status === 'completed'\n && !['success', 'neutral', 'skipped'].includes(c.conclusion))\n .map(c => ({ name: c.name, html_url: c.html_url, conclusion: c.conclusion }));\n} catch (err) {\n core.warning(`Failed to enumerate check-runs: ${err.message}`);\n}\ncore.exportVariable('PR_VALIDATION_FAILING_CHECKS', JSON.stringify(failing));\n\n// Hydrate Dependabot enrichment input from REST so the agent does not depend on\n// the integrity-filtered MCP read of the PR body.\ncore.exportVariable('PR_BODY', pr.body || '');\n\ncore.info(`Resolved PR #${pr.number} (${pr.title}); PR Validation conclusion: ${run.conclusion}; failing checks: ${failing.length}`);\n" - name: Configure Git credentials env: @@ -509,15 +492,15 @@ 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_a6000a4bbc0dff64_EOF' - {"add_comment":{"max":2,"target":"triggering"},"create_pull_request_review_comment":{"max":5,"side":"RIGHT"},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{},"submit_pull_request_review":{"max":1}} - GH_AW_SAFE_OUTPUTS_CONFIG_a6000a4bbc0dff64_EOF + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_1092981f5bf7e3ab_EOF' + {"add_comment":{"max":2,"target":"${{ env.PR_NUMBER }}"},"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"},"report_incomplete":{},"submit_pull_request_review":{"max":1,"target":"${{ env.PR_NUMBER }}"}} + GH_AW_SAFE_OUTPUTS_CONFIG_1092981f5bf7e3ab_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | { "description_suffixes": { - "add_comment": " CONSTRAINTS: Maximum 2 comment(s) can be added. Target: triggering. Supports reply_to_id for discussion threading.", + "add_comment": " CONSTRAINTS: Maximum 2 comment(s) can be added. Target: ${{ env.PR_NUMBER }}. Supports reply_to_id for discussion threading.", "create_pull_request_review_comment": " CONSTRAINTS: Maximum 5 review comment(s) can be created. Comments will be on the RIGHT side of the diff.", "submit_pull_request_review": " CONSTRAINTS: Maximum 1 review(s) can be submitted." }, @@ -757,7 +740,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_658c528aa9fae3bb_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_85a1043331f22ef5_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "github": { @@ -798,7 +781,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_658c528aa9fae3bb_EOF + GH_AW_MCP_CONFIG_85a1043331f22ef5_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true @@ -1378,8 +1361,8 @@ jobs: pre_activation: if: > - github.event.pull_request != null && startsWith(github.event.pull_request.head.ref, 'dependabot/') && - github.event.pull_request.user.login == 'dependabot[bot]' && !github.event.pull_request.draft + github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.actor.login == 'dependabot[bot]' && contains(fromJSON('["success","failure","cancelled","timed_out","neutral","skipped","action_required"]'), + github.event.workflow_run.conclusion) runs-on: ubuntu-slim outputs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} @@ -1401,7 +1384,6 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_REQUIRED_ROLES: "admin,maintainer,write" - GH_AW_ALLOWED_BOTS: "dependabot[bot]" with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | @@ -1485,7 +1467,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.docker.com,*.docker.io,*.githubusercontent.com,*.pythonhosted.org,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.osv.dev,api.snapcraft.io,apt.releases.hashicorp.com,archive.ubuntu.com,auth.docker.io,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,cdn.jsdelivr.net,codeload.github.com,conda.anaconda.org,conda.binstar.org,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,deb.nodesource.com,deno.land,dl.k8s.io,docs.github.com,esm.sh,files.pythonhosted.org,gcr.io,get.pnpm.io,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,mcr.microsoft.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,objects.githubusercontent.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,pip.pypa.io,pkg.go.dev,pkgs.k8s.io,ppa.launchpad.net,production.cloudflare.docker.com,proxy.golang.org,pypi.org,pypi.python.org,quay.io,raw.githubusercontent.com,registry.bower.io,registry.hub.docker.com,registry.npmjs.com,registry.npmjs.org,registry.terraform.io,registry.yarnpkg.com,releases.hashicorp.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,s.symcb.com,s.symcd.com,security.ubuntu.com,services.nvd.nist.gov,skimdb.npmjs.com,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com,www.npmjs.com,www.npmjs.org,yarnpkg.com,yum.releases.hashicorp.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":2,\"target\":\"triggering\"},\"create_pull_request_review_comment\":{\"max\":5,\"side\":\"RIGHT\"},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{},\"submit_pull_request_review\":{\"max\":1}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":2,\"target\":\"${{ env.PR_NUMBER }}\"},\"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\"},\"report_incomplete\":{},\"submit_pull_request_review\":{\"max\":1,\"target\":\"${{ env.PR_NUMBER }}\"}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | From 30868d41cb6f704abfcb44ca2e45226f909822a1 Mon Sep 17 00:00:00 2001 From: katriendg Date: Mon, 11 May 2026 14:23:08 +0000 Subject: [PATCH 5/9] fix(agents): address PR review feedback on resolver robustness MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Disambiguate fork-PR search fallback by filtering to open Dependabot PRs with matching SHA; fail loudly on ambiguity - Paginate checks.listForRef to avoid silently missing check-runs when the CI matrix grows beyond a single page 🤖 - Generated by Copilot --- .../aw-dependabot-pr-review.lock.yml | 28 +++++++++---------- .github/workflows/aw-dependabot-pr-review.md | 22 ++++++++++----- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/.github/workflows/aw-dependabot-pr-review.lock.yml b/.github/workflows/aw-dependabot-pr-review.lock.yml index 07bddf87..b0f37619 100644 --- a/.github/workflows/aw-dependabot-pr-review.lock.yml +++ b/.github/workflows/aw-dependabot-pr-review.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"cfc76a9382771b49f7a1c754e06a15c3c365b0cc269ac1203bec149b73fbc281","compiler_version":"v0.71.5","strict":true,"agent_id":"copilot"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"24b6c6f55e12179ced2c38016bba01a29fcda32c3d1ea10310f7fad47b4570b6","compiler_version":"v0.71.5","strict":true,"agent_id":"copilot"} # gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"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":"373c709c69115d41ff229c7e5df9f8788daa9553"},{"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/setup-python","sha":"a309ff8b426b58ec0e2a45f0f869d46889d02405","version":"v6.2.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"astral-sh/setup-uv","sha":"08807647e7069bb48b6ef5acd8ec9567f424441b","version":"v8.1.0"},{"repo":"github/gh-aw-actions/setup","sha":"b8068426813005612b960b5ab0b8bd2c27142323","version":"v0.71.5"},{"repo":"hashicorp/setup-terraform","sha":"5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85","version":"5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85"},{"repo":"terraform-linters/setup-tflint","sha":"b480b8fcdaa6f2c577f8e4fa799e89e756bb7c93","version":"b480b8fcdaa6f2c577f8e4fa799e89e756bb7c93"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.40","digest":"sha256:14ff567e8d9d4c2fbc5e55c973488381c71d7e0fdbe72d30ee7b8a738fd86504","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.40@sha256:14ff567e8d9d4c2fbc5e55c973488381c71d7e0fdbe72d30ee7b8a738fd86504"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.40","digest":"sha256:2883ca3e5ae9f330cafdd9345bfd4ae17fc8da36c96d4c9a1f76e922b4c45280","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.40@sha256:2883ca3e5ae9f330cafdd9345bfd4ae17fc8da36c96d4c9a1f76e922b4c45280"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.40","digest":"sha256:b084f4a2c771f584ee68084ced52fa6b3245197a1889645d817462d307d3ac51","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.40@sha256:b084f4a2c771f584ee68084ced52fa6b3245197a1889645d817462d307d3ac51"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -197,20 +197,20 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_a27685d308878644_EOF' + cat << 'GH_AW_PROMPT_418fa511ea3c5b8e_EOF' - GH_AW_PROMPT_a27685d308878644_EOF + GH_AW_PROMPT_418fa511ea3c5b8e_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/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_a27685d308878644_EOF' + cat << 'GH_AW_PROMPT_418fa511ea3c5b8e_EOF' Tools: add_comment(max:2), create_pull_request_review_comment(max:5), submit_pull_request_review, missing_tool, missing_data, noop - GH_AW_PROMPT_a27685d308878644_EOF + GH_AW_PROMPT_418fa511ea3c5b8e_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_a27685d308878644_EOF' + cat << 'GH_AW_PROMPT_418fa511ea3c5b8e_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -239,13 +239,13 @@ jobs: {{/if}} - GH_AW_PROMPT_a27685d308878644_EOF + GH_AW_PROMPT_418fa511ea3c5b8e_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_a27685d308878644_EOF' + cat << 'GH_AW_PROMPT_418fa511ea3c5b8e_EOF' {{#runtime-import .github/agents/dependabot-pr-reviewer.agent.md}} {{#runtime-import .github/workflows/aw-dependabot-pr-review.md}} - GH_AW_PROMPT_a27685d308878644_EOF + GH_AW_PROMPT_418fa511ea3c5b8e_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -429,7 +429,7 @@ jobs: name: Resolve Dependabot PR context from workflow_run uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # 373c709c69115d41ff229c7e5df9f8788daa9553 with: - script: "const run = context.payload.workflow_run;\nif (!run) {\n core.setFailed('workflow_run payload missing');\n return;\n}\nif (run.event !== 'pull_request') {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'not-a-pr-run');\n return;\n}\n\nlet pr = (run.pull_requests || [])[0];\nif (!pr) {\n // Fork PRs do not appear in workflow_run.pull_requests; fall back to search.\n const q = `repo:${context.repo.owner}/${context.repo.repo} is:pr sha:${run.head_sha}`;\n const { data } = await github.rest.search.issuesAndPullRequests({ q });\n const hit = (data.items || [])[0];\n if (!hit) {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'pr-resolution-failed');\n return;\n }\n const { data: full } = await github.rest.pulls.get({\n owner: context.repo.owner,\n repo: context.repo.repo,\n pull_number: hit.number,\n });\n pr = full;\n} else {\n // Hydrate the full PR object so fields like `body` and `draft` are reliable.\n const { data: full } = await github.rest.pulls.get({\n owner: context.repo.owner,\n repo: context.repo.repo,\n pull_number: pr.number,\n });\n pr = full;\n}\n\nif (pr.user.login !== 'dependabot[bot]') {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'not-dependabot');\n return;\n}\nif (pr.draft) {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'draft');\n return;\n}\n\ncore.exportVariable('PR_NUMBER', String(pr.number));\ncore.exportVariable('PR_TITLE', pr.title);\ncore.exportVariable('PR_HEAD_REF', pr.head.ref);\ncore.exportVariable('PR_BASE_REF', pr.base.ref);\ncore.exportVariable('PR_AUTHOR', pr.user.login);\ncore.exportVariable('PR_HEAD_SHA', pr.head.sha);\n\n// PR Validation conclusion comes directly from the triggering workflow_run payload;\n// it is always final under `types: [completed]`.\ncore.exportVariable('PR_VALIDATION_CONCLUSION', run.conclusion || 'unknown');\ncore.exportVariable('PR_VALIDATION_RUN_URL', run.html_url || '');\n\n// Resolve per-surface check-runs ONCE here so the persona does not re-walk them.\nlet failing = [];\ntry {\n const { data: checks } = await github.rest.checks.listForRef({\n owner: context.repo.owner,\n repo: context.repo.repo,\n ref: pr.head.sha,\n per_page: 100,\n });\n failing = (checks.check_runs || [])\n .filter(c => c.status === 'completed'\n && !['success', 'neutral', 'skipped'].includes(c.conclusion))\n .map(c => ({ name: c.name, html_url: c.html_url, conclusion: c.conclusion }));\n} catch (err) {\n core.warning(`Failed to enumerate check-runs: ${err.message}`);\n}\ncore.exportVariable('PR_VALIDATION_FAILING_CHECKS', JSON.stringify(failing));\n\n// Hydrate Dependabot enrichment input from REST so the agent does not depend on\n// the integrity-filtered MCP read of the PR body.\ncore.exportVariable('PR_BODY', pr.body || '');\n\ncore.info(`Resolved PR #${pr.number} (${pr.title}); PR Validation conclusion: ${run.conclusion}; failing checks: ${failing.length}`);\n" + script: "const run = context.payload.workflow_run;\nif (!run) {\n core.setFailed('workflow_run payload missing');\n return;\n}\nif (run.event !== 'pull_request') {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'not-a-pr-run');\n return;\n}\n\nlet pr = (run.pull_requests || [])[0];\nif (!pr) {\n // Fork PRs do not appear in workflow_run.pull_requests; fall back to search.\n // Filter to open Dependabot PRs with the exact head SHA to avoid ambiguity\n // when Dependabot opens several PRs in the same batch.\n const q = `repo:${context.repo.owner}/${context.repo.repo} is:pr is:open author:app/dependabot sha:${run.head_sha}`;\n const { data } = await github.rest.search.issuesAndPullRequests({ q });\n const matches = (data.items || []).filter(i =>\n i.user.login === 'dependabot[bot]' && i.state === 'open');\n if (matches.length === 0) {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'pr-resolution-failed');\n return;\n }\n if (matches.length > 1) {\n core.setFailed(`Ambiguous PR resolution: ${matches.length} open Dependabot PRs match SHA ${run.head_sha}`);\n return;\n }\n const { data: full } = await github.rest.pulls.get({\n owner: context.repo.owner,\n repo: context.repo.repo,\n pull_number: matches[0].number,\n });\n pr = full;\n} else {\n // Hydrate the full PR object so fields like `body` and `draft` are reliable.\n const { data: full } = await github.rest.pulls.get({\n owner: context.repo.owner,\n repo: context.repo.repo,\n pull_number: pr.number,\n });\n pr = full;\n}\n\nif (pr.user.login !== 'dependabot[bot]') {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'not-dependabot');\n return;\n}\nif (pr.draft) {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'draft');\n return;\n}\n\ncore.exportVariable('PR_NUMBER', String(pr.number));\ncore.exportVariable('PR_TITLE', pr.title);\ncore.exportVariable('PR_HEAD_REF', pr.head.ref);\ncore.exportVariable('PR_BASE_REF', pr.base.ref);\ncore.exportVariable('PR_AUTHOR', pr.user.login);\ncore.exportVariable('PR_HEAD_SHA', pr.head.sha);\n\n// PR Validation conclusion comes directly from the triggering workflow_run payload;\n// it is always final under `types: [completed]`.\ncore.exportVariable('PR_VALIDATION_CONCLUSION', run.conclusion || 'unknown');\ncore.exportVariable('PR_VALIDATION_RUN_URL', run.html_url || '');\n\n// Resolve per-surface check-runs ONCE here so the persona does not re-walk them.\n// Paginate to avoid silently missing checks when the matrix grows beyond a single page.\nlet failing = [];\ntry {\n const checkRuns = await github.paginate(github.rest.checks.listForRef, {\n owner: context.repo.owner,\n repo: context.repo.repo,\n ref: pr.head.sha,\n per_page: 100,\n }, response => response.data.check_runs);\n failing = checkRuns\n .filter(c => c.status === 'completed'\n && !['success', 'neutral', 'skipped'].includes(c.conclusion))\n .map(c => ({ name: c.name, html_url: c.html_url, conclusion: c.conclusion }));\n} catch (err) {\n core.warning(`Failed to enumerate check-runs: ${err.message}`);\n}\ncore.exportVariable('PR_VALIDATION_FAILING_CHECKS', JSON.stringify(failing));\n\n// Hydrate Dependabot enrichment input from REST so the agent does not depend on\n// the integrity-filtered MCP read of the PR body.\ncore.exportVariable('PR_BODY', pr.body || '');\n\ncore.info(`Resolved PR #${pr.number} (${pr.title}); PR Validation conclusion: ${run.conclusion}; failing checks: ${failing.length}`);\n" - name: Configure Git credentials env: @@ -492,9 +492,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_1092981f5bf7e3ab_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_c47b816a376ea069_EOF' {"add_comment":{"max":2,"target":"${{ env.PR_NUMBER }}"},"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"},"report_incomplete":{},"submit_pull_request_review":{"max":1,"target":"${{ env.PR_NUMBER }}"}} - GH_AW_SAFE_OUTPUTS_CONFIG_1092981f5bf7e3ab_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_c47b816a376ea069_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -740,7 +740,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_85a1043331f22ef5_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_e7c028e8ba453c23_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "github": { @@ -781,7 +781,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_85a1043331f22ef5_EOF + GH_AW_MCP_CONFIG_e7c028e8ba453c23_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true diff --git a/.github/workflows/aw-dependabot-pr-review.md b/.github/workflows/aw-dependabot-pr-review.md index bdcb9186..2b44ba43 100644 --- a/.github/workflows/aw-dependabot-pr-review.md +++ b/.github/workflows/aw-dependabot-pr-review.md @@ -81,17 +81,24 @@ steps: let pr = (run.pull_requests || [])[0]; if (!pr) { // Fork PRs do not appear in workflow_run.pull_requests; fall back to search. - const q = `repo:${context.repo.owner}/${context.repo.repo} is:pr sha:${run.head_sha}`; + // Filter to open Dependabot PRs with the exact head SHA to avoid ambiguity + // when Dependabot opens several PRs in the same batch. + const q = `repo:${context.repo.owner}/${context.repo.repo} is:pr is:open author:app/dependabot sha:${run.head_sha}`; const { data } = await github.rest.search.issuesAndPullRequests({ q }); - const hit = (data.items || [])[0]; - if (!hit) { + const matches = (data.items || []).filter(i => + i.user.login === 'dependabot[bot]' && i.state === 'open'); + if (matches.length === 0) { core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'pr-resolution-failed'); return; } + if (matches.length > 1) { + core.setFailed(`Ambiguous PR resolution: ${matches.length} open Dependabot PRs match SHA ${run.head_sha}`); + return; + } const { data: full } = await github.rest.pulls.get({ owner: context.repo.owner, repo: context.repo.repo, - pull_number: hit.number, + pull_number: matches[0].number, }); pr = full; } else { @@ -126,15 +133,16 @@ steps: core.exportVariable('PR_VALIDATION_RUN_URL', run.html_url || ''); // Resolve per-surface check-runs ONCE here so the persona does not re-walk them. + // Paginate to avoid silently missing checks when the matrix grows beyond a single page. let failing = []; try { - const { data: checks } = await github.rest.checks.listForRef({ + const checkRuns = await github.paginate(github.rest.checks.listForRef, { owner: context.repo.owner, repo: context.repo.repo, ref: pr.head.sha, per_page: 100, - }); - failing = (checks.check_runs || []) + }, response => response.data.check_runs); + failing = checkRuns .filter(c => c.status === 'completed' && !['success', 'neutral', 'skipped'].includes(c.conclusion)) .map(c => ({ name: c.name, html_url: c.html_url, conclusion: c.conclusion })); From a23692a991ae6d8144f8ca5afbf1062285bd6372 Mon Sep 17 00:00:00 2001 From: katriendg Date: Mon, 11 May 2026 14:24:20 +0000 Subject: [PATCH 6/9] refactor(agents): drop dead conclusion fallback and consolidate lint exclusions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove || 'unknown' fallback on run.conclusion since workflow_run types: [completed] guarantees conclusion is set - Consolidate lock file exclusions in Invoke-YamlLint.ps1 to a single post-filter; drop redundant inline exclusions 🤖 - Generated by Copilot --- .../aw-dependabot-pr-review.lock.yml | 28 +++++++++---------- .github/workflows/aw-dependabot-pr-review.md | 2 +- scripts/linting/Invoke-YamlLint.ps1 | 6 ++-- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/aw-dependabot-pr-review.lock.yml b/.github/workflows/aw-dependabot-pr-review.lock.yml index b0f37619..fac9c206 100644 --- a/.github/workflows/aw-dependabot-pr-review.lock.yml +++ b/.github/workflows/aw-dependabot-pr-review.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"24b6c6f55e12179ced2c38016bba01a29fcda32c3d1ea10310f7fad47b4570b6","compiler_version":"v0.71.5","strict":true,"agent_id":"copilot"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"796edc7da795ef61575b0fb90f636ab54226337d2f4096f917a5e6c7282c6ec0","compiler_version":"v0.71.5","strict":true,"agent_id":"copilot"} # gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"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":"373c709c69115d41ff229c7e5df9f8788daa9553"},{"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/setup-python","sha":"a309ff8b426b58ec0e2a45f0f869d46889d02405","version":"v6.2.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"astral-sh/setup-uv","sha":"08807647e7069bb48b6ef5acd8ec9567f424441b","version":"v8.1.0"},{"repo":"github/gh-aw-actions/setup","sha":"b8068426813005612b960b5ab0b8bd2c27142323","version":"v0.71.5"},{"repo":"hashicorp/setup-terraform","sha":"5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85","version":"5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85"},{"repo":"terraform-linters/setup-tflint","sha":"b480b8fcdaa6f2c577f8e4fa799e89e756bb7c93","version":"b480b8fcdaa6f2c577f8e4fa799e89e756bb7c93"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.40","digest":"sha256:14ff567e8d9d4c2fbc5e55c973488381c71d7e0fdbe72d30ee7b8a738fd86504","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.40@sha256:14ff567e8d9d4c2fbc5e55c973488381c71d7e0fdbe72d30ee7b8a738fd86504"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.40","digest":"sha256:2883ca3e5ae9f330cafdd9345bfd4ae17fc8da36c96d4c9a1f76e922b4c45280","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.40@sha256:2883ca3e5ae9f330cafdd9345bfd4ae17fc8da36c96d4c9a1f76e922b4c45280"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.40","digest":"sha256:b084f4a2c771f584ee68084ced52fa6b3245197a1889645d817462d307d3ac51","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.40@sha256:b084f4a2c771f584ee68084ced52fa6b3245197a1889645d817462d307d3ac51"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -197,20 +197,20 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_418fa511ea3c5b8e_EOF' + cat << 'GH_AW_PROMPT_3b155fcff95403e4_EOF' - GH_AW_PROMPT_418fa511ea3c5b8e_EOF + GH_AW_PROMPT_3b155fcff95403e4_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/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_418fa511ea3c5b8e_EOF' + cat << 'GH_AW_PROMPT_3b155fcff95403e4_EOF' Tools: add_comment(max:2), create_pull_request_review_comment(max:5), submit_pull_request_review, missing_tool, missing_data, noop - GH_AW_PROMPT_418fa511ea3c5b8e_EOF + GH_AW_PROMPT_3b155fcff95403e4_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_418fa511ea3c5b8e_EOF' + cat << 'GH_AW_PROMPT_3b155fcff95403e4_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -239,13 +239,13 @@ jobs: {{/if}} - GH_AW_PROMPT_418fa511ea3c5b8e_EOF + GH_AW_PROMPT_3b155fcff95403e4_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_418fa511ea3c5b8e_EOF' + cat << 'GH_AW_PROMPT_3b155fcff95403e4_EOF' {{#runtime-import .github/agents/dependabot-pr-reviewer.agent.md}} {{#runtime-import .github/workflows/aw-dependabot-pr-review.md}} - GH_AW_PROMPT_418fa511ea3c5b8e_EOF + GH_AW_PROMPT_3b155fcff95403e4_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -429,7 +429,7 @@ jobs: name: Resolve Dependabot PR context from workflow_run uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # 373c709c69115d41ff229c7e5df9f8788daa9553 with: - script: "const run = context.payload.workflow_run;\nif (!run) {\n core.setFailed('workflow_run payload missing');\n return;\n}\nif (run.event !== 'pull_request') {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'not-a-pr-run');\n return;\n}\n\nlet pr = (run.pull_requests || [])[0];\nif (!pr) {\n // Fork PRs do not appear in workflow_run.pull_requests; fall back to search.\n // Filter to open Dependabot PRs with the exact head SHA to avoid ambiguity\n // when Dependabot opens several PRs in the same batch.\n const q = `repo:${context.repo.owner}/${context.repo.repo} is:pr is:open author:app/dependabot sha:${run.head_sha}`;\n const { data } = await github.rest.search.issuesAndPullRequests({ q });\n const matches = (data.items || []).filter(i =>\n i.user.login === 'dependabot[bot]' && i.state === 'open');\n if (matches.length === 0) {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'pr-resolution-failed');\n return;\n }\n if (matches.length > 1) {\n core.setFailed(`Ambiguous PR resolution: ${matches.length} open Dependabot PRs match SHA ${run.head_sha}`);\n return;\n }\n const { data: full } = await github.rest.pulls.get({\n owner: context.repo.owner,\n repo: context.repo.repo,\n pull_number: matches[0].number,\n });\n pr = full;\n} else {\n // Hydrate the full PR object so fields like `body` and `draft` are reliable.\n const { data: full } = await github.rest.pulls.get({\n owner: context.repo.owner,\n repo: context.repo.repo,\n pull_number: pr.number,\n });\n pr = full;\n}\n\nif (pr.user.login !== 'dependabot[bot]') {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'not-dependabot');\n return;\n}\nif (pr.draft) {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'draft');\n return;\n}\n\ncore.exportVariable('PR_NUMBER', String(pr.number));\ncore.exportVariable('PR_TITLE', pr.title);\ncore.exportVariable('PR_HEAD_REF', pr.head.ref);\ncore.exportVariable('PR_BASE_REF', pr.base.ref);\ncore.exportVariable('PR_AUTHOR', pr.user.login);\ncore.exportVariable('PR_HEAD_SHA', pr.head.sha);\n\n// PR Validation conclusion comes directly from the triggering workflow_run payload;\n// it is always final under `types: [completed]`.\ncore.exportVariable('PR_VALIDATION_CONCLUSION', run.conclusion || 'unknown');\ncore.exportVariable('PR_VALIDATION_RUN_URL', run.html_url || '');\n\n// Resolve per-surface check-runs ONCE here so the persona does not re-walk them.\n// Paginate to avoid silently missing checks when the matrix grows beyond a single page.\nlet failing = [];\ntry {\n const checkRuns = await github.paginate(github.rest.checks.listForRef, {\n owner: context.repo.owner,\n repo: context.repo.repo,\n ref: pr.head.sha,\n per_page: 100,\n }, response => response.data.check_runs);\n failing = checkRuns\n .filter(c => c.status === 'completed'\n && !['success', 'neutral', 'skipped'].includes(c.conclusion))\n .map(c => ({ name: c.name, html_url: c.html_url, conclusion: c.conclusion }));\n} catch (err) {\n core.warning(`Failed to enumerate check-runs: ${err.message}`);\n}\ncore.exportVariable('PR_VALIDATION_FAILING_CHECKS', JSON.stringify(failing));\n\n// Hydrate Dependabot enrichment input from REST so the agent does not depend on\n// the integrity-filtered MCP read of the PR body.\ncore.exportVariable('PR_BODY', pr.body || '');\n\ncore.info(`Resolved PR #${pr.number} (${pr.title}); PR Validation conclusion: ${run.conclusion}; failing checks: ${failing.length}`);\n" + script: "const run = context.payload.workflow_run;\nif (!run) {\n core.setFailed('workflow_run payload missing');\n return;\n}\nif (run.event !== 'pull_request') {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'not-a-pr-run');\n return;\n}\n\nlet pr = (run.pull_requests || [])[0];\nif (!pr) {\n // Fork PRs do not appear in workflow_run.pull_requests; fall back to search.\n // Filter to open Dependabot PRs with the exact head SHA to avoid ambiguity\n // when Dependabot opens several PRs in the same batch.\n const q = `repo:${context.repo.owner}/${context.repo.repo} is:pr is:open author:app/dependabot sha:${run.head_sha}`;\n const { data } = await github.rest.search.issuesAndPullRequests({ q });\n const matches = (data.items || []).filter(i =>\n i.user.login === 'dependabot[bot]' && i.state === 'open');\n if (matches.length === 0) {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'pr-resolution-failed');\n return;\n }\n if (matches.length > 1) {\n core.setFailed(`Ambiguous PR resolution: ${matches.length} open Dependabot PRs match SHA ${run.head_sha}`);\n return;\n }\n const { data: full } = await github.rest.pulls.get({\n owner: context.repo.owner,\n repo: context.repo.repo,\n pull_number: matches[0].number,\n });\n pr = full;\n} else {\n // Hydrate the full PR object so fields like `body` and `draft` are reliable.\n const { data: full } = await github.rest.pulls.get({\n owner: context.repo.owner,\n repo: context.repo.repo,\n pull_number: pr.number,\n });\n pr = full;\n}\n\nif (pr.user.login !== 'dependabot[bot]') {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'not-dependabot');\n return;\n}\nif (pr.draft) {\n core.exportVariable('PR_DEPENDABOT_SKIP_REASON', 'draft');\n return;\n}\n\ncore.exportVariable('PR_NUMBER', String(pr.number));\ncore.exportVariable('PR_TITLE', pr.title);\ncore.exportVariable('PR_HEAD_REF', pr.head.ref);\ncore.exportVariable('PR_BASE_REF', pr.base.ref);\ncore.exportVariable('PR_AUTHOR', pr.user.login);\ncore.exportVariable('PR_HEAD_SHA', pr.head.sha);\n\n// PR Validation conclusion comes directly from the triggering workflow_run payload;\n// it is always final under `types: [completed]`.\ncore.exportVariable('PR_VALIDATION_CONCLUSION', run.conclusion);\ncore.exportVariable('PR_VALIDATION_RUN_URL', run.html_url || '');\n\n// Resolve per-surface check-runs ONCE here so the persona does not re-walk them.\n// Paginate to avoid silently missing checks when the matrix grows beyond a single page.\nlet failing = [];\ntry {\n const checkRuns = await github.paginate(github.rest.checks.listForRef, {\n owner: context.repo.owner,\n repo: context.repo.repo,\n ref: pr.head.sha,\n per_page: 100,\n }, response => response.data.check_runs);\n failing = checkRuns\n .filter(c => c.status === 'completed'\n && !['success', 'neutral', 'skipped'].includes(c.conclusion))\n .map(c => ({ name: c.name, html_url: c.html_url, conclusion: c.conclusion }));\n} catch (err) {\n core.warning(`Failed to enumerate check-runs: ${err.message}`);\n}\ncore.exportVariable('PR_VALIDATION_FAILING_CHECKS', JSON.stringify(failing));\n\n// Hydrate Dependabot enrichment input from REST so the agent does not depend on\n// the integrity-filtered MCP read of the PR body.\ncore.exportVariable('PR_BODY', pr.body || '');\n\ncore.info(`Resolved PR #${pr.number} (${pr.title}); PR Validation conclusion: ${run.conclusion}; failing checks: ${failing.length}`);\n" - name: Configure Git credentials env: @@ -492,9 +492,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_c47b816a376ea069_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_a1842f71406e823e_EOF' {"add_comment":{"max":2,"target":"${{ env.PR_NUMBER }}"},"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"},"report_incomplete":{},"submit_pull_request_review":{"max":1,"target":"${{ env.PR_NUMBER }}"}} - GH_AW_SAFE_OUTPUTS_CONFIG_c47b816a376ea069_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_a1842f71406e823e_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -740,7 +740,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_e7c028e8ba453c23_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_aec822c9675c7bde_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "github": { @@ -781,7 +781,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_e7c028e8ba453c23_EOF + GH_AW_MCP_CONFIG_aec822c9675c7bde_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true diff --git a/.github/workflows/aw-dependabot-pr-review.md b/.github/workflows/aw-dependabot-pr-review.md index 2b44ba43..1962c0ec 100644 --- a/.github/workflows/aw-dependabot-pr-review.md +++ b/.github/workflows/aw-dependabot-pr-review.md @@ -129,7 +129,7 @@ steps: // PR Validation conclusion comes directly from the triggering workflow_run payload; // it is always final under `types: [completed]`. - core.exportVariable('PR_VALIDATION_CONCLUSION', run.conclusion || 'unknown'); + core.exportVariable('PR_VALIDATION_CONCLUSION', run.conclusion); core.exportVariable('PR_VALIDATION_RUN_URL', run.html_url || ''); // Resolve per-surface check-runs ONCE here so the persona does not re-walk them. diff --git a/scripts/linting/Invoke-YamlLint.ps1 b/scripts/linting/Invoke-YamlLint.ps1 index d8bf8d3a..b8205c4f 100644 --- a/scripts/linting/Invoke-YamlLint.ps1 +++ b/scripts/linting/Invoke-YamlLint.ps1 @@ -68,19 +68,19 @@ function Invoke-YamlLintCore { Write-Host "Linting changed workflow files only (base: $BaseBranch)" $allChanged = @(Get-ChangedFilesFromGit -BaseBranch $BaseBranch -FileExtensions @('*.yml', '*.yaml')) $filesToLint = @($allChanged | Where-Object { - $_ -match '\.github[\\/]workflows[\\/]' -and $_ -notmatch '\.lock\.yml$' + $_ -match '\.github[\\/]workflows[\\/]' }) } else { Write-Host 'Linting all GitHub Actions workflow files' $workflowDir = Join-Path $repoRoot '.github/workflows' if (Test-Path $workflowDir) { - $filesToLint = @(Get-ChildItem -Path $workflowDir -Recurse -Include '*.yml', '*.yaml' -Exclude '*.lock.yml' -File | + $filesToLint = @(Get-ChildItem -Path $workflowDir -Recurse -Include '*.yml', '*.yaml' -File | Select-Object -ExpandProperty FullName) } } - # Exclude gh-aw compiler-generated lock files (machine-generated, not editable) + # Lock files are gh-aw machine-generated; never lint them. $filesToLint = @($filesToLint | Where-Object { $_ -notmatch '\.lock\.(yml|yaml)$' }) Write-Host "Found $(@($filesToLint).Count) workflow file(s) to lint" From e1c86f1d5456edd22f250e7e16d4368c44877c23 Mon Sep 17 00:00:00 2001 From: katriendg Date: Mon, 11 May 2026 14:28:14 +0000 Subject: [PATCH 7/9] chore: json linting --- scripts/linting/Invoke-YamlLint.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/linting/Invoke-YamlLint.ps1 b/scripts/linting/Invoke-YamlLint.ps1 index b8205c4f..8c50aa92 100644 --- a/scripts/linting/Invoke-YamlLint.ps1 +++ b/scripts/linting/Invoke-YamlLint.ps1 @@ -68,8 +68,8 @@ function Invoke-YamlLintCore { Write-Host "Linting changed workflow files only (base: $BaseBranch)" $allChanged = @(Get-ChangedFilesFromGit -BaseBranch $BaseBranch -FileExtensions @('*.yml', '*.yaml')) $filesToLint = @($allChanged | Where-Object { - $_ -match '\.github[\\/]workflows[\\/]' - }) + $_ -match '\.github[\\/]workflows[\\/]' + }) } else { Write-Host 'Linting all GitHub Actions workflow files' From c7f54f322cbb31d5f875d645b88e6f1cde5a98be Mon Sep 17 00:00:00 2001 From: katriendg Date: Mon, 11 May 2026 14:37:33 +0000 Subject: [PATCH 8/9] perf(agents): add concurrency job-discriminator for parallel PR reviews MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add concurrency.job-discriminator keyed on workflow_run.head_sha so independent Dependabot PR reviews run in parallel instead of serializing end-to-end through a single concurrency group 🤖 - Generated by Copilot --- .../aw-dependabot-pr-review.lock.yml | 30 +++++++++---------- .github/workflows/aw-dependabot-pr-review.md | 2 ++ 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/.github/workflows/aw-dependabot-pr-review.lock.yml b/.github/workflows/aw-dependabot-pr-review.lock.yml index fac9c206..b18154ae 100644 --- a/.github/workflows/aw-dependabot-pr-review.lock.yml +++ b/.github/workflows/aw-dependabot-pr-review.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"796edc7da795ef61575b0fb90f636ab54226337d2f4096f917a5e6c7282c6ec0","compiler_version":"v0.71.5","strict":true,"agent_id":"copilot"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"8280dd5a8cb5dbb66ef96aa1668da8329aa3d131e6be219cf8a5622c696ccc49","compiler_version":"v0.71.5","strict":true,"agent_id":"copilot"} # gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"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":"373c709c69115d41ff229c7e5df9f8788daa9553"},{"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/setup-python","sha":"a309ff8b426b58ec0e2a45f0f869d46889d02405","version":"v6.2.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"astral-sh/setup-uv","sha":"08807647e7069bb48b6ef5acd8ec9567f424441b","version":"v8.1.0"},{"repo":"github/gh-aw-actions/setup","sha":"b8068426813005612b960b5ab0b8bd2c27142323","version":"v0.71.5"},{"repo":"hashicorp/setup-terraform","sha":"5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85","version":"5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85"},{"repo":"terraform-linters/setup-tflint","sha":"b480b8fcdaa6f2c577f8e4fa799e89e756bb7c93","version":"b480b8fcdaa6f2c577f8e4fa799e89e756bb7c93"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.40","digest":"sha256:14ff567e8d9d4c2fbc5e55c973488381c71d7e0fdbe72d30ee7b8a738fd86504","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.40@sha256:14ff567e8d9d4c2fbc5e55c973488381c71d7e0fdbe72d30ee7b8a738fd86504"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.40","digest":"sha256:2883ca3e5ae9f330cafdd9345bfd4ae17fc8da36c96d4c9a1f76e922b4c45280","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.40@sha256:2883ca3e5ae9f330cafdd9345bfd4ae17fc8da36c96d4c9a1f76e922b4c45280"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.40","digest":"sha256:b084f4a2c771f584ee68084ced52fa6b3245197a1889645d817462d307d3ac51","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.40@sha256:b084f4a2c771f584ee68084ced52fa6b3245197a1889645d817462d307d3ac51"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -197,20 +197,20 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_3b155fcff95403e4_EOF' + cat << 'GH_AW_PROMPT_62143e0c441a6736_EOF' - GH_AW_PROMPT_3b155fcff95403e4_EOF + GH_AW_PROMPT_62143e0c441a6736_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/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_3b155fcff95403e4_EOF' + cat << 'GH_AW_PROMPT_62143e0c441a6736_EOF' Tools: add_comment(max:2), create_pull_request_review_comment(max:5), submit_pull_request_review, missing_tool, missing_data, noop - GH_AW_PROMPT_3b155fcff95403e4_EOF + GH_AW_PROMPT_62143e0c441a6736_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_3b155fcff95403e4_EOF' + cat << 'GH_AW_PROMPT_62143e0c441a6736_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -239,13 +239,13 @@ jobs: {{/if}} - GH_AW_PROMPT_3b155fcff95403e4_EOF + GH_AW_PROMPT_62143e0c441a6736_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_3b155fcff95403e4_EOF' + cat << 'GH_AW_PROMPT_62143e0c441a6736_EOF' {{#runtime-import .github/agents/dependabot-pr-reviewer.agent.md}} {{#runtime-import .github/workflows/aw-dependabot-pr-review.md}} - GH_AW_PROMPT_3b155fcff95403e4_EOF + GH_AW_PROMPT_62143e0c441a6736_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -328,7 +328,7 @@ jobs: contents: read pull-requests: read concurrency: - group: "gh-aw-copilot-${{ github.workflow }}" + group: "gh-aw-copilot-${{ github.workflow }}-${{ github.event.workflow_run.head_sha }}" env: DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} GH_AW_ASSETS_ALLOWED_EXTS: "" @@ -492,9 +492,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_a1842f71406e823e_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_7bc49ded57060af8_EOF' {"add_comment":{"max":2,"target":"${{ env.PR_NUMBER }}"},"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"},"report_incomplete":{},"submit_pull_request_review":{"max":1,"target":"${{ env.PR_NUMBER }}"}} - GH_AW_SAFE_OUTPUTS_CONFIG_a1842f71406e823e_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_7bc49ded57060af8_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -740,7 +740,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_aec822c9675c7bde_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_b5465a56f59782f6_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "github": { @@ -781,7 +781,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_aec822c9675c7bde_EOF + GH_AW_MCP_CONFIG_b5465a56f59782f6_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true @@ -1042,7 +1042,7 @@ jobs: issues: write pull-requests: write concurrency: - group: "gh-aw-conclusion-aw-dependabot-pr-review" + group: "gh-aw-conclusion-aw-dependabot-pr-review-${{ github.event.workflow_run.head_sha }}" cancel-in-progress: false outputs: incomplete_count: ${{ steps.report_incomplete.outputs.incomplete_count }} diff --git a/.github/workflows/aw-dependabot-pr-review.md b/.github/workflows/aw-dependabot-pr-review.md index 1962c0ec..f53ffc17 100644 --- a/.github/workflows/aw-dependabot-pr-review.md +++ b/.github/workflows/aw-dependabot-pr-review.md @@ -13,6 +13,8 @@ on: workflows: ["PR Validation"] types: [completed] branches: ["dependabot/**"] +concurrency: + job-discriminator: ${{ github.event.workflow_run.head_sha }} permissions: contents: read pull-requests: read From c7cc45ab8f3a87fce63fa1c2d1d1659807081a22 Mon Sep 17 00:00:00 2001 From: katriendg Date: Mon, 11 May 2026 14:41:32 +0000 Subject: [PATCH 9/9] docs(agents): note dead checkout step in Trigger Posture section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Clarify that the agent runs without a working tree and the compiler-generated checkout step is permanently skipped under workflow_run 🤖 - Generated by Copilot --- .github/workflows/aw-dependabot-pr-review.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/aw-dependabot-pr-review.md b/.github/workflows/aw-dependabot-pr-review.md index f53ffc17..025e23b3 100644 --- a/.github/workflows/aw-dependabot-pr-review.md +++ b/.github/workflows/aw-dependabot-pr-review.md @@ -210,9 +210,12 @@ which under `types: [completed]` is always one of `success`, `failure`, `cancell The resolver step exports `PR Validation`'s final conclusion directly from `context.payload.workflow_run.conclusion` (no separate `listWorkflowRunsForRepo` call), then enumerates per-surface check-runs once via `checks.listForRef` so the agent never has to walk the checks API itself. -The `checks: read` permission grants exactly that scope and nothing more. The agent must never attempt -to run validation tooling (`uv`, `pytest`, `npm ci`, `terraform`, `go`) from the bash tool because those -binaries are not visible inside the AWF firewall sandbox. +The `checks: read` permission grants exactly that scope and nothing more. The agent runs without a +working tree — all PR context comes from REST APIs in the resolver. Do not add a checkout step; the +compiler-generated "Checkout PR branch" step in the lock file is permanently skipped under +`workflow_run` because neither `github.event.pull_request` nor `github.event.issue.pull_request` is set. +The agent must never attempt to run validation tooling (`uv`, `pytest`, `npm ci`, `terraform`, `go`) +from the bash tool because those binaries are not visible inside the AWF firewall sandbox. The resolver step exports these environment variables for the agent to read: