From c0dece4d66c195100f764d772d614e427ecb1552 Mon Sep 17 00:00:00 2001 From: Muiris Woulfe Date: Thu, 29 Oct 2026 14:59:03 +0000 Subject: [PATCH 1/8] ci: restore unattended dependency updates Use native organization-billed Copilot inference after release initiation. Add a read-only branch probe to check access without merging into main. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: bbc1bf98-847f-4a02-9212-a22eaab288a5 --- .../skills/refresh-ci-dependencies/SKILL.md | 130 - .gitattributes | 1 + .github/aw/actions-lock.json | 9 + .github/workflows/actions.lock | 123 + .github/workflows/build.yml | 21 +- .github/workflows/release-initiate.yml | 31 +- .github/workflows/release-publish.yml | 2 +- .../workflows/test-copilot-org-billing.yml | 65 + .../workflows/update-ci-dependencies.lock.yml | 2240 +++++++++++++++++ .github/workflows/update-ci-dependencies.md | 250 ++ docs/dependency-management.md | 84 +- 11 files changed, 2791 insertions(+), 165 deletions(-) delete mode 100644 .agents/skills/refresh-ci-dependencies/SKILL.md create mode 100644 .gitattributes create mode 100644 .github/aw/actions-lock.json create mode 100644 .github/workflows/actions.lock create mode 100644 .github/workflows/test-copilot-org-billing.yml create mode 100644 .github/workflows/update-ci-dependencies.lock.yml create mode 100644 .github/workflows/update-ci-dependencies.md diff --git a/.agents/skills/refresh-ci-dependencies/SKILL.md b/.agents/skills/refresh-ci-dependencies/SKILL.md deleted file mode 100644 index 8ef6307f..00000000 --- a/.agents/skills/refresh-ci-dependencies/SKILL.md +++ /dev/null @@ -1,130 +0,0 @@ ---- -name: refresh-ci-dependencies -description: >- - Refresh SHA-pinned GitHub Actions and Azure DevOps task versions, and audit - Node.js runtime consistency on an open release pull request branch. - Run only with /refresh-ci-dependencies. -disable-model-invocation: true ---- - -Refresh the pinned versions in this repository's GitHub Actions workflows and -Azure DevOps pipelines, and enforce Node.js runtime consistency across them. Run -this on the branch of the open release pull request, before it is merged. - -## Context - -Run only when the user invokes `/refresh-ci-dependencies`. Do not run -automatically or in response to a general dependency update request. - -Run from the `release/vX.Y.Z` branch of the open release pull request. That pull -request is created by the `Release – Initiate` workflow, carries the `release` -label, and has a title beginning `[Autogenerated] Release v`. - -## Scope - -Edit only these files: - -- `.github/workflows/build.yml` -- `.github/workflows/release-initiate.yml` -- `.github/workflows/release-publish.yml` -- `.azure-devops/*.yml` -- `package.json` -- `.nvmrc` - -## GitHub Action SHAs - -In `.github/workflows/build.yml`, `release-initiate.yml`, and -`release-publish.yml`, each action is pinned as -`uses: owner/repo@<40-char SHA> # vX.Y.Z`. Some actions live in a subpath – -`uses: owner/repo/subpath@<40-char SHA> # vX.Y.Z`, such as -`github/codeql-action/init` and `github/codeql-action/analyze`; subpaths of the -same repository share one release and one SHA, so update them together. For each -action, resolve the latest release and its tag SHA, then update the SHA and the -trailing `# vX.Y.Z` comment together – never one without the other: - -```bash -gh api repos///releases/latest --jq '.tag_name' -gh api repos///git/refs/tags/ --jq '.object.sha' -``` - -`releases/latest` can return a tag that is not the action's version – for -example, `github/codeql-action` returns a `codeql-bundle-vX.Y.Z` tag. When the -latest tag does not match `vX.Y.Z`, list releases and take the newest `vX.Y.Z` -tag instead: - -```bash -gh api 'repos///releases?per_page=100' --jq '[.[].tag_name | select(test("^v[0-9]+\\.[0-9]+\\.[0-9]+$"))] | first' -``` - -If the tag points to an annotated tag object, dereference it with a second -`gh api` call against the tag object to obtain the commit SHA. - -## Azure DevOps Task Versions - -In `.azure-devops/*.yml`, tasks are pinned by major version as -`task: TaskName@N` – for example, `Npm@1`, `UseNode@1`, or `EsrpCodeSigning@6`. -Only the major version is declared; the latest minor or patch resolves at -runtime. For built-in tasks, confirm the latest major from the `Tasks/` folders -of the [`microsoft/azure-pipelines-tasks`][ado-tasks-repo] repository – an -`AzureCLIV3` folder means `@3` exists – and cross-check the -[Azure Pipelines task reference][ado-tasks] for inputs. Internal-extension -tasks – `EsrpCodeSigning`, `PoliCheck`, `PublishSecurityAnalysisLogs`, -`PostAnalysis`, and `ComponentGovernanceComponentDetection` – are in neither -source; leave them unless you can review their release notes. Never bump this -product's own `PRMetrics@N` task here. Bump a major version only after reviewing -its release notes and adjusting inputs accordingly. Add any newly required -inputs, and when an input is genuinely renamed, switch to its replacement. -Prefer the input name the task's [reference docs][ado-tasks] show in their YAML -syntax, which is not always the task.json `name`; do not replace a -still-supported input with an alias when neither is deprecated. For example, -`AzureCLI@3` adds a required `connectionType: azureRM` but keeps -`azureSubscription` – the documented input – even though its task.json `name` -is the older `connectedServiceNameARM`. This includes the `UseNode@1` task -version itself, but never the `version:` input it receives. - -## Node.js Version Consistency - -The pinned Node.js runtime must match everywhere it appears. Do not bump it to a -newer version – that is a separate, deliberate change. Audit only, and resolve -any divergence. Locate every occurrence: - -- `.github/workflows/build.yml`, `release-initiate.yml`, and - `release-publish.yml` – `node-version: X.Y.Z` under `actions/setup-node`. -- `.azure-devops/*.yml` – `UseNode@1` with `version: X.Y.Z`. -- `package.json` – `engines.node`. -- `.nvmrc`, if present. - -If values diverge, align them on the single intended pin. Prefer the value set -by the most recent deliberate bump – check `git log` on whichever file changed -most recently. Do not change the value itself. - -## Constraints - -- **Never Desynchronize an Action SHA and its Version Comment**: Update both in - the same edit. -- **Never Blindly Bump an Azure DevOps Task Major Version**: Review the release - notes and adjust inputs first. -- **Never Bump the Node.js Runtime Value**: Audit only. -- **Never Duplicate a Dependabot Pull Request**: If Dependabot already has an - open pull request for an action, rebase or merge it rather than producing a - competing change. -- **Never Edit Files Outside the Scope**: Only the files listed above may be - changed. - -## Finishing - -1. Preserve formatting: trailing newlines, comment spacing, and two-space - indentation. -1. Before committing, integrate the remote branch. While you work, the `Build` - workflow may auto-commit linting and `dist` updates to this branch, so the - local branch can fall behind. Run `git fetch`, then fast-forward or rebase - onto `origin/release/vX.Y.Z`, preserving any unrelated working-tree changes. - Stage only the files this skill changed. -1. Commit with the message `chore: refresh CI pins`. -1. Push to the release pull request branch with a plain fast-forward push – - never `--force`. Confirm exactly one new commit is added. -1. No manual verification is required. The `Build` workflow reruns on the push - and re-lints the modified files; any failure surfaces there. - -[ado-tasks]: https://learn.microsoft.com/azure/devops/pipelines/tasks/reference/ -[ado-tasks-repo]: https://github.com/microsoft/azure-pipelines-tasks diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..1f7549b5 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +.github/workflows/*.lock.yml linguist-generated=true \ No newline at end of file diff --git a/.github/aw/actions-lock.json b/.github/aw/actions-lock.json new file mode 100644 index 00000000..202a477d --- /dev/null +++ b/.github/aw/actions-lock.json @@ -0,0 +1,9 @@ +{ + "entries": { + "github/gh-aw-actions/setup@v1.0.1": { + "repo": "github/gh-aw-actions/setup", + "version": "v1.0.1", + "sha": "221ba4f4319de6b8e809d1a15528b3ae6a818aa5" + } + } +} diff --git a/.github/workflows/actions.lock b/.github/workflows/actions.lock new file mode 100644 index 00000000..f7ae5425 --- /dev/null +++ b/.github/workflows/actions.lock @@ -0,0 +1,123 @@ +# This file is machine-generated by `gh actions-lock`. +# Do not edit by hand; run `gh actions-lock` to update. +# Docs: https://gh.io/actions-lockfile +version: 'v0.0.3' +workflows: + '.github/workflows/build.yml': + - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' + - 'actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1' + - 'actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9' + - 'github/codeql-action@9b3254085494b55a0f7c4c2b3d2d52cc712ce370' + - 'super-linter/super-linter@2da136927bd4a73596db63044b504547c62cb854' + '.github/workflows/pr-automation.yml': + - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' + - 'actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c' + - 'actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a' + - 'azure/login@a641126d1b8aa4d1fa005f4f92df94a3a4c4c906' + '.github/workflows/release-initiate.yml': + - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' + - 'actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1' + - 'azure/login@a641126d1b8aa4d1fa005f4f92df94a3a4c4c906' + - 'grafana/github-api-commit-action@b1d81091e8480dd11fcea8bc1f0ab977a0376ca5' + '.github/workflows/release-publish.yml': + - 'actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8' + - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' + - 'actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1' + - 'actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9' + - 'azure/login@a641126d1b8aa4d1fa005f4f92df94a3a4c4c906' + - 'sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6' + '.github/workflows/test-copilot-org-billing.yml': + - 'actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1' + '.github/workflows/update-ci-dependencies.lock.yml': + - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' + - 'actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333' + - 'actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3' + - 'actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1' + - 'actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9' + - 'github/gh-aw-actions@221ba4f4319de6b8e809d1a15528b3ae6a818aa5' + - 'microsoft/pr-metrics@5fe360db472f2604e1d2c0f5d33600d033db40ae' +dependencies: + 'actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8': + ref: 'v4.2.2' + commit: 'sha1-4d101475d8b20a2381f78447822ac1eab6504dd8' + owner_id: 44036562 + repo_id: 760702757 + uses: + - 'actions/attest@508db95dd578ae2727ebd6217d5ba78e4fbda05d' + 'actions/attest@508db95dd578ae2727ebd6217d5ba78e4fbda05d': + ref: 'v4.2.1' + commit: 'sha1-508db95dd578ae2727ebd6217d5ba78e4fbda05d' + owner_id: 44036562 + repo_id: 760701061 + 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1': + ref: 'v7.0.1' + commit: 'sha1-3d3c42e5aac5ba805825da76410c181273ba90b1' + owner_id: 44036562 + repo_id: 197814629 + 'actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c': + ref: 'v8.0.1' + commit: 'sha1-3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c' + owner_id: 44036562 + repo_id: 192626254 + 'actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333': + ref: 'v8.0.2' + commit: 'sha1-9000827ccba6bdab643e8b6fd33ac0654aef8333' + owner_id: 44036562 + repo_id: 192626254 + 'actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3': + ref: 'v9.0.0' + commit: 'sha1-3a2844b7e9c422d3c10d287c895573f7108da1b3' + owner_id: 44036562 + repo_id: 205262760 + 'actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1': + ref: 'v7.1.0' + commit: 'sha1-949feb2413d6458794dcd2491c4babbbce0c15c1' + owner_id: 44036562 + repo_id: 189476904 + 'actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a': + ref: 'v7.0.1' + commit: 'sha1-043fb46d1a93c77aae656e7c1c64a875d1fc6a0a' + owner_id: 44036562 + repo_id: 192625955 + 'actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9': + ref: 'v7.0.2' + commit: 'sha1-cf430e030ddbb5b0abf93d22962f4752f3646cd9' + owner_id: 44036562 + repo_id: 192625955 + 'azure/login@a641126d1b8aa4d1fa005f4f92df94a3a4c4c906': + ref: 'v3.1.0' + commit: 'sha1-a641126d1b8aa4d1fa005f4f92df94a3a4c4c906' + owner_id: 6844498 + repo_id: 210798615 + 'github/codeql-action@9b3254085494b55a0f7c4c2b3d2d52cc712ce370': + ref: 'v4.39.1' + commit: 'sha1-9b3254085494b55a0f7c4c2b3d2d52cc712ce370' + owner_id: 9919 + repo_id: 259445878 + 'github/gh-aw-actions@221ba4f4319de6b8e809d1a15528b3ae6a818aa5': + ref: 'v1.0.1' + commit: 'sha1-221ba4f4319de6b8e809d1a15528b3ae6a818aa5' + owner_id: 9919 + repo_id: 1156386970 + 'grafana/github-api-commit-action@b1d81091e8480dd11fcea8bc1f0ab977a0376ca5': + ref: 'v1.0.0' + commit: 'sha1-b1d81091e8480dd11fcea8bc1f0ab977a0376ca5' + owner_id: 7195757 + repo_id: 631276923 + 'microsoft/pr-metrics@5fe360db472f2604e1d2c0f5d33600d033db40ae': + ref: 'v1.8.3' + commit: 'sha1-5fe360db472f2604e1d2c0f5d33600d033db40ae' + owner_id: 6154722 + repo_id: 309438703 + uses: + - 'azure/login@a641126d1b8aa4d1fa005f4f92df94a3a4c4c906' + 'sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6': + ref: 'v4.1.2' + commit: 'sha1-6f9f17788090df1f26f669e9d70d6ae9567deba6' + owner_id: 71096353 + repo_id: 351211695 + 'super-linter/super-linter@2da136927bd4a73596db63044b504547c62cb854': + ref: 'v9.0.0' + commit: 'sha1-2da136927bd4a73596db63044b504547c62cb854' + owner_id: 74564708 + repo_id: 216581567 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 20476813..acaa64dc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -104,7 +104,7 @@ jobs: uses: super-linter/super-linter@2da136927bd4a73596db63044b504547c62cb854 # v9.0.0 env: ENABLE_GITHUB_PULL_REQUEST_SUMMARY_COMMENT: false - FILTER_REGEX_EXCLUDE: .*dist/.* + FILTER_REGEX_EXCLUDE: .*(dist/|\.github/workflows/.*\.lock\.yml).* FIX_JSON_PRETTIER: true FIX_MARKDOWN_PRETTIER: true FIX_MARKDOWN: true @@ -141,13 +141,28 @@ jobs: build: name: Build runs-on: ubuntu-latest - permissions: {} + permissions: + contents: read steps: - name: Checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false + - name: Agentic Workflow – Verify + shell: bash + run: | + gh extension install github/gh-aw --pin v1.0.1 + gh aw compile update-ci-dependencies --validate --no-check-update + git diff --exit-code -- .github/workflows/update-ci-dependencies.lock.yml .github/aw/actions-lock.json + env: + GH_TOKEN: ${{ github.token }} + + - name: Workflow Lockfile – Verify + run: gh extension install github/gh-actions-lock --pin v0.4.0 && gh actions-lock --verify + env: + GH_TOKEN: ${{ github.token }} + - name: Install Node.js uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 with: @@ -217,7 +232,7 @@ jobs: uses: super-linter/super-linter@2da136927bd4a73596db63044b504547c62cb854 # v9.0.0 env: ENABLE_GITHUB_PULL_REQUEST_SUMMARY_COMMENT: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository }} - FILTER_REGEX_EXCLUDE: .*dist/.* + FILTER_REGEX_EXCLUDE: .*(dist/|\.github/workflows/.*\.lock\.yml).* GITHUB_TOKEN: ${{ github.token }} GITLEAKS_CONFIG_FILE: gitleaks.toml MARKDOWN_CONFIG_FILE: ../../.markdownlint.json diff --git a/.github/workflows/release-initiate.yml b/.github/workflows/release-initiate.yml index a6f2cf4f..6368cec6 100644 --- a/.github/workflows/release-initiate.yml +++ b/.github/workflows/release-initiate.yml @@ -23,15 +23,9 @@ jobs: contents: read id-token: write steps: - - name: Checkout – Action - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - sparse-checkout: .github/actions - - name: App Token – Mint id: app-token - uses: ./.github/actions/mint-github-app-token # zizmor: ignore[self-repository] + uses: $/.github/actions/mint-github-app-token with: azure-client-id: ${{ vars.AZURE_CLIENT_ID }} azure-tenant-id: ${{ vars.AZURE_TENANT_ID }} @@ -93,29 +87,6 @@ jobs: env: GITHUB_TOKEN: ${{ steps.app-token.outputs.token }} - - name: PR – Comment - run: |- - $body = @' - **Action required before merging** - - Check out this release branch, then start GitHub Copilot CLI from the repository root: - - ```bash - copilot - ``` - - In the interactive session, run this slash-command: - - ```text - /refresh-ci-dependencies - ``` - - The skill updates SHA-pinned GitHub Actions and supported Azure DevOps task versions, and checks Node.js runtime consistency without upgrading Node.js. It then commits and pushes to this branch. These checks cover pins that automated dependency updates do not cover. See `.agents/skills/refresh-ci-dependencies/SKILL.md`. The skill runs only when you invoke the slash-command. - '@ - gh pr comment "release/v$env:version" --body $body - env: - GITHUB_TOKEN: ${{ steps.app-token.outputs.token }} - - name: Install Node.js uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 with: diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml index 36af4c9a..25cf5692 100644 --- a/.github/workflows/release-publish.yml +++ b/.github/workflows/release-publish.yml @@ -36,7 +36,7 @@ jobs: - name: App Token – Mint id: app-token - uses: ./.github/actions/mint-github-app-token # zizmor: ignore[self-repository] + uses: $/.github/actions/mint-github-app-token with: azure-client-id: ${{ vars.AZURE_CLIENT_ID }} azure-tenant-id: ${{ vars.AZURE_TENANT_ID }} diff --git a/.github/workflows/test-copilot-org-billing.yml b/.github/workflows/test-copilot-org-billing.yml new file mode 100644 index 00000000..cdf0a2ec --- /dev/null +++ b/.github/workflows/test-copilot-org-billing.yml @@ -0,0 +1,65 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +--- +name: Copilot Org Billing Test + +on: + push: + branches: + - test/copilot-org-billing + paths: + - .github/workflows/test-copilot-org-billing.yml + +permissions: {} + +jobs: + billing: + if: github.repository == 'microsoft/PR-Metrics' && github.ref == 'refs/heads/test/copilot-org-billing' + name: Test Organization-Billed Inference + runs-on: ubuntu-latest + timeout-minutes: 5 + permissions: + contents: read + copilot-requests: write + steps: + - name: Install Node.js + uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 + with: + node-version: 24.18.1 + + - name: Install Copilot CLI + run: npm install --global --no-audit --no-fund @github/copilot@1.0.105 + + - name: Test Native Organization Billing + id: inference + shell: bash + working-directory: ${{ runner.temp }} + env: + COPILOT_GITHUB_TOKEN: ${{ github.token }} + run: | + set -euo pipefail + copilot \ + --prompt 'Do not use tools. Reply with exactly ORG_BILLING_OK and nothing else.' \ + --model auto \ + --silent \ + --no-color \ + --no-auto-update \ + --no-custom-instructions \ + --no-ask-user \ + --disable-builtin-mcps \ + --deny-tool '*' \ + --trust-folder \ + | tee copilot-org-billing-response.txt + + if [[ "$(cat copilot-org-billing-response.txt)" != 'ORG_BILLING_OK' ]]; then + echo '::error::Copilot did not return the expected billing test response.' + exit 1 + fi + + printf '%s\n' \ + '## Organization billing test passed' \ + 'Copilot returned the expected response using the native workflow GITHUB_TOKEN.' \ + 'No personal token, production credentials, or repository writes were used.' \ + 'This confirms inference access, not release pull request publishing.' \ + >> "$GITHUB_STEP_SUMMARY" diff --git a/.github/workflows/update-ci-dependencies.lock.yml b/.github/workflows/update-ci-dependencies.lock.yml new file mode 100644 index 00000000..4c73b270 --- /dev/null +++ b/.github/workflows/update-ci-dependencies.lock.yml @@ -0,0 +1,2240 @@ +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"83672948284a233c2dffb4bb365b3a3c22ca8b810f65ae545b27e3a851c82b14","body_hash":"480d779c1cfc2184da0b4930412fbc089a2bc8e68f52222db17a301700dbc09c","compiler_version":"v1.0.1","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.103"}} +# gh-aw-manifest: {"version":1,"secrets":["GH_AW_CI_TRIGGER_TOKEN","GH_AW_DEFAULT_OTLP_ENDPOINT","GH_AW_DEFAULT_OTLP_HEADERS","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/download-artifact","sha":"9000827ccba6bdab643e8b6fd33ac0654aef8333","version":"v8.0.2"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"949feb2413d6458794dcd2491c4babbbce0c15c1","version":"v7.1.0"},{"repo":"actions/upload-artifact","sha":"cf430e030ddbb5b0abf93d22962f4752f3646cd9","version":"v7.0.2"},{"repo":"github/gh-aw-actions/setup","sha":"221ba4f4319de6b8e809d1a15528b3ae6a818aa5","version":"v1.0.1"},{"repo":"microsoft/PR-Metrics/.github/actions/mint-github-app-token","sha":"5fe360db472f2604e1d2c0f5d33600d033db40ae","version":"5fe360db472f2604e1d2c0f5d33600d033db40ae"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.29.0","digest":"sha256:b14bd399376180b5649a9324be3b50fbfc82bfe8f0c80045840416b5a4e65b96","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.29.0@sha256:b14bd399376180b5649a9324be3b50fbfc82bfe8f0c80045840416b5a4e65b96"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.29.0","digest":"sha256:baff00b856a4bdc93bce134928c70af3d3492f2e518757115042040674d56b0b","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.29.0@sha256:baff00b856a4bdc93bce134928c70af3d3492f2e518757115042040674d56b0b"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.29.0","digest":"sha256:6e0cbf7f980beb78b5461563a8164f6439ca959bc93733d5a6b52972e523ed50","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.29.0@sha256:6e0cbf7f980beb78b5461563a8164f6439ca959bc93733d5a6b52972e523ed50"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.5.0","digest":"sha256:d3544a4222e7efeeeb38669d8a1af0c72691c55b8f6506b15aa5920f7f31b7bc","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.5.0@sha256:d3544a4222e7efeeeb38669d8a1af0c72691c55b8f6506b15aa5920f7f31b7bc"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:2c2ea524e648b91c8333ce246e3838fcf5b19ac70e45baac1a51b9207299749f","pinned_image":"ghcr.io/github/gh-aw-node@sha256:2c2ea524e648b91c8333ce246e3838fcf5b19ac70e45baac1a51b9207299749f"},{"image":"ghcr.io/github/github-mcp-server:v2.0.3","digest":"sha256:250bc6ce70788207608ef74cef4397230ff2e8481218da74d6093e4bd9101132","pinned_image":"ghcr.io/github/github-mcp-server:v2.0.3@sha256:250bc6ce70788207608ef74cef4397230ff2e8481218da74d6093e4bd9101132"}],"mcp_servers":[{"name":"github","tools":["get_commit","get_file_contents","get_latest_release","get_me","get_pull_request","get_pull_request_comments","get_pull_request_diff","get_pull_request_files","get_pull_request_review_comments","get_pull_request_reviews","get_pull_request_status","get_release_by_tag","get_tag","issue_read","list_branches","list_commits","list_issue_types","list_issues","list_pull_requests","list_releases","list_starred_repositories","list_tags","pull_request_read","search_code","search_issues","search_pull_requests","search_repositories"]},{"name":"safeoutputs","tools":["noop","push_to_pull_request_branch","report_incomplete","report_missing_data","report_missing_tool"]}],"threat_detection":{"mode":"enabled"},"admission":false} +# This file was automatically generated by gh-aw (v1.0.1). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md +# +# ___ _ _ +# / _ \ | | (_) +# | |_| | __ _ ___ _ __ | |_ _ ___ +# | _ |/ _` |/ _ \ '_ \| __| |/ __| +# | | | | (_| | __/ | | | |_| | (__ +# \_| |_/\__, |\___|_| |_|\__|_|\___| +# __/ | +# _ _ |___/ +# | | | | / _| | +# | | | | ___ _ __ _ __| |_| | _____ ____ +# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___| +# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ +# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ +# +# +# To update this file, edit the corresponding .md file and run: +# gh aw compile +# Not all edits will cause changes to this file. +# +# For more information: https://github.github.com/gh-aw/introduction/overview/ +# +# +# Secrets used: +# - GH_AW_CI_TRIGGER_TOKEN +# - GH_AW_DEFAULT_OTLP_ENDPOINT +# - GH_AW_DEFAULT_OTLP_HEADERS +# - GH_AW_GITHUB_MCP_SERVER_TOKEN +# - GH_AW_GITHUB_TOKEN +# - GITHUB_TOKEN +# +# Custom actions used: +# - actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 +# - actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 +# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 +# - actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 +# - actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 +# - github/gh-aw-actions/setup@221ba4f4319de6b8e809d1a15528b3ae6a818aa5 # v1.0.1 +# - microsoft/PR-Metrics/.github/actions/mint-github-app-token@5fe360db472f2604e1d2c0f5d33600d033db40ae +# +# Container images used: +# - ghcr.io/github/gh-aw-firewall/agent:0.29.0@sha256:b14bd399376180b5649a9324be3b50fbfc82bfe8f0c80045840416b5a4e65b96 +# - ghcr.io/github/gh-aw-firewall/api-proxy:0.29.0@sha256:baff00b856a4bdc93bce134928c70af3d3492f2e518757115042040674d56b0b +# - ghcr.io/github/gh-aw-firewall/squid:0.29.0@sha256:6e0cbf7f980beb78b5461563a8164f6439ca959bc93733d5a6b52972e523ed50 +# - ghcr.io/github/gh-aw-mcpg:v0.5.0@sha256:d3544a4222e7efeeeb38669d8a1af0c72691c55b8f6506b15aa5920f7f31b7bc +# - ghcr.io/github/gh-aw-node@sha256:2c2ea524e648b91c8333ce246e3838fcf5b19ac70e45baac1a51b9207299749f +# - ghcr.io/github/github-mcp-server:v2.0.3@sha256:250bc6ce70788207608ef74cef4397230ff2e8481218da74d6093e4bd9101132 + +name: "Update CI Dependencies" +on: + workflow_dispatch: + inputs: + aw_context: + default: "" + description: "Agent caller context (Reserved for Agentic Workflows)." + required: false + type: string + workflow_run: + # zizmor: ignore[dangerous-triggers] - workflow_run trigger is secured with role and fork validation + branches: + - main + types: + - completed + workflows: + - Release – Initiate + +# Jobs receive only their explicitly declared permissions. +permissions: {} + +concurrency: + cancel-in-progress: false + group: update-ci-dependencies + +run-name: "Update CI Dependencies" + +env: + OTEL_EXPORTER_OTLP_ENDPOINT: ${{ secrets.GH_AW_DEFAULT_OTLP_ENDPOINT || vars.GH_AW_DEFAULT_OTLP_ENDPOINT }} + OTEL_SERVICE_NAME: gh-aw.update-ci-dependencies + OTEL_RESOURCE_ATTRIBUTES: 'gh-aw.workflow.name=Update%20CI%20Dependencies,gh-aw.repository=${{ github.repository }},gh-aw.run.id=${{ github.run_id }},github.run_id=${{ github.run_id }},gh-aw.engine.id=copilot' + OTEL_EXPORTER_OTLP_HEADERS: ${{ secrets.GH_AW_DEFAULT_OTLP_HEADERS }} + GH_AW_OTLP_ENDPOINTS: '[{"url":"${{ secrets.GH_AW_DEFAULT_OTLP_ENDPOINT || vars.GH_AW_DEFAULT_OTLP_ENDPOINT }}","headers":"${{ secrets.GH_AW_DEFAULT_OTLP_HEADERS }}"}]' + GH_AW_OTLP_IF_MISSING: ignore + +jobs: + activation: + name: 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.ref == 'refs/heads/main' && (github.event_name == 'workflow_dispatch' || + (github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'workflow_dispatch' && + github.event.workflow_run.head_repository.full_name == github.repository)))) && (github.event_name != 'workflow_run' || + github.event.workflow_run != null && github.event.workflow_run.repository != null && github.event.workflow_run.repository.id == github.repository_id && + (!(github.event.workflow_run.repository.fork))) + runs-on: ubuntu-slim + # Permissions for the activation job (workflow permissions default to none). + permissions: + actions: read + contents: read + issues: write + env: + GH_AW_MAX_DAILY_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_DAILY_AI_CREDITS || '5000' }} + GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }} + outputs: + aw_context: ${{ steps.generate_aw_info.outputs.aw_context }} + comment_id: "" + comment_repo: "" + daily_ai_credits_estimated: ${{ steps.daily-ai-credits-workflow-guardrail.outputs.daily_ai_credits_estimated || '' }} + daily_ai_credits_exceeded: ${{ steps.daily-ai-credits-workflow-guardrail.outputs.daily_ai_credits_exceeded == 'true' }} + daily_ai_credits_guardrail_error: ${{ steps.daily-ai-credits-workflow-guardrail.outputs.daily_ai_credits_guardrail_error || '' }} + daily_ai_credits_guardrail_status: ${{ steps.daily-ai-credits-workflow-guardrail.outputs.daily_ai_credits_guardrail_status || '' }} + daily_ai_credits_threshold: ${{ steps.daily-ai-credits-workflow-guardrail.outputs.daily_ai_credits_threshold || '' }} + daily_ai_credits_total: ${{ steps.daily-ai-credits-workflow-guardrail.outputs.daily_ai_credits_total || '' }} + 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 }} + oauth_token_check_failed: ${{ steps.check-oauth-tokens.outputs.oauth_token_check_failed == 'true' }} + setup-parent-span-id: ${{ steps.setup.outputs.parent-span-id || steps.setup.outputs.span-id }} + setup-span-id: ${{ steps.setup.outputs.span-id }} + setup-trace-id: ${{ steps.setup.outputs.trace-id }} + stale_lock_file_failed: ${{ steps.check-lock-file.outputs.stale_lock_file_failed == 'true' }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@221ba4f4319de6b8e809d1a15528b3ae6a818aa5 # v1.0.1 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.pre_activation.outputs.setup-trace-id }} + parent-span-id: ${{ needs.pre_activation.outputs.setup-parent-span-id || needs.pre_activation.outputs.setup-span-id }} + safe-output-artifact-client: ${{ env.GH_AW_MAX_DAILY_AI_CREDITS != '' }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "Update CI Dependencies" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/update-ci-dependencies.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.103" + GH_AW_INFO_AWF_VERSION: "v0.29.0" + GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_SETUP_AW_CONTEXT: ${{ inputs.aw_context }} + - name: Mask OTLP telemetry headers + run: bash "${RUNNER_TEMP}/gh-aw/actions/mask_otlp_headers.sh" + - 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 || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'auto' }} + GH_AW_INFO_VERSION: "1.0.103" + GH_AW_INFO_AGENT_VERSION: "1.0.103" + GH_AW_INFO_CLI_VERSION: "v1.0.1" + GH_AW_INFO_WORKFLOW_NAME: "Update CI Dependencies" + GH_AW_INFO_WORKFLOW_ID: ${{ job.workflow_ref }} + GH_AW_INFO_EXPERIMENTAL: "false" + GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" + GH_AW_INFO_STAGED: "false" + GH_AW_INFO_ALLOWED_DOMAINS: '["defaults","github","learn.microsoft.com"]' + GH_AW_INFO_FIREWALL_ENABLED: "true" + GH_AW_INFO_AWF_VERSION: "v0.29.0" + GH_AW_INFO_AWMG_VERSION: "" + GH_AW_INFO_FIREWALL_TYPE: "squid" + GH_AW_INFO_AGENT_RUNTIME: "" + GH_AW_INFO_ENGINE_HARNESS: "copilot-cli" + GH_AW_INFO_MODEL_CONFIG: '{"routing":{"enabled":false},"models":{"allowed":[],"blocked":[]},"max_ai_credits_source":"default"}' + GH_AW_INFO_MAX_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }} + GH_AW_COMPILED_STRICT: "true" + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'generate_aw_info.cjs')); + await main(core, context); + - name: Restore daily AIC scan observations + id: restore-daily-aic-cache-fallback + if: ${{ env.GH_AW_ADMISSION_RESULT != 'admitted' && env.GH_AW_MAX_DAILY_AI_CREDITS != '' }} + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_HAS_SLASH_COMMAND: "false" + GH_AW_HAS_LABEL_COMMAND: "false" + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'restore_aic_scan_cache.cjs')); + await main(); + - name: Check daily workflow token guardrail + id: daily-ai-credits-workflow-guardrail + if: ${{ env.GH_AW_ADMISSION_RESULT != 'admitted' && env.GH_AW_MAX_DAILY_AI_CREDITS != '' }} + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_WORKFLOW_NAME: "Update CI Dependencies" + GH_AW_WORKFLOW_ID: "update-ci-dependencies" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_WORKFLOW_DISPATCH_AW_CONTEXT: ${{ github.event.inputs.aw_context || '' }} + GH_AW_HAS_SLASH_COMMAND: "false" + GH_AW_HAS_LABEL_COMMAND: "false" + GH_AW_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_AW_MAX_DAILY_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_DAILY_AI_CREDITS || '5000' }} + GH_AW_MAX_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'check_daily_aic_workflow_guardrail.cjs')); + await main(); + - name: Publish daily AIC scan observations + if: always() && env.GH_AW_ADMISSION_RESULT != 'admitted' && env.GH_AW_MAX_DAILY_AI_CREDITS != '' + continue-on-error: true + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + with: + name: aic-usage-scan-v2 + path: /tmp/gh-aw/agentic-workflow-usage-scan-v2.jsonl + overwrite: true + if-no-files-found: ignore + retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '3' }} + - name: Check for OAuth tokens + id: check-oauth-tokens + run: bash "${RUNNER_TEMP}/gh-aw/actions/check_oauth_tokens.sh" + env: + GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + - name: Checkout .github and .agents folders + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + sparse-checkout: | + .github + .agents + .claude + .codex + .gemini + .pi + sparse-checkout-cone-mode: true + fetch-depth: 1 + - name: Save agent config folders for base branch restoration + env: + GH_AW_AGENT_FOLDERS: ".agents .github" + GH_AW_AGENT_FILES: "AGENTS.md" + 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.0.0 + env: + GH_AW_WORKFLOW_FILE: "update-ci-dependencies.lock.yml" + GH_AW_CONTEXT_WORKFLOW_REF: "${{ github.workflow_ref }}" + with: + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'check_workflow_timestamp_api.cjs')); + await main(); + - name: Check compile-agentic version + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_COMPILED_VERSION: "v1.0.1" + GH_AW_HAS_SAFE_OUTPUTS: "true" + GH_AW_BLOCKED_VERSION_REPORT_AS_ISSUE: "true" + GH_AW_WORKFLOW_NAME: "Update CI Dependencies" + with: + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'check_version_updates.cjs')); + await main(); + - name: Log runtime features + if: ${{ contains(toJSON(vars), '"GH_AW_RUNTIME_FEATURES":') }} + run: bash "${RUNNER_TEMP}/gh-aw/actions/log_runtime_features_summary.sh" + - name: Create prompt with built-in context + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_ACTIONS_DIR: ${{ runner.temp }}/gh-aw/actions + GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ runner.temp }}/gh-aw/safeoutputs/outputs.jsonl + GH_AW_PROMPT_CONFIG: "{\"items\":[{\"content_env\":\"GH_AW_PROMPT_CONTENT_0000\"},{\"file\":\"xpia.md\"},{\"file\":\"temp_folder_prompt.md\"},{\"file\":\"markdown.md\"},{\"file\":\"safe_outputs_mcp_transport_prompt.md\"},{\"file\":\"safe_outputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0001\"},{\"file\":\"safe_outputs_push_to_pr_branch.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0002\"},{\"file\":\"mcp_cli_tools_with_safeoutputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0003\"},{\"file\":\"github_mcp_tools_with_safeoutputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0004\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0005\"}],\"system_item_count\":13}" + GH_AW_EXPR_76DF9333: ${{ github.event.pull_request.number || (fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_type == 'pull_request' && fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_number) }} + GH_AW_EXPR_77C1A4D2: ${{ github.event.comment.id || fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').comment_id }} + GH_AW_EXPR_7C248226: ${{ github.event.issue.number || (fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_type == 'issue' && fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_number) }} + GH_AW_EXPR_C19C384F: ${{ github.event.discussion.number || (fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_type == 'discussion' && fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_number) }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + GH_AW_PROMPT_CONTENT_0000: "\n" + GH_AW_PROMPT_CONTENT_0001: "\nTools: push_to_pull_request_branch, report_missing_tool, report_missing_data, noop(max:2)\n" + GH_AW_PROMPT_CONTENT_0002: "\n" + GH_AW_PROMPT_CONTENT_0003: "\nThe following GitHub context information is available for this workflow:\n{{#if github.actor}}\n- **actor**: __GH_AW_GITHUB_ACTOR__\n{{/if}}\n{{#if github.repository}}\n- **repository**: __GH_AW_GITHUB_REPOSITORY__\n{{/if}}\n{{#if github.workspace}}\n- **workspace**: __GH_AW_GITHUB_WORKSPACE__\n{{/if}}\n{{#if github.event.issue.number || (github.aw.context.item_type == 'issue' && github.aw.context.item_number)}}\n- **issue-number**: #__GH_AW_EXPR_7C248226__\n{{/if}}\n{{#if github.event.discussion.number || (github.aw.context.item_type == 'discussion' && github.aw.context.item_number)}}\n- **discussion-number**: #__GH_AW_EXPR_C19C384F__\n{{/if}}\n{{#if github.event.pull_request.number || (github.aw.context.item_type == 'pull_request' && github.aw.context.item_number)}}\n- **pull-request-number**: #__GH_AW_EXPR_76DF9333__\n{{/if}}\n{{#if github.event.comment.id || github.aw.context.comment_id}}\n- **comment-id**: __GH_AW_EXPR_77C1A4D2__\n{{/if}}\n{{#if github.run_id}}\n- **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__\n{{/if}}\n- **checkouts**: The following repositories have been checked out and are available in the workspace:\n - repo `__GH_AW_GITHUB_REPOSITORY__` → `__GH_AW_GITHUB_WORKSPACE__` (cwd) [full history, all branches available as remote-tracking refs] [additional refs fetched: *]\n - **Note**: The workspace path reported above may contain a separate shallow, credential-free checkout of the host repository. Use the exact checkout path shown for the repository you need. Before concluding that a branch is unavailable, confirm your working directory matches that path and inspect refs there. If the branch is not present in that checkout and is not listed as an additional fetched ref, it has NOT been checked out. For private repositories you cannot fetch it. If the branch is required and not available, exit with an error and ask the user to add it to the `fetch:` option of the `checkout:` configuration (e.g., `fetch: [\"refs/pulls/open/*\"]` for all open PR refs, or `fetch: [\"main\", \"feature/my-branch\"]` for specific branches).\n - **Warning: No git credentials are available to the agent.** Credentials are\n intentionally removed after the checkout step for security. This means any git\n operation that needs to authenticate to the remote will fail. In private repositories, that includes:\n - `git fetch`, `git pull`, `git clone`, and `git push` (direct push, not via safe-output tools)\n - Checking out or switching to a remote branch that is not already fetched\n - Deepening a shallow clone (`git fetch --unshallow`)\n - On-demand blob fetches in partial/blobless clones (operations on files not in the initial checkout)\n Do NOT attempt to configure credentials, run `git credential fill`, or modify `.gitconfig` —\n authentication will not succeed. If you encounter credential prompts or authentication errors,\n stop immediately and report the limitation rather than spending turns trying to work around it.\n\n\n" + GH_AW_PROMPT_CONTENT_0004: "\n" + GH_AW_PROMPT_CONTENT_0005: "{{#runtime-import .github/workflows/update-ci-dependencies.md}}\n" + with: + script: | + const { setupGlobals } = require(process.env.GH_AW_ACTIONS_DIR + '/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(process.env.GH_AW_ACTIONS_DIR + '/create_prompt.cjs'); + await main(core); + - name: Interpolate variables and render templates + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt + GH_AW_ENGINE_ID: "copilot" + GH_AW_SUB_AGENT_DIR: ".github/agents" + GH_AW_SUB_AGENT_EXT: ".agent.md" + GH_AW_SKILL_DIR: ".github/skills" + GH_AW_SKILL_EXT: "/SKILL.md" + with: + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'interpolate_prompt.cjs')); + await main(); + - name: Substitute placeholders + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt + GH_AW_EXPR_76DF9333: ${{ github.event.pull_request.number || (fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_type == 'pull_request' && fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_number) }} + GH_AW_EXPR_77C1A4D2: ${{ github.event.comment.id || fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').comment_id }} + GH_AW_EXPR_7C248226: ${{ github.event.issue.number || (fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_type == 'issue' && fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_number) }} + GH_AW_EXPR_C19C384F: ${{ github.event.discussion.number || (fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_type == 'discussion' && fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_number) }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + 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: "- `github` — run `github --help` to see available tools\n- `safeoutputs` — run `safeoutputs --help` to see available tools" + GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: ${{ needs.pre_activation.outputs.activated }} + with: + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + + const substitutePlaceholders = require(path.join(actionsDir, 'substitute_placeholders.cjs')); + + // Call the substitution function + return await substitutePlaceholders({ + file: process.env.GH_AW_PROMPT, + substitutions: { + GH_AW_EXPR_76DF9333: process.env.GH_AW_EXPR_76DF9333, + GH_AW_EXPR_77C1A4D2: process.env.GH_AW_EXPR_77C1A4D2, + GH_AW_EXPR_7C248226: process.env.GH_AW_EXPR_7C248226, + GH_AW_EXPR_C19C384F: process.env.GH_AW_EXPR_C19C384F, + GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, + 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 + } + }); + - name: Validate prompt placeholders + env: + GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt + run: | + bash "${RUNNER_TEMP}/gh-aw/actions/validate_prompt_placeholders.sh" + - name: Print prompt + env: + GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt + run: | + bash "${RUNNER_TEMP}/gh-aw/actions/print_prompt_summary.sh" + - name: Inventory installed skills + if: success() || failure() + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_SKILL_DIR: ".github/skills" + with: + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'skill_inventory.cjs')); + await main(); + - name: Upload info artifact + if: success() || failure() + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + with: + name: info + path: /tmp/gh-aw/aw_info.json + if-no-files-found: ignore + retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }} + - name: Stage prompt files for artifact upload + run: | + mkdir -p /tmp/gh-aw/aw-prompts + cp -a "${RUNNER_TEMP}/gh-aw/aw-prompts/." /tmp/gh-aw/aw-prompts/ + - name: Upload activation artifact + if: success() || failure() + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + with: + name: activation + include-hidden-files: true + path: | + /tmp/gh-aw/aw_info.json + /tmp/gh-aw/models.json + /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/aw-prompts/system.txt + /tmp/gh-aw/aw-prompts/user.txt + /tmp/gh-aw/aw-prompts/prompt-template.txt + /tmp/gh-aw/aw-prompts/prompt-import-tree.json + /tmp/gh-aw/github_rate_limits.jsonl + /tmp/gh-aw/base + /tmp/gh-aw/.github/agents + /tmp/gh-aw/.github/skills + /tmp/gh-aw/skill_inventory.json + if-no-files-found: ignore + retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '1' }} + + agent: + name: agent + needs: activation + if: needs.activation.outputs.daily_ai_credits_exceeded != 'true' + runs-on: ubuntu-latest + # Permissions for the agent job (workflow permissions default to none). + permissions: + actions: read + contents: read + copilot-requests: write + pull-requests: read + concurrency: + group: "gh-aw-copilot-${{ github.workflow }}" + queue: max + timeout-minutes: 60 + env: + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + GH_AW_ASSETS_ALLOWED_EXTS: "" + GH_AW_ASSETS_BRANCH: "" + GH_AW_ASSETS_MAX_SIZE_KB: 0 + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + GH_AW_PR_HEAD_BASE_BRANCH: "" + GH_AW_PR_HEAD_BASE_PR_NUMBER: "" + GH_AW_PR_HEAD_BASE_REF: "" + GH_AW_PR_HEAD_BASE_REPO: "" + GH_AW_PR_HEAD_BASE_SHA: "" + GH_AW_PR_HEAD_REPO: "" + GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }} + GH_AW_TARGET_REPO_SLUG: "" + GH_AW_WORKFLOW_ID_SANITIZED: updatecidependencies + outputs: + agentic_engine_timeout: ${{ steps.detect-agent-errors.outputs.agentic_engine_timeout || 'false' }} + ai_credits_rate_limit_error: ${{ steps.parse-mcp-gateway.outputs.ai_credits_rate_limit_error || 'false' }} + aic: ${{ steps.parse-token-usage.outputs.aic }} + ambient_context: ${{ steps.parse-token-usage.outputs.ambient_context }} + checkout_pr_invalidated: ${{ steps.checkout-pr.outputs.checkout_pr_invalidated || 'false' }} + checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} + has_patch: ${{ steps.collect_output.outputs.has_patch }} + http_400_response_error: ${{ steps.detect-agent-errors.outputs.http_400_response_error || 'false' }} + inference_access_error: ${{ steps.detect-agent-errors.outputs.inference_access_error || 'false' }} + invocation_cap_exceeded: ${{ steps.detect-agent-errors.outputs.invocation_cap_exceeded || 'false' }} + max_cache_misses_exceeded: ${{ steps.detect-agent-errors.outputs.max_cache_misses_exceeded || 'false' }} + mcp_policy_error: ${{ steps.detect-agent-errors.outputs.mcp_policy_error || 'false' }} + missing_model_pricing_error: ${{ steps.detect-agent-errors.outputs.missing_model_pricing_error || 'false' }} + missing_model_pricing_model_name: ${{ steps.detect-agent-errors.outputs.missing_model_pricing_model_name || '' }} + model: ${{ needs.activation.outputs.model }} + model_endpoint_mismatch_error: ${{ steps.detect-agent-errors.outputs.model_endpoint_mismatch_error || 'false' }} + model_not_supported_error: ${{ steps.detect-agent-errors.outputs.model_not_supported_error || 'false' }} + output: ${{ steps.collect_output.outputs.output }} + output_types: ${{ steps.collect_output.outputs.output_types }} + setup-parent-span-id: ${{ steps.setup.outputs.parent-span-id || steps.setup.outputs.span-id }} + setup-span-id: ${{ steps.setup.outputs.span-id }} + setup-trace-id: ${{ steps.setup.outputs.trace-id }} + shell_expansion_guard_rejected: ${{ steps.detect-agent-errors.outputs.shell_expansion_guard_rejected || 'false' }} + unknown_model_ai_credits: ${{ steps.parse-mcp-gateway.outputs.unknown_model_ai_credits || 'false' }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@221ba4f4319de6b8e809d1a15528b3ae6a818aa5 # v1.0.1 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "Update CI Dependencies" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/update-ci-dependencies.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.103" + GH_AW_INFO_AWF_VERSION: "v0.29.0" + GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_SETUP_AW_CONTEXT: ${{ inputs.aw_context }} + - name: Set runtime paths + id: set-runtime-paths + env: + GH_AW_RUNNER_TOOL_CACHE: ${{ runner.tool_cache }} + run: | # zizmor: ignore[github-env] - runner.tool_cache is set by GitHub Actions, not user input. + if [ -z "${RUNNER_TOOL_CACHE:-}" ]; then + echo "RUNNER_TOOL_CACHE=${GH_AW_RUNNER_TOOL_CACHE}" >> "$GITHUB_ENV" + fi + { + echo "GH_AW_SAFE_OUTPUTS=${RUNNER_TEMP}/gh-aw/safeoutputs/outputs.jsonl" + echo "GH_AW_SAFE_OUTPUTS_CONFIG_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" + echo "GH_AW_SAFE_OUTPUTS_TOOLS_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/tools.json" + } >> "$GITHUB_OUTPUT" + - name: Mask OTLP telemetry headers + run: bash "${RUNNER_TEMP}/gh-aw/actions/mask_otlp_headers.sh" + - name: Check OTLP telemetry configuration + run: bash "${RUNNER_TEMP}/gh-aw/actions/check_otlp_default_credentials.sh" + - env: + GH_TOKEN: ${{ github.token }} + id: repository-token + name: Configure Read-Only Repository Token + run: "printf 'token=%s\\n' \"$GH_TOKEN\" >> \"$GITHUB_OUTPUT\"" + + - name: Checkout repository (gh-aw default) + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + token: ${{ github.token }} + fetch-depth: 0 + - name: Fetch additional refs + env: + GH_AW_FETCH_TOKEN: ${{ github.token }} + run: | + set -o pipefail + header=$(printf "x-access-token:%s" "${GH_AW_FETCH_TOKEN}" | base64 -w 0) + refspecs=('+refs/heads/*:refs/remotes/origin/*') + for refspec in "${refspecs[@]}"; do + source_ref=${refspec%%:*} + source_ref=${source_ref#+} + if matched=$(git -c "http.extraheader=Authorization: Basic ${header}" ls-remote --exit-code origin "$source_ref" | { + found=0 + while read -r _ remote_ref; do + # Match the configured ref glob, not a literal string. + # shellcheck disable=SC2254 + case "$remote_ref" in ($source_ref) found=1 ;; esac + done + printf '%s' "$found" + }); then + if [ "$matched" -eq 0 ]; then continue; fi + git -c "http.extraheader=Authorization: Basic ${header}" fetch origin "$refspec" + else + status=$? + if [ "$status" -ne 2 ]; then exit "$status"; fi + fi + done + - name: Initialize agent execution evidence + run: | + mkdir -p "/tmp/gh-aw" + evidence_tmp="/tmp/gh-aw/agent_execution.json.tmp" + printf '{"version":1,"component":"agent","run_id":%s,"run_attempt":%s,"state":"not_started"}\n' "$GITHUB_RUN_ID" "$GITHUB_RUN_ATTEMPT" > "$evidence_tmp" + mv "$evidence_tmp" "/tmp/gh-aw/agent_execution.json" + - name: Create gh-aw temp directory + run: bash "${RUNNER_TEMP}/gh-aw/actions/create_gh_aw_tmp_dir.sh" + - name: Configure gh CLI for GitHub Enterprise + run: bash "${RUNNER_TEMP}/gh-aw/actions/configure_gh_for_ghe.sh" + env: + GH_TOKEN: ${{ github.token }} + - name: Download activation artifact + uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 + with: + name: activation + path: /tmp/gh-aw + - env: + GH_TOKEN: ${{ github.token }} + name: Install Workflow Lockfile Tool + run: gh extension install github/gh-actions-lock --pin v0.4.0 + + - name: Configure Git credentials + env: + GITHUB_REPOSITORY: ${{ github.repository }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_TOKEN: ${{ github.token }} + run: bash "${RUNNER_TEMP}/gh-aw/actions/configure_git_credentials.sh" + - name: Checkout PR branch + id: checkout-pr + if: | + github.event.pull_request || github.event.issue.pull_request || github.event_name == 'workflow_dispatch' + 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: + github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'checkout_pr_branch.cjs')); + await main(); + - name: Install GitHub Copilot CLI + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.103 --checksums-sha256 26cd3e4b32cde498e4961fb4d48e7b85d7859fc69af1a645a19201fdd577bdb2 --prefer-toolcache + env: + GH_HOST: github.com + GH_AW_COPILOT_MIN_VERSION: 1.0.35 + - name: Install AWF binary + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.29.0 --rootless + - name: Determine automatic lockdown mode for GitHub MCP Server + id: determine-automatic-lockdown + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + with: + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const determineAutomaticLockdown = require(path.join(actionsDir, 'determine_automatic_lockdown.cjs')); + await determineAutomaticLockdown(github, context, core); + - name: Restore agent config folders from base branch + if: steps.checkout-pr.outcome == 'success' + env: + GH_AW_AGENT_FOLDERS: ".agents .github" + GH_AW_AGENT_FILES: "AGENTS.md" + run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_base_github_folders.sh" + - name: Restore inline sub-agents from activation artifact + env: + GH_AW_SUB_AGENT_DIR: ".github/agents" + GH_AW_SUB_AGENT_EXT: ".agent.md" + run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_sub_agents.sh" + - name: Restore inline skills from activation artifact + env: + GH_AW_SKILL_DIR: ".github/skills" + run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_skills.sh" + - name: Download container images + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.29.0@sha256:b14bd399376180b5649a9324be3b50fbfc82bfe8f0c80045840416b5a4e65b96 ghcr.io/github/gh-aw-firewall/api-proxy:0.29.0@sha256:baff00b856a4bdc93bce134928c70af3d3492f2e518757115042040674d56b0b ghcr.io/github/gh-aw-firewall/squid:0.29.0@sha256:6e0cbf7f980beb78b5461563a8164f6439ca959bc93733d5a6b52972e523ed50 ghcr.io/github/gh-aw-mcpg:v0.5.0@sha256:d3544a4222e7efeeeb38669d8a1af0c72691c55b8f6506b15aa5920f7f31b7bc ghcr.io/github/gh-aw-node@sha256:2c2ea524e648b91c8333ce246e3838fcf5b19ac70e45baac1a51b9207299749f ghcr.io/github/github-mcp-server:v2.0.3@sha256:250bc6ce70788207608ef74cef4397230ff2e8481218da74d6093e4bd9101132 + - name: Prepare Safe Outputs Directories + run: | + mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" + mkdir -p /tmp/gh-aw/safeoutputs + mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs + - name: Generate Safe Outputs Config + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_FILE_ROOT: "${{ runner.temp }}/gh-aw" + GH_AW_FILE_CONFIG: "{\"files\":[{\"path\":\"safeoutputs/config.json\",\"content_env\":\"GH_AW_SAFE_OUTPUTS_CONFIG\"}]}" + GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_report_incomplete_issue\":{},\"noop\":{\"max\":2,\"report-as-issue\":\"false\"},\"push_to_pull_request_branch\":{\"allowed_files\":[\".github/workflows/build.yml\",\".github/workflows/pr-automation.yml\",\".github/workflows/release-initiate.yml\",\".github/workflows/release-publish.yml\",\".github/workflows/actions.lock\",\".github/actions/mint-github-app-token/action.yml\",\".azure-devops/*.yml\",\"package.json\",\".nvmrc\"],\"github-token\":\"${{ steps.repository-token.outputs.token }}\",\"if_no_changes\":\"ignore\",\"max\":1,\"max_patch_size\":4096,\"protect_top_level_dot_folders\":true,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"CODEOWNERS\",\"DESIGN.md\",\"README.md\",\"CONTRIBUTING.md\",\"SECURITY.md\",\"CODE_OF_CONDUCT.md\",\"AGENTS.md\"],\"protected_files_policy\":\"allowed\",\"required_labels\":[\"release\"],\"target\":\"*\"},\"report_incomplete\":{},\"report_missing_data\":{},\"report_missing_tool\":{}}" + with: + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'create_files.cjs')); + await main(); + - name: Generate Safe Outputs Tools + env: + GH_AW_TOOLS_META_JSON: | + { + "description_suffixes": { + "push_to_pull_request_branch": " CONSTRAINTS: Maximum 1 push(es) can be made." + }, + "repo_params": {}, + "dynamic_tools": [] + } + GH_AW_VALIDATION_JSON: | + { + "noop": { + "defaultMax": 2, + "fields": { + "message": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + } + } + }, + "push_to_pull_request_branch": { + "defaultMax": 1, + "fields": { + "branch": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "message": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "pull_request_number": { + "issueOrPRNumber": true + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, + "report_incomplete": { + "defaultMax": 5, + "fields": { + "details": { + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "reason": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 1024 + } + } + }, + "report_missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, + "report_missing_tool": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 512 + }, + "reason": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "tool": { + "type": "string", + "sanitize": true, + "maxLength": 128 + } + } + } + } + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'generate_safe_outputs_tools.cjs')); + await main(); + - name: Start MCP Gateway + id: start-mcp-gateway + env: + DEBUG: ${{ env.DEBUG || runner.debug == '1' && '*' || '' }} + GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST: ${{ vars.GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST || 'true' }} + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS_CONFIG_PATH }} + GH_AW_SAFE_OUTPUTS_TOOLS_PATH: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS_TOOLS_PATH }} + GH_AW_SINK_VISIBILITY: ${{ steps.determine-automatic-lockdown.outputs.visibility }} + GITHUB_MCP_GUARD_MIN_INTEGRITY: ${{ steps.determine-automatic-lockdown.outputs.min_integrity }} + GITHUB_MCP_GUARD_REPOS: ${{ steps.determine-automatic-lockdown.outputs.repos }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -eo pipefail + mkdir -p "${RUNNER_TEMP}/gh-aw/mcp-config" + if [ -n "${GITHUB_EVENT_PATH:-}" ] && [ -r "${GITHUB_EVENT_PATH}" ]; then + GH_AW_SAFEOUTPUTS_EVENT_PATH="${RUNNER_TEMP}/gh-aw/safeoutputs/github_event.json" + cp "${GITHUB_EVENT_PATH}" "${GH_AW_SAFEOUTPUTS_EVENT_PATH}" + export GITHUB_EVENT_PATH="${GH_AW_SAFEOUTPUTS_EVENT_PATH}" + fi + + # Export gateway environment variables for MCP config and gateway script + export MCP_GATEWAY_PORT="8080" + export MCP_GATEWAY_DOMAIN="awmg-mcpg" + export MCP_GATEWAY_HOST_DOMAIN="localhost" + MCP_GATEWAY_AGENT_ID=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${MCP_GATEWAY_AGENT_ID}" + export MCP_GATEWAY_AGENT_ID + export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads" + mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}" + export MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD="524288" + export MCP_GATEWAY_ALLOWED_MOUNT_ROOTS="${GITHUB_WORKSPACE}:rw,${RUNNER_TEMP}/gh-aw:ro,${RUNNER_TEMP}/gh-aw/safeoutputs:rw,/opt:ro,/tmp:rw,/usr/bin/gh:ro" + export GH_AW_PR_HEAD_BASE_BRANCH="${GH_AW_PR_HEAD_BASE_BRANCH:-}" + export GH_AW_PR_HEAD_BASE_SHA="${GH_AW_PR_HEAD_BASE_SHA:-}" + export GH_AW_PR_HEAD_BASE_REPO="${GH_AW_PR_HEAD_BASE_REPO:-}" + export GH_AW_PR_HEAD_BASE_PR_NUMBER="${GH_AW_PR_HEAD_BASE_PR_NUMBER:-}" + export GH_AW_PR_HEAD_BASE_REF="${GH_AW_PR_HEAD_BASE_REF:-}" + export GH_AW_PR_HEAD_REPO="${GH_AW_PR_HEAD_REPO:-}" + export GH_AW_TARGET_REPO_SLUG="${GH_AW_TARGET_REPO_SLUG:-}" + export GH_AW_ENGINE="copilot" + MCP_GATEWAY_UID=$(id -u 2>/dev/null || echo '0') + MCP_GATEWAY_GID=$(id -g 2>/dev/null || echo '0') + source "${RUNNER_TEMP}/gh-aw/actions/resolve_docker_socket_gid.sh" + export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network bridge -p 127.0.0.1:'"${MCP_GATEWAY_PORT}"':'"${MCP_GATEWAY_PORT}"' --name awmg-mcpg --add-host host.docker.internal:host-gateway --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v '"${DOCKER_SOCK_PATH}"':/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_AGENT_ID -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DOCKER_HOST=unix:///var/run/docker.sock -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_TARGET_REPO_SLUG -e GH_AW_PR_HEAD_BASE_BRANCH -e GH_AW_PR_HEAD_BASE_SHA -e GH_AW_PR_HEAD_BASE_REPO -e GH_AW_PR_HEAD_BASE_PR_NUMBER -e GH_AW_PR_HEAD_BASE_REF -e GH_AW_PR_HEAD_REPO -e GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST -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 GH_AW_SINK_VISIBILITY -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 RUNNER_TEMP -e RUNNER_TOOL_CACHE -e MCP_GATEWAY_ALLOWED_MOUNT_ROOTS -e GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -e OTEL_EXPORTER_OTLP_HEADERS -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 -v '"${RUNNER_TEMP}"'/gh-aw/safeoutputs:'"${RUNNER_TEMP}"'/gh-aw/safeoutputs:rw ghcr.io/github/gh-aw-mcpg:v0.5.0@sha256:d3544a4222e7efeeeb38669d8a1af0c72691c55b8f6506b15aa5920f7f31b7bc' + + mkdir -p "$HOME/.copilot" + GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) + cat << GH_AW_MCP_CONFIG_b79eaaa85379052a_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + { + "mcpServers": { + "github": { + "type": "stdio", + "container": "ghcr.io/github/github-mcp-server:v2.0.3", + "env": { + "GITHUB_FEATURES": "fields_param", + "GITHUB_HOST": "${GITHUB_SERVER_URL}", + "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_MCP_SERVER_TOKEN}", + "GITHUB_READ_ONLY": "1", + "GITHUB_TOOLSETS": "context,repos,issues,pull_requests" + }, + "guard-policies": { + "allow-only": { + "min-integrity": "$GITHUB_MCP_GUARD_MIN_INTEGRITY", + "repos": "$GITHUB_MCP_GUARD_REPOS" + } + } + }, + "safeoutputs": { + "type": "stdio", + "container": "ghcr.io/github/gh-aw-node@sha256:2c2ea524e648b91c8333ce246e3838fcf5b19ac70e45baac1a51b9207299749f", + "mounts": ["\${GITHUB_WORKSPACE}:\${GITHUB_WORKSPACE}:rw", "${RUNNER_TEMP}/gh-aw/safeoutputs:${RUNNER_TEMP}/gh-aw/safeoutputs:rw", "/tmp/gh-aw:/tmp/gh-aw:rw"], + "args": ["-w", "\${GITHUB_WORKSPACE}"], + "entrypoint": "sh", + "entrypointArgs": ["-c", "sh ${RUNNER_TEMP}/gh-aw/safeoutputs/start_safe_outputs_mcp.sh"], + "env": { + "DEBUG": "\${DEBUG}", + "DEFAULT_BRANCH": "\${DEFAULT_BRANCH}", + "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}", + "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}", + "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}", + "GH_AW_MCP_LOG_DIR": "\${GH_AW_MCP_LOG_DIR}", + "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", + "GH_AW_SAFE_OUTPUTS_CONFIG_PATH": "\${GH_AW_SAFE_OUTPUTS_CONFIG_PATH}", + "GH_AW_SAFE_OUTPUTS_TOOLS_PATH": "\${GH_AW_SAFE_OUTPUTS_TOOLS_PATH}", + "GH_AW_TARGET_REPO_SLUG": "\${GH_AW_TARGET_REPO_SLUG}", + "GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST": "\${GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST}", + "GH_AW_PR_HEAD_BASE_BRANCH": "\${GH_AW_PR_HEAD_BASE_BRANCH}", + "GH_AW_PR_HEAD_BASE_SHA": "\${GH_AW_PR_HEAD_BASE_SHA}", + "GH_AW_PR_HEAD_BASE_REPO": "\${GH_AW_PR_HEAD_BASE_REPO}", + "GH_AW_PR_HEAD_BASE_PR_NUMBER": "\${GH_AW_PR_HEAD_BASE_PR_NUMBER}", + "GH_AW_PR_HEAD_BASE_REF": "\${GH_AW_PR_HEAD_BASE_REF}", + "GH_AW_PR_HEAD_REPO": "\${GH_AW_PR_HEAD_REPO}", + "GITHUB_EVENT_NAME": "\${GITHUB_EVENT_NAME}", + "GITHUB_EVENT_PATH": "\${GITHUB_EVENT_PATH}", + "GITHUB_REPOSITORY": "\${GITHUB_REPOSITORY}", + "GITHUB_SHA": "\${GITHUB_SHA}", + "GITHUB_TOKEN": "\${GITHUB_TOKEN}", + "GITHUB_WORKSPACE": "\${GITHUB_WORKSPACE}", + "RUNNER_TEMP": "\${RUNNER_TEMP}" + }, + "guard-policies": { + "write-sink": { + "accept": [ + "*" + ], + "sink-visibility": "${GH_AW_SINK_VISIBILITY}" + } + } + } + }, + "gateway": { + "port": $MCP_GATEWAY_PORT, + "domain": "${MCP_GATEWAY_DOMAIN}", + "agentId": "${MCP_GATEWAY_AGENT_ID}", + "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}", + "startupTimeout": 120, + "opentelemetry": { + "endpoint": "${OTEL_EXPORTER_OTLP_ENDPOINT}", + "traceId": "${GITHUB_AW_OTEL_TRACE_ID}", + "spanId": "${GITHUB_AW_OTEL_PARENT_SPAN_ID}" + } + } + } + GH_AW_MCP_CONFIG_b79eaaa85379052a_EOF + - name: Mount MCP servers as CLIs + id: mount-mcp-clis + continue-on-error: true + env: + MCP_GATEWAY_AGENT_ID: ${{ steps.start-mcp-gateway.outputs.gateway-agent-id }} + 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: + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io); + const { main } = require(path.join(actionsDir, 'mount_mcp_as_cli.cjs')); + await main(); + - name: Clean credentials + run: | + bash "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh" + bash "${RUNNER_TEMP}/gh-aw/actions/verify_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: Log GitHub rate limits at agent start + continue-on-error: true + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { fetchAndLogRateLimit } = require(path.join(actionsDir, 'github_rate_limit_logger.cjs')); + await fetchAndLogRateLimit(github, 'agent_start', true); + - name: Execute GitHub Copilot CLI + id: agentic_execution + # Copilot CLI tool arguments (sorted): + # --allow-tool github + # --allow-tool safeoutputs + # --allow-tool shell(cat) + # --allow-tool shell(curl:*) + # --allow-tool shell(date) + # --allow-tool shell(echo) + # --allow-tool shell(gh actions-lock) + # --allow-tool shell(gh api) + # --allow-tool shell(gh pr list) + # --allow-tool shell(gh pr view) + # --allow-tool shell(git add:*) + # --allow-tool shell(git branch:*) + # --allow-tool shell(git checkout:*) + # --allow-tool shell(git commit:*) + # --allow-tool shell(git merge:*) + # --allow-tool shell(git rm:*) + # --allow-tool shell(git status) + # --allow-tool shell(git switch:*) + # --allow-tool shell(git:*) + # --allow-tool shell(github:*) + # --allow-tool shell(grep) + # --allow-tool shell(head) + # --allow-tool shell(jq) + # --allow-tool shell(ls) + # --allow-tool shell(printf) + # --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 write + timeout-minutes: ${{ fromJSON(vars.GH_AW_DEFAULT_TIMEOUT_MINUTES || '20') }} + run: | + set -o pipefail + printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt + gh_aw_exit_code=0 + trap 'gh_aw_exit_code=$?; mkdir -p /tmp/gh-aw >/dev/null 2>&1 || true; printf "%s" "$gh_aw_exit_code" > /tmp/gh-aw/agent_execution_exit_code.txt || true; rm -f "$HOME/.copilot/settings.json"; if [ "$gh_aw_exit_code" -ne 0 ]; then echo "::error::Agent execution exited with code $gh_aw_exit_code"; fi' EXIT + mkdir -p "$HOME/.copilot" + printf '%s' '{"builtInAgents":{"rubberDuck":false},"enabledFeatureFlags":{"EXTENSIONS":false}}' > "$HOME/.copilot/settings.json" + export XDG_CONFIG_HOME="$HOME" + export GH_AW_MCP_CONFIG="$HOME/.copilot/mcp-config.json" + GH_AW_COPILOT_SRC="$(command -v copilot 2>/dev/null || true)" + if [ -z "$GH_AW_COPILOT_SRC" ] || [ ! -x "$GH_AW_COPILOT_SRC" ]; then + echo "GitHub Copilot CLI executable not found on PATH after installation" >&2 + exit 127 + fi + GH_AW_COPILOT_BIN="${RUNNER_TEMP}/gh-aw/bin/copilot" + mkdir -p "${RUNNER_TEMP}/gh-aw/bin" + if [ "$GH_AW_COPILOT_SRC" != "$GH_AW_COPILOT_BIN" ]; then + cp "$GH_AW_COPILOT_SRC" "$GH_AW_COPILOT_BIN" + fi + chmod 755 "$GH_AW_COPILOT_BIN" + + touch /tmp/gh-aw/agent-step-summary.md + GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true) + export GH_AW_NODE_BIN + export COPILOT_API_KEY="$COPILOT_DUMMY_BYOK" + (umask 177 && touch /tmp/gh-aw/agent-stdio.log) + GH_AW_MAX_AI_CREDITS="${GH_AW_MAX_AI_CREDITS:-1000}" + if [[ ! "$GH_AW_MAX_AI_CREDITS" =~ ^[0-9]+$ ]]; then + GH_AW_MAX_AI_CREDITS="1000" + fi + if [[ "${GH_AW_ADMISSION_RESULT:-}" == "admitted" && -z "${GH_AW_ADMISSION_MAX_AI_CREDITS:-}" ]]; then + echo "ERR_ADMISSION: Missing required runtime admission allowance." >&2 + exit 1 + fi + + if [[ "${GH_AW_ADMISSION_RESULT:-}" == "admitted" && -n "${GH_AW_ADMISSION_MAX_AI_CREDITS:-}" ]]; then + if [[ ! "$GH_AW_ADMISSION_MAX_AI_CREDITS" =~ ^[1-9][0-9]{0,9}$ ]] || (( GH_AW_ADMISSION_MAX_AI_CREDITS > 2147483647 )); then + echo "ERR_ADMISSION: Invalid runtime admission allowance." >&2 + exit 1 + fi + GH_AW_MAX_AI_CREDITS="$GH_AW_ADMISSION_MAX_AI_CREDITS" + echo "Admission allowance applied (value withheld)." + else + echo "No component admission allowance; retaining existing budget policy (value withheld)." + fi + unset GH_AW_ADMISSION_RESULT GH_AW_ADMISSION_MAX_AI_CREDITS + printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.29.0/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"*.githubusercontent.com\",\"api.snapcraft.io\",\"archive.ubuntu.com\",\"azure.archive.ubuntu.com\",\"codeload.github.com\",\"crl.geotrust.com\",\"crl.globalsign.com\",\"crl.identrust.com\",\"crl.sectigo.com\",\"crl.thawte.com\",\"crl.usertrust.com\",\"crl.verisign.com\",\"crl3.digicert.com\",\"crl4.digicert.com\",\"crls.ssl.com\",\"docs.github.com\",\"github-cloud.githubusercontent.com\",\"github-cloud.s3.amazonaws.com\",\"github.blog\",\"github.com\",\"github.githubassets.com\",\"json-schema.org\",\"json.schemastore.org\",\"keyserver.ubuntu.com\",\"learn.microsoft.com\",\"lfs.github.com\",\"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\",\"patch-diff.githubusercontent.com\",\"patchdiff.githubusercontent.com\",\"ppa.launchpad.net\",\"raw.githubusercontent.com\",\"s.symcb.com\",\"s.symcd.com\",\"security.ubuntu.com\",\"ts-crl.ws.symantec.com\",\"ts-ocsp.ws.symantec.com\",\"www.googleapis.com\"],\"isolation\":true,\"topologyAttach\":[\"awmg-mcpg\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"maxCacheMisses\":5,\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-6\",\"gpt-5.4\",\"gpt-5.5\",\"gpt-5.6\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"auto\":[\"copilot/auto\",\"large\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\",\"kimi\"],\"computer-use\":[\"copilot/*computer-use*\",\"google/*computer-use*\",\"gemini/*computer-use*\",\"openai/*computer-use*\"],\"copilot\":[\"agent\"],\"deep-research\":[\"copilot/deep-research*\",\"copilot/o3-deep-research*\",\"copilot/o4-mini-deep-research*\",\"google/deep-research*\",\"gemini/deep-research*\",\"openai/o3-deep-research*\",\"openai/o4-mini-deep-research*\"],\"detection\":[\"small\"],\"evals\":[\"small\"],\"fable\":[\"copilot/*fable*\",\"anthropic/*fable*\"],\"gemini\":[\"agent\"],\"gemini-3-flash\":[\"copilot/gemini-3*flash*\",\"google/gemini-3*flash*\",\"gemini/gemini-3*flash*\"],\"gemini-3-pro\":[\"copilot/gemini-3*pro*\",\"google/gemini-3*pro*\",\"google/nano-banana*\",\"gemini/gemini-3*pro*\"],\"gemini-3.1-flash\":[\"copilot/gemini-3.1*flash*\",\"google/gemini-3.1*flash*\",\"gemini/gemini-3.1*flash*\"],\"gemini-3.1-pro\":[\"copilot/gemini-3.1*pro*\",\"google/gemini-3.1*pro*\",\"gemini/gemini-3.1*pro*\"],\"gemini-3.5-flash\":[\"copilot/gemini-3.5*flash*\",\"google/gemini-3.5*flash*\",\"gemini/gemini-3.5*flash*\"],\"gemini-3.6-flash\":[\"copilot/gemini-3.6*flash*\",\"google/gemini-3.6*flash*\",\"gemini/gemini-3.6*flash*\"],\"gemini-3.7-flash\":[\"copilot/gemini-3.7*flash*\",\"google/gemini-3.7*flash*\",\"gemini/gemini-3.7*flash*\"],\"gemini-3.8-flash\":[\"copilot/gemini-3.8*flash*\",\"google/gemini-3.8*flash*\",\"gemini/gemini-3.8*flash*\"],\"gemini-flash\":[\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"],\"gemini-flash-lite\":[\"copilot/gemini-*flash*lite*\",\"google/gemini-*flash*lite*\",\"gemini/gemini-*flash*lite*\"],\"gemini-omni\":[\"copilot/gemini-omni*\",\"google/gemini-omni*\",\"gemini/gemini-omni*\"],\"gemini-pro\":[\"copilot/gemini-*pro*\",\"google/gemini-*pro*\",\"gemini/gemini-*pro*\"],\"gemma\":[\"copilot/gemma*\",\"google/gemma*\",\"gemini/gemma*\"],\"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*\"],\"gpt-5.1\":[\"copilot/gpt-5.1*\",\"openai/gpt-5.1*\"],\"gpt-5.2\":[\"copilot/gpt-5.2*\",\"openai/gpt-5.2*\"],\"gpt-5.3\":[\"copilot/gpt-5.3*\",\"openai/gpt-5.3*\"],\"gpt-5.4\":[\"copilot/gpt-5.4*\",\"openai/gpt-5.4*\"],\"gpt-5.5\":[\"copilot/gpt-5.5*\",\"openai/gpt-5.5*\"],\"gpt-5.6\":[\"copilot/gpt-5.6*\",\"openai/gpt-5.6*\"],\"gpt-6\":[\"copilot/gpt-6*\",\"openai/gpt-6*\"],\"grok\":[\"copilot/*grok*\",\"openai/*grok*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"image-generation\":[\"copilot/gpt-image*\",\"openai/gpt-image*\",\"openai/chatgpt-image*\",\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"google/imagen*\"],\"kimi\":[\"copilot/kimi*\",\"openai/kimi*\"],\"kiwi\":[\"copilot/kiwi*\",\"openai/kiwi*\"],\"large\":[\"sonnet\",\"gpt-6\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"lyria\":[\"google/lyria*\",\"gemini/lyria*\",\"copilot/lyria*\"],\"mai-code\":[\"copilot/MAI-Code*\",\"copilot/mai-code*\",\"openai/MAI-Code*\"],\"mini\":[\"haiku\",\"gpt-5-mini\",\"gpt-5-nano\",\"gemini-flash-lite\"],\"nano-banana\":[\"copilot/nano-banana*\",\"google/nano-banana*\",\"gemini/nano-banana*\"],\"opus\":[\"copilot/*opus*\",\"anthropic/*opus*\"],\"opusplan\":[\"opus?effort=high\"],\"raptor-mini\":[\"copilot/raptor*\",\"openai/raptor*\"],\"reasoning\":[\"copilot/o1*\",\"copilot/o3*\",\"copilot/o4*\",\"openai/o1*\",\"openai/o3*\",\"openai/o4*\"],\"robotics\":[\"copilot/*robotics*\",\"google/*robotics*\",\"gemini/*robotics*\"],\"small\":[\"mini\"],\"small-agent\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash\"],\"sonnet\":[\"copilot/*sonnet*\",\"anthropic/*sonnet*\"],\"sonnet-6x\":[\"copilot/*sonnet-4.5*\",\"copilot/*sonnet-4.6*\",\"copilot/*sonnet-5*\",\"copilot/*sonnet-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\",\"anthropic/*sonnet-5*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"veo\":[\"google/veo*\",\"gemini/veo*\"],\"vision\":[\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.29.0,squid=sha256:6e0cbf7f980beb78b5461563a8164f6439ca959bc93733d5a6b52972e523ed50,agent=sha256:b14bd399376180b5649a9324be3b50fbfc82bfe8f0c80045840416b5a4e65b96,api-proxy=sha256:baff00b856a4bdc93bce134928c70af3d3492f2e518757115042040674d56b0b,cli-proxy=sha256:087a8e4efff8ac62d46e106cd22005c002822b1481fc233097799511be353b5d\"},\"logging\":{\"proxyLogsDir\":\"/tmp/gh-aw/sandbox/firewall/logs\",\"auditDir\":\"/tmp/gh-aw/sandbox/firewall/audit\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json" + cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json + export GH_AW_MODELS_JSON_PATH="/tmp/gh-aw/models.json" + GH_AW_DOCKER_HOST="" + if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then + GH_AW_DOCKER_HOST="${DOCKER_HOST}" + fi + if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then + GH_AW_CHROOT_BINARIES_SOURCE_PATH="${RUNNER_TEMP}/gh-aw" GH_AW_CHROOT_IDENTITY_HOME="${RUNNER_TEMP}/gh-aw/home" node "${RUNNER_TEMP}/gh-aw/actions/patch_awf_chroot_config.cjs" + fi + GH_AW_TOOL_CACHE_MOUNT="" + GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}" + if [ -d "$GH_AW_TOOL_CACHE" ]; then + if [[ "$GH_AW_TOOL_CACHE" != /opt/* ]]; then + GH_AW_TOOL_CACHE_MOUNT="$GH_AW_TOOL_CACHE:$GH_AW_TOOL_CACHE:ro" + fi + fi + # shellcheck disable=SC1003,SC2016,SC2086 + mkdir -p "/tmp/gh-aw" + evidence_tmp="/tmp/gh-aw/agent_execution.json.tmp" + printf '{"version":1,"component":"agent","run_id":%s,"run_attempt":%s,"state":"started"}\n' "$GITHUB_RUN_ID" "$GITHUB_RUN_ATTEMPT" > "$evidence_tmp" + mv "$evidence_tmp" "/tmp/gh-aw/agent_execution.json" + export GH_AW_AWF_EXECUTION_COMPONENT="agent" + export GH_AW_AWF_EXECUTION_EVIDENCE_FILE="/tmp/gh-aw/agent_execution.json" + GH_AW_AWF_ENGINE_NAME=copilot \ + GH_AW_AWF_HARNESS_MARKER='[copilot-harness]' \ + GH_AW_AWF_LOG_FILE=/tmp/gh-aw/agent-stdio.log \ + GH_AW_AWF_ATTEMPT_LOG_NAME=copilot \ + bash "${RUNNER_TEMP}/gh-aw/actions/run_awf_with_startup_retries.sh" -- \ + 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" ${GH_AW_ENGINE_STEP_TIMEOUT_MINUTES:+--agent-timeout "$GH_AW_ENGINE_STEP_TIMEOUT_MINUTES"} ${GH_AW_TOOL_CACHE_MOUNT:+--mount "$GH_AW_TOOL_CACHE_MOUNT"} ${GH_AW_DOCKER_HOST:+--docker-host "$GH_AW_DOCKER_HOST"} --env-all --exclude-env ACTIONS_ID_TOKEN_REQUEST_TOKEN --exclude-env ACTIONS_ID_TOKEN_REQUEST_URL --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GH_AW_OTLP_ALL_HEADERS --exclude-env GH_AW_OTLP_ENDPOINTS --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_AGENT_ID --exclude-env OTEL_EXPORTER_OTLP_ENDPOINT --exclude-env OTEL_EXPORTER_OTLP_HEADERS --mount /tmp/gh-aw:/tmp/gh-aw:rw --log-level info --session-state-dir /tmp/gh-aw/sandbox/agent/session-state --skip-pull \ + -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && : "${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"; GH_AW_TOOL_CACHE="$RUNNER_TOOL_CACHE"; GH_AW_TOOL_BINS="$(find "$GH_AW_TOOL_CACHE" -maxdepth 5 -type d -name bin 2>/dev/null | tr "\n" ":")"; GH_AW_TOOL_BINS="${GH_AW_TOOL_BINS%:}"; export PATH="$PATH${GH_AW_TOOL_BINS:+:}$GH_AW_TOOL_BINS"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true; [ -n "$ERLANG_HOME" ] && export PATH="$ERLANG_HOME/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 || true)"; fi; if [ -z "$GH_AW_NODE_EXEC" ]; then echo "node runtime missing on this runner — check runtimes.node in workflow YAML" >&2; exit 127; fi; GH_AW_NPM_GLOBAL_ROOT="$(npm root -g 2>/dev/null || true)"; if [ -n "$GH_AW_NPM_GLOBAL_ROOT" ]; then export NODE_PATH="${GH_AW_NPM_GLOBAL_ROOT}${NODE_PATH:+:${NODE_PATH}}"; fi; "$GH_AW_NODE_EXEC" "${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs" "${RUNNER_TEMP}/gh-aw/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)'\'' --allow-tool '\''shell(curl:*)'\'' --allow-tool '\''shell(date)'\'' --allow-tool '\''shell(echo)'\'' --allow-tool '\''shell(gh actions-lock)'\'' --allow-tool '\''shell(gh api)'\'' --allow-tool '\''shell(gh pr list)'\'' --allow-tool '\''shell(gh pr view)'\'' --allow-tool '\''shell(git add:*)'\'' --allow-tool '\''shell(git branch:*)'\'' --allow-tool '\''shell(git checkout:*)'\'' --allow-tool '\''shell(git commit:*)'\'' --allow-tool '\''shell(git merge:*)'\'' --allow-tool '\''shell(git rm:*)'\'' --allow-tool '\''shell(git status)'\'' --allow-tool '\''shell(git switch:*)'\'' --allow-tool '\''shell(git:*)'\'' --allow-tool '\''shell(github:*)'\'' --allow-tool '\''shell(grep)'\'' --allow-tool '\''shell(head)'\'' --allow-tool '\''shell(jq)'\'' --allow-tool '\''shell(ls)'\'' --allow-tool '\''shell(printf)'\'' --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 write --deny-tool workflow --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' + env: + AWF_REFLECT_ENABLED: 1 + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_DUMMY_BYOK: dummy-byok-key-for-offline-mode + COPILOT_GITHUB_TOKEN: ${{ github.token }} + COPILOT_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'auto' }} + GH_AW_ENGINE_STEP_TIMEOUT_MINUTES: ${{ fromJSON(vars.GH_AW_DEFAULT_TIMEOUT_MINUTES || '20') }} + GH_AW_LLM_PROVIDER: github + GH_AW_MAX_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }} + GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }} + 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_TIMEOUT_MINUTES: ${{ fromJSON(vars.GH_AW_DEFAULT_TIMEOUT_MINUTES || '20') }} + GH_AW_VERSION: v1.0.1 + GITHUB_API_URL: ${{ github.api_url }} + GITHUB_AW: true + GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows + GITHUB_COPILOT_PROMPT_MODE_EXTENSIONS: false + 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 }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md + GITHUB_WORKSPACE: ${{ github.workspace }} + GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com + GIT_AUTHOR_NAME: github-actions[bot] + GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com + GIT_COMMITTER_NAME: github-actions[bot] + RUNNER_TEMP: ${{ runner.temp }} + S2STOKENS: true + TRACEPARENT: ${{ env.GITHUB_AW_OTEL_TRACE_ID != '' && env.GITHUB_AW_OTEL_PARENT_SPAN_ID != '' && format('00-{0}-{1}-01', env.GITHUB_AW_OTEL_TRACE_ID, env.GITHUB_AW_OTEL_PARENT_SPAN_ID) || '' }} + - name: Log GitHub rate limits at agent end + if: always() + continue-on-error: true + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { fetchAndLogRateLimit } = require(path.join(actionsDir, 'github_rate_limit_logger.cjs')); + await fetchAndLogRateLimit(github, 'agent_end', true); + - name: Detect agent errors + if: always() + id: detect-agent-errors + continue-on-error: true + env: + GH_AW_AGENTIC_EXECUTION_OUTCOME: ${{ steps.agentic_execution.outcome }} + GH_AW_ENGINE_STEP_TIMEOUT_MINUTES: ${{ fromJSON(vars.GH_AW_DEFAULT_TIMEOUT_MINUTES || '20') }} + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'detect_agent_errors.cjs')); + await main(); + - name: Configure Git credentials + env: + GITHUB_REPOSITORY: ${{ github.repository }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_TOKEN: ${{ github.token }} + run: bash "${RUNNER_TEMP}/gh-aw/actions/configure_git_credentials.sh" + - name: Copy Copilot session state files to logs + if: always() + continue-on-error: true + run: bash "${RUNNER_TEMP}/gh-aw/actions/copy_copilot_session_state.sh" + - name: Stop MCP Gateway + if: always() + continue-on-error: true + env: + MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} + MCP_GATEWAY_AGENT_ID: ${{ steps.start-mcp-gateway.outputs.gateway-agent-id }} + GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }} + run: | + bash "${RUNNER_TEMP}/gh-aw/actions/stop_mcp_gateway.sh" "$GATEWAY_PID" + - name: Redact secrets in logs + id: redact_secrets + if: always() + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'redact_secrets.cjs')); + await main(); + env: + GH_AW_SECRET_NAMES: 'GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN' + SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Append agent step summary + if: always() + run: bash "${RUNNER_TEMP}/gh-aw/actions/append_agent_step_summary.sh" + - name: Copy Safe Outputs + if: always() + env: + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + run: | + mkdir -p /tmp/gh-aw + cp "$GH_AW_SAFE_OUTPUTS" /tmp/gh-aw/safeoutputs.jsonl 2>/dev/null || true + - name: Ingest agent output + id: collect_output + if: always() + 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: "*.githubusercontent.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,docs.github.com,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,learn.microsoft.com,lfs.github.com,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,patch-diff.githubusercontent.com,patchdiff.githubusercontent.com,ppa.launchpad.net,raw.githubusercontent.com,s.symcb.com,s.symcd.com,security.ubuntu.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + with: + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'collect_ndjson_output.cjs')); + await main(); + - name: Parse agent logs for step summary + if: always() + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + with: + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'parse_copilot_log.cjs')); + await main(); + - name: Parse MCP Gateway logs for step summary + if: always() + id: parse-mcp-gateway + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'parse_mcp_gateway_log.cjs')); + await main(); + - name: Print firewall logs + if: always() + continue-on-error: true + env: + AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs + run: bash "${RUNNER_TEMP}/gh-aw/actions/print_firewall_logs.sh" --rootless + - name: Parse token usage for step summary + if: always() + id: parse-token-usage + continue-on-error: true + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, '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 path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'awf_reflect_summary.cjs')); + await main(); + - name: Generate observability summary + if: always() + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'generate_observability_summary.cjs')); + await main(core); + - name: Write agent output placeholder if missing + if: always() + run: | + if [ ! -f /tmp/gh-aw/agent_output.json ]; then + echo '{"items":[]}' > /tmp/gh-aw/agent_output.json + fi + # Small dedicated copy of the agent output so safe-output processing + # survives a failed or timed-out upload of the larger agent artifact + - name: Upload agent output fallback artifact + if: always() && steps.redact_secrets.outcome == 'success' + continue-on-error: true + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + with: + name: agent-output-fallback + path: | + /tmp/gh-aw/agent_output.json + /tmp/gh-aw/safeoutputs.jsonl + /tmp/gh-aw/agent_execution.json + /tmp/gh-aw/agent_execution_exit_code.txt + /tmp/gh-aw/agent_usage.jsonl + /tmp/gh-aw/agent_usage.json + /tmp/gh-aw/agent/harness_retry.json + /tmp/gh-aw/agent/model-endpoint-mismatch.json + /tmp/gh-aw/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl + /tmp/gh-aw/sandbox/firewall-audit-logs/api-proxy-logs/model-routing.jsonl + /tmp/gh-aw/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl + /tmp/gh-aw/sandbox/firewall/logs/api-proxy-logs/model-routing.jsonl + /tmp/gh-aw/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl + /tmp/gh-aw/sandbox/firewall/audit/api-proxy-logs/model-routing.jsonl + /tmp/gh-aw/awf-resolved-config.json + if-no-files-found: ignore + retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }} + - name: Upload agent artifacts + if: always() && steps.redact_secrets.outcome == 'success' + continue-on-error: true + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + with: + name: agent + path: | + /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/agent_execution.json + /tmp/gh-aw/agent_execution_exit_code.txt + /tmp/gh-aw/agent-session.jsonl + /tmp/gh-aw/agent-errors.jsonl + /tmp/gh-aw/aw-prompts/user.txt + /tmp/gh-aw/aw-prompts/system.txt + /tmp/gh-aw/skill_inventory.json + /tmp/gh-aw/sandbox/agent/logs/ + /tmp/gh-aw/redacted-urls.log + /tmp/gh-aw/mcp-logs/ + /tmp/gh-aw/agent_usage.json + /tmp/gh-aw/runtime/aw_info.json + /tmp/gh-aw/agent_usage.jsonl + /tmp/gh-aw/agent/model-endpoint-mismatch.json + /tmp/gh-aw/agent/model-resolution.json + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/agent/harness_retry.json + /tmp/gh-aw/pre-agent-audit.txt + /tmp/gh-aw/github_rate_limits.jsonl + /tmp/gh-aw/otel.jsonl + /tmp/gh-aw/otlp-export-errors.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/awf-resolved-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 + retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }} + + conclusion: + name: conclusion + needs: + - activation + - agent + - detection + - safe_outputs + if: > + always() && (needs.agent.result != 'skipped' || needs.activation.outputs.lockdown_check_failed == 'true' || + needs.activation.outputs.oauth_token_check_failed == 'true' || needs.activation.outputs.stale_lock_file_failed == 'true' || + needs.activation.outputs.daily_ai_credits_exceeded == 'true' || needs.activation.outputs.daily_ai_credits_guardrail_status == 'structural_error' || + needs.activation.outputs.daily_ai_credits_guardrail_status == 'transient_error') + runs-on: ubuntu-slim + environment: production + # Permissions for the conclusion job (workflow permissions default to none). + permissions: + actions: read + checks: read + contents: write + issues: write + pull-requests: write + concurrency: + group: "gh-aw-conclusion-update-ci-dependencies" + cancel-in-progress: false + queue: max + env: + GH_AW_JOB_DISPLAY_NAMES: "{\"activation\":\"activation\",\"agent\":\"agent\",\"conclusion\":\"conclusion\",\"detection\":\"detection\",\"pre_activation\":\"pre_activation\",\"safe_outputs\":\"safe_outputs\"}" + GH_AW_JOB_RESULTS: "{\"activation\":{\"result\":\"${{ needs.activation.result }}\"},\"agent\":{\"result\":\"${{ needs.agent.result }}\"},\"detection\":{\"result\":\"${{ needs.detection.result }}\"},\"safe_outputs\":{\"result\":\"${{ needs.safe_outputs.result }}\"}}" + GH_AW_JOB_TIMING_ELIGIBLE: "{\"activation\":true,\"agent\":true,\"conclusion\":true,\"detection\":true,\"pre_activation\":true,\"safe_outputs\":true}" + GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }} + outputs: + incomplete_count: ${{ steps.report_incomplete.outputs.incomplete_count }} + noop_comment_body: ${{ steps.noop.outputs.noop_comment_body }} + noop_message: ${{ steps.noop.outputs.noop_message }} + tools_reported: ${{ steps.missing_tool.outputs.tools_reported }} + total_count: ${{ steps.missing_tool.outputs.total_count }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@221ba4f4319de6b8e809d1a15528b3ae6a818aa5 # v1.0.1 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "Update CI Dependencies" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/update-ci-dependencies.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.103" + GH_AW_INFO_AWF_VERSION: "v0.29.0" + GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_SETUP_AW_CONTEXT: ${{ inputs.aw_context }} + - name: Download agent output artifact + id: download-agent-output + continue-on-error: true + uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 + with: + pattern: "{agent,agent-output-fallback}" + merge-multiple: true + path: /tmp/gh-aw/ + - name: Setup agent output environment variable + id: setup-agent-output-env + if: steps.download-agent-output.outcome == 'success' + run: | + mkdir -p /tmp/gh-aw/ + find "/tmp/gh-aw/" -type f -print + if [ -f "/tmp/gh-aw/agent_output.json" ]; then + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" + fi + - name: Restore runtime model metadata + if: always() + run: | + if [ -f /tmp/gh-aw/runtime/aw_info.json ]; then cp /tmp/gh-aw/runtime/aw_info.json /tmp/gh-aw/aw_info.json; fi + - name: Warn if threat detection produced no verdict + if: always() && needs.detection.result != 'skipped' && (needs.detection.outputs.detection_reason == 'agent_failure' || needs.detection.outputs.detection_reason == 'parse_error' || needs.detection.outputs.detection_conclusion == '') + run: echo "::warning::Threat detection produced no security verdict. Review the detection job logs before trusting the agent outputs." + - name: Download detection artifact + id: download-detection-artifact + continue-on-error: true + uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 + with: + name: detection + path: /tmp/gh-aw/threat-detection/ + - name: Download Safe Outputs Items Manifest + id: download-safe-outputs-manifest + if: always() + continue-on-error: true + uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 + with: + pattern: safe-outputs-items + merge-multiple: true + path: /tmp/gh-aw/ + - name: Process no-op messages + id: noop + 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: "2" + GH_AW_WORKFLOW_NAME: "Update CI Dependencies" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/update-ci-dependencies.md" + GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }} + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} + GH_AW_NOOP_REPORT_AS_ISSUE: "false" + GH_AW_AIC: ${{ needs.agent.outputs.aic }} + GH_AW_THREAT_DETECTION_AIC: ${{ needs.detection.outputs.aic }} + GH_AW_AMBIENT_CONTEXT: ${{ needs.agent.outputs.ambient_context }} + GH_AW_WORKFLOW_ID: "update-ci-dependencies" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'handle_noop_message.cjs')); + await main(); + - name: Log detection run + id: detection_runs + 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: "Update CI Dependencies" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/update-ci-dependencies.md" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }} + GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'handle_detection_runs.cjs')); + await main(); + - name: Record missing tool + id: missing_tool + 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" + GH_AW_WORKFLOW_NAME: "Update CI Dependencies" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/update-ci-dependencies.md" + GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'missing_tool.cjs')); + await main(); + - name: Record incomplete + id: report_incomplete + 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" + GH_AW_WORKFLOW_NAME: "Update CI Dependencies" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/update-ci-dependencies.md" + GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'report_incomplete_handler.cjs')); + await main(); + - name: Handle agent failure + id: handle_agent_failure + if: always() + 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: "Update CI Dependencies" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/update-ci-dependencies.md" + 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: "update-ci-dependencies" + GH_AW_ACTION_FAILURE_ISSUE_EXPIRES_HOURS: "0" + GH_AW_ENGINE_ID: "copilot" + GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} + GH_AW_CHECKOUT_PR_INVALIDATED: ${{ needs.agent.outputs.checkout_pr_invalidated }} + GH_AW_AI_CREDITS_RATE_LIMIT_ERROR: ${{ needs.agent.outputs.ai_credits_rate_limit_error || 'false' }} + GH_AW_UNKNOWN_MODEL_AI_CREDITS: ${{ needs.agent.outputs.unknown_model_ai_credits || 'false' }} + GH_AW_AIC: ${{ needs.agent.outputs.aic }} + GH_AW_THREAT_DETECTION_AIC: ${{ needs.detection.outputs.aic }} + GH_AW_DETECTION_JOB_RESULT: ${{ needs.detection.result }} + GH_AW_MAX_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }} + GH_AW_DEFAULT_CHECKOUT_USES_TRIGGER_REF: "true" + GH_AW_INFERENCE_ACCESS_ERROR: ${{ needs.agent.outputs.inference_access_error }} + 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_MODEL_ENDPOINT_MISMATCH_ERROR: ${{ needs.agent.outputs.model_endpoint_mismatch_error }} + GH_AW_HTTP_400_RESPONSE_ERROR: ${{ needs.agent.outputs.http_400_response_error }} + GH_AW_MAX_CACHE_MISSES_EXCEEDED: ${{ needs.agent.outputs.max_cache_misses_exceeded }} + GH_AW_MISSING_MODEL_PRICING_ERROR: ${{ needs.agent.outputs.missing_model_pricing_error }} + GH_AW_MISSING_MODEL_PRICING_MODEL_NAME: ${{ needs.agent.outputs.missing_model_pricing_model_name }} + GH_AW_SHELL_EXPANSION_GUARD_REJECTED: ${{ needs.agent.outputs.shell_expansion_guard_rejected }} + GH_AW_ENGINE_API_HOSTS: "api.enterprise.githubcopilot.com,api.githubcopilot.com,api.business.githubcopilot.com,api.individual.githubcopilot.com" + GH_AW_CODE_PUSH_FAILURE_ERRORS: ${{ needs.safe_outputs.outputs.code_push_failure_errors }} + GH_AW_CODE_PUSH_FAILURE_COUNT: ${{ needs.safe_outputs.outputs.code_push_failure_count }} + GH_AW_LOCKDOWN_CHECK_FAILED: ${{ needs.activation.outputs.lockdown_check_failed }} + GH_AW_OAUTH_TOKEN_CHECK_FAILED: ${{ needs.activation.outputs.oauth_token_check_failed }} + GH_AW_STALE_LOCK_FILE_FAILED: ${{ needs.activation.outputs.stale_lock_file_failed }} + GH_AW_DAILY_AI_CREDITS_EXCEEDED: ${{ needs.activation.outputs.daily_ai_credits_exceeded }} + GH_AW_DAILY_AI_CREDITS_GUARDRAIL_STATUS: ${{ needs.activation.outputs.daily_ai_credits_guardrail_status }} + GH_AW_DAILY_AI_CREDITS_GUARDRAIL_ERROR: ${{ needs.activation.outputs.daily_ai_credits_guardrail_error }} + GH_AW_DAILY_AI_CREDITS_TOTAL: ${{ needs.activation.outputs.daily_ai_credits_total }} + GH_AW_DAILY_AI_CREDITS_ESTIMATED: ${{ needs.activation.outputs.daily_ai_credits_estimated }} + GH_AW_DAILY_AI_CREDITS_THRESHOLD: ${{ needs.activation.outputs.daily_ai_credits_threshold }} + GH_AW_DAILY_AI_CREDITS_CONTINUE_ON_ERROR: "false" + 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: "${{ fromJSON(vars.GH_AW_DEFAULT_TIMEOUT_MINUTES || '20') }}" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'handle_agent_failure.cjs')); + await main(); + - name: Report failed jobs + id: report_failed_jobs + if: always() + 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: "Update CI Dependencies" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/update-ci-dependencies.md" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_REPORT_FAILED_JOBS: "true" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'report_failed_jobs.cjs')); + await main(); + - name: Collect usage artifact files + if: always() + continue-on-error: true + env: + GH_AW_DETECTION_JOB_RESULT: ${{ needs.detection.result }} + GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }} + GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }} + run: bash "${RUNNER_TEMP}/gh-aw/actions/collect_usage_artifact_files.sh" + - name: Generate usage activity summary and unified session + if: always() + continue-on-error: true + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_GRADER_MANIFEST_0: '{"version":2,"graders":[]}' + GH_AW_GRADER_MANIFEST_CHUNKS: '1' + GH_AW_JOB_DURATIONS: ${{ steps.report_failed_jobs.outputs.job_durations }} + GH_AW_DAILY_AI_CREDITS_GUARDRAIL_STATUS: ${{ needs.activation.outputs.daily_ai_credits_guardrail_status }} + GH_AW_DAILY_AI_CREDITS_EXCEEDED: ${{ needs.activation.outputs.daily_ai_credits_exceeded }} + GH_AW_DAILY_AI_CREDITS_TOTAL: ${{ needs.activation.outputs.daily_ai_credits_total }} + GH_AW_DAILY_AI_CREDITS_ESTIMATED: ${{ needs.activation.outputs.daily_ai_credits_estimated }} + GH_AW_DAILY_AI_CREDITS_THRESHOLD: ${{ needs.activation.outputs.daily_ai_credits_threshold }} + with: + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'generate_usage_artifacts.cjs')); + await main(); + - name: Upload usage artifact + id: upload-usage-artifact + if: always() + continue-on-error: true + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + with: + name: usage + path: | + /tmp/gh-aw/usage/aw_session.jsonl + /tmp/gh-aw/usage/aw_info.json + /tmp/gh-aw/usage/aw-info.jsonl + /tmp/gh-aw/usage/agent_usage.json + /tmp/gh-aw/usage/agent_usage.jsonl + /tmp/gh-aw/usage/detection_usage.jsonl + /tmp/gh-aw/usage/evals.jsonl + /tmp/gh-aw/usage/graders/grader_manifest.json + /tmp/gh-aw/usage/graders/grader_results.json + /tmp/gh-aw/usage/github_rate_limits.jsonl + /tmp/gh-aw/usage/agent/token_usage.jsonl + /tmp/gh-aw/usage/agent/model-routing.jsonl + /tmp/gh-aw/usage/agent/execution.json + /tmp/gh-aw/usage/agent/harness_retry.json + /tmp/gh-aw/usage/detection/token_usage.jsonl + /tmp/gh-aw/usage/detection/execution.json + /tmp/gh-aw/usage/detection/harness_retry.json + /tmp/gh-aw/usage/detection/detection_result.json + /tmp/gh-aw/usage/evals/token_usage.jsonl + /tmp/gh-aw/usage/evals/execution.json + /tmp/gh-aw/usage/experiment/state.jsonl + /tmp/gh-aw/usage/experiment/state.json + /tmp/gh-aw/usage/experiment/assignments.json + /tmp/gh-aw/usage/activity/summary.json + if-no-files-found: ignore + retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }} + - name: Wait before retrying usage artifact upload + if: always() && steps.upload-usage-artifact.outcome == 'failure' + run: sleep 10 + - name: Retry upload usage artifact + id: upload-usage-artifact-retry + if: always() && steps.upload-usage-artifact.outcome == 'failure' + continue-on-error: true + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + with: + name: usage + path: | + /tmp/gh-aw/usage/aw_session.jsonl + /tmp/gh-aw/usage/aw_info.json + /tmp/gh-aw/usage/aw-info.jsonl + /tmp/gh-aw/usage/agent_usage.json + /tmp/gh-aw/usage/agent_usage.jsonl + /tmp/gh-aw/usage/detection_usage.jsonl + /tmp/gh-aw/usage/evals.jsonl + /tmp/gh-aw/usage/graders/grader_manifest.json + /tmp/gh-aw/usage/graders/grader_results.json + /tmp/gh-aw/usage/github_rate_limits.jsonl + /tmp/gh-aw/usage/agent/token_usage.jsonl + /tmp/gh-aw/usage/agent/model-routing.jsonl + /tmp/gh-aw/usage/agent/execution.json + /tmp/gh-aw/usage/agent/harness_retry.json + /tmp/gh-aw/usage/detection/token_usage.jsonl + /tmp/gh-aw/usage/detection/execution.json + /tmp/gh-aw/usage/detection/harness_retry.json + /tmp/gh-aw/usage/detection/detection_result.json + /tmp/gh-aw/usage/evals/token_usage.jsonl + /tmp/gh-aw/usage/evals/execution.json + /tmp/gh-aw/usage/experiment/state.jsonl + /tmp/gh-aw/usage/experiment/state.json + /tmp/gh-aw/usage/experiment/assignments.json + /tmp/gh-aw/usage/activity/summary.json + if-no-files-found: ignore + overwrite: true + retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }} + + detection: + name: detection + needs: + - activation + - agent + if: always() && needs.agent.result != 'skipped' + runs-on: ubuntu-latest + # Permissions for the detection job (workflow permissions default to none). + permissions: + contents: read + copilot-requests: write + timeout-minutes: 10 + env: + GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }} + outputs: + aic: ${{ steps.parse_detection_token_usage.outputs.aic }} + detection_conclusion: ${{ steps.detection_conclusion.outputs.conclusion }} + detection_reason: ${{ steps.detection_conclusion.outputs.reason }} + detection_success: ${{ steps.detection_conclusion.outputs.success }} + run_detection: ${{ steps.detection_guard.outputs.run_detection }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@221ba4f4319de6b8e809d1a15528b3ae6a818aa5 # v1.0.1 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "Update CI Dependencies" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/update-ci-dependencies.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.103" + GH_AW_INFO_AWF_VERSION: "v0.29.0" + GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_SETUP_AW_CONTEXT: ${{ inputs.aw_context }} + - name: Download activation artifact + continue-on-error: true + uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 + with: + name: activation + path: /tmp/gh-aw + - name: Download agent output artifact + id: download-agent-output + continue-on-error: true + uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 + with: + pattern: "{agent,agent-output-fallback}" + merge-multiple: true + path: /tmp/gh-aw/ + - name: Setup agent output environment variable + id: setup-agent-output-env + if: steps.download-agent-output.outcome == 'success' + run: | + mkdir -p /tmp/gh-aw/ + find "/tmp/gh-aw/" -type f -print + if [ -f "/tmp/gh-aw/agent_output.json" ]; then + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" + fi + - name: Clear agent token usage + if: always() + run: rm -f /tmp/gh-aw/agent_usage.json + - name: Checkout repository for patch context + if: needs.agent.outputs.has_patch == 'true' + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + # --- Threat Detection --- + - name: Initialize detection execution evidence + run: | + mkdir -p "/tmp/gh-aw/threat-detection" + evidence_tmp="/tmp/gh-aw/threat-detection/execution.json.tmp" + printf '{"version":1,"component":"detection","run_id":%s,"run_attempt":%s,"state":"not_started"}\n' "$GITHUB_RUN_ID" "$GITHUB_RUN_ATTEMPT" > "$evidence_tmp" + mv "$evidence_tmp" "/tmp/gh-aw/threat-detection/execution.json" + - name: Clear inherited Copilot session state + run: rm -rf /tmp/gh-aw/sandbox/agent/logs/copilot-session-state + - name: Clean stale firewall files from agent artifact + run: | + 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.29.0@sha256:b14bd399376180b5649a9324be3b50fbfc82bfe8f0c80045840416b5a4e65b96 ghcr.io/github/gh-aw-firewall/api-proxy:0.29.0@sha256:baff00b856a4bdc93bce134928c70af3d3492f2e518757115042040674d56b0b ghcr.io/github/gh-aw-firewall/squid:0.29.0@sha256:6e0cbf7f980beb78b5461563a8164f6439ca959bc93733d5a6b52972e523ed50 + - name: Check if detection needed + id: detection_guard + if: always() + env: + OUTPUT_TYPES: ${{ needs.agent.outputs.output_types }} + HAS_PATCH: ${{ needs.agent.outputs.has_patch }} + run: | + if [[ -n "$OUTPUT_TYPES" || "$HAS_PATCH" == "true" ]]; then + echo "run_detection=true" >> "$GITHUB_OUTPUT" + echo "Detection will run: output_types=$OUTPUT_TYPES, has_patch=$HAS_PATCH" + else + echo "run_detection=false" >> "$GITHUB_OUTPUT" + echo "Detection skipped: no agent outputs or patches to analyze" + fi + - name: Clear MCP Config for detection + if: always() && steps.detection_guard.outputs.run_detection == 'true' + run: | + rm -f "${RUNNER_TEMP}/gh-aw/mcp-config/mcp-servers.json" + rm -f "$HOME/.copilot/mcp-config.json" + rm -f "$GITHUB_WORKSPACE/.gemini/settings.json" + - name: Prepare threat detection files + if: always() && steps.detection_guard.outputs.run_detection == 'true' + run: | + bash "${RUNNER_TEMP}/gh-aw/actions/prepare_threat_detection_files.sh" + - name: Setup threat detection + id: detection_setup + if: always() && steps.detection_guard.outputs.run_detection == 'true' + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + WORKFLOW_NAME: "Update CI Dependencies" + WORKFLOW_DESCRIPTION: "No description provided" + HAS_PATCH: ${{ needs.agent.outputs.has_patch }} + GH_AW_DETECTION_CONTINUE_ON_ERROR: "true" + GH_AW_DETECTION_SKIP_PROMPT_SUMMARY: "true" + with: + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'setup_threat_detection.cjs')); + await main(); + - name: Ensure threat-detection directory and log + if: always() && steps.detection_guard.outputs.run_detection == 'true' + run: | + mkdir -p /tmp/gh-aw/threat-detection + touch /tmp/gh-aw/threat-detection/detection.log + - name: Install AWF binary + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.29.0 --rootless + - name: Setup Node.js + uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.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.103 --checksums-sha256 26cd3e4b32cde498e4961fb4d48e7b85d7859fc69af1a645a19201fdd577bdb2 --prefer-toolcache + env: + GH_HOST: github.com + GH_AW_COPILOT_MIN_VERSION: 1.0.35 + - name: Install threat-detect binary + id: threat_detect_install + if: always() && steps.detection_guard.outputs.run_detection == 'true' + continue-on-error: true + run: | + bash "${RUNNER_TEMP}/gh-aw/actions/install_threat_detect_binary.sh" v0.5.3 --artifact-base-url https://github.com/github/gh-aw-threat-detection/releases/download --sha256-amd64 7cfab3bd02717968a0584ddd3790cff22550059e36d6f656c4f35e9d27851009 --sha256-arm64 6f355949af98e7b5527a958ac11431bd7867db45c0191b94c3a205c662181cc6 + - name: Execute threat detection with AWF + id: detection_agentic_execution + if: always() && steps.detection_guard.outputs.run_detection == 'true' && steps.detection_setup.outcome == 'success' && steps.detection_setup.outputs.ready == 'true' && steps.threat_detect_install.outcome == 'success' + continue-on-error: true + timeout-minutes: 10 + env: + AWF_REFLECT_ENABLED: 1 + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_DUMMY_BYOK: dummy-byok-key-for-offline-mode + COPILOT_GITHUB_TOKEN: ${{ github.token }} + COPILOT_MODEL: ${{ vars.GH_AW_MODEL_DETECTION_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'detection' }} + GH_AW_HARNESS_MAX_RETRIES: 0 + GH_AW_LLM_PROVIDER: github + GH_AW_MAX_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_DETECTION_MAX_AI_CREDITS || '400' }} + GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }} + GH_AW_MODEL_FALLBACK: ${{ vars.GH_AW_MODEL_DETECTION_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'auto' }} + GH_AW_PHASE: detection + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_TIMEOUT_MINUTES: 10 + GH_AW_VERSION: v1.0.1 + GITHUB_API_URL: ${{ github.api_url }} + GITHUB_AW: true + GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows + GITHUB_COPILOT_PROMPT_MODE_EXTENSIONS: false + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md + GITHUB_WORKSPACE: ${{ github.workspace }} + GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com + GIT_AUTHOR_NAME: github-actions[bot] + GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com + GIT_COMMITTER_NAME: github-actions[bot] + RUNNER_TEMP: ${{ runner.temp }} + S2STOKENS: true + TRACEPARENT: ${{ env.GITHUB_AW_OTEL_TRACE_ID != '' && env.GITHUB_AW_OTEL_PARENT_SPAN_ID != '' && format('00-{0}-{1}-01', env.GITHUB_AW_OTEL_TRACE_ID, env.GITHUB_AW_OTEL_PARENT_SPAN_ID) || '' }} + WORKFLOW_NAME: "Update CI Dependencies" + WORKFLOW_DESCRIPTION: "No description provided" + HAS_PATCH: ${{ needs.agent.outputs.has_patch }} + GH_AW_DETECTION_CONTINUE_ON_ERROR: "true" + run: | + mkdir -p "/tmp/gh-aw/threat-detection" + evidence_tmp="/tmp/gh-aw/threat-detection/execution.json.tmp" + printf '{"version":1,"component":"detection","run_id":%s,"run_attempt":%s,"state":"started"}\n' "$GITHUB_RUN_ID" "$GITHUB_RUN_ATTEMPT" > "$evidence_tmp" + mv "$evidence_tmp" "/tmp/gh-aw/threat-detection/execution.json" + export GH_AW_AWF_EXECUTION_COMPONENT="detection" + export GH_AW_AWF_EXECUTION_EVIDENCE_FILE="/tmp/gh-aw/threat-detection/execution.json" + set -o pipefail + printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt + GH_AW_COPILOT_SRC="$(command -v copilot 2>/dev/null || true)" + if [ -z "$GH_AW_COPILOT_SRC" ] || [ ! -x "$GH_AW_COPILOT_SRC" ]; then + echo "GitHub Copilot CLI executable not found on PATH after installation" >&2 + exit 127 + fi + GH_AW_COPILOT_BIN="${RUNNER_TEMP}/gh-aw/bin/copilot" + mkdir -p "${RUNNER_TEMP}/gh-aw/bin" + if [ "$GH_AW_COPILOT_SRC" != "$GH_AW_COPILOT_BIN" ]; then + cp "$GH_AW_COPILOT_SRC" "$GH_AW_COPILOT_BIN" + fi + chmod 755 "$GH_AW_COPILOT_BIN" + + (umask 177 && touch /tmp/gh-aw/threat-detection/detection.log) + GH_AW_MAX_AI_CREDITS="${GH_AW_MAX_AI_CREDITS:-400}" + if [[ ! "$GH_AW_MAX_AI_CREDITS" =~ ^[0-9]+$ ]]; then + GH_AW_MAX_AI_CREDITS="400" + fi + + if [[ "${GH_AW_ADMISSION_RESULT:-}" == "admitted" && -n "${GH_AW_ADMISSION_MAX_AI_CREDITS:-}" ]]; then + if [[ ! "$GH_AW_ADMISSION_MAX_AI_CREDITS" =~ ^[1-9][0-9]{0,9}$ ]] || (( GH_AW_ADMISSION_MAX_AI_CREDITS > 2147483647 )); then + echo "ERR_ADMISSION: Invalid runtime admission allowance." >&2 + exit 1 + fi + GH_AW_MAX_AI_CREDITS="$GH_AW_ADMISSION_MAX_AI_CREDITS" + echo "Admission allowance applied (value withheld)." + else + echo "No component admission allowance; retaining existing budget policy (value withheld)." + fi + unset GH_AW_ADMISSION_RESULT GH_AW_ADMISSION_MAX_AI_CREDITS + printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.29.0/awf-config.schema.json\",\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"maxCacheMisses\":5,\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-6\",\"gpt-5.4\",\"gpt-5.5\",\"gpt-5.6\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"auto\":[\"copilot/auto\",\"large\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\",\"kimi\"],\"computer-use\":[\"copilot/*computer-use*\",\"google/*computer-use*\",\"gemini/*computer-use*\",\"openai/*computer-use*\"],\"copilot\":[\"agent\"],\"deep-research\":[\"copilot/deep-research*\",\"copilot/o3-deep-research*\",\"copilot/o4-mini-deep-research*\",\"google/deep-research*\",\"gemini/deep-research*\",\"openai/o3-deep-research*\",\"openai/o4-mini-deep-research*\"],\"detection\":[\"small\"],\"evals\":[\"small\"],\"fable\":[\"copilot/*fable*\",\"anthropic/*fable*\"],\"gemini\":[\"agent\"],\"gemini-3-flash\":[\"copilot/gemini-3*flash*\",\"google/gemini-3*flash*\",\"gemini/gemini-3*flash*\"],\"gemini-3-pro\":[\"copilot/gemini-3*pro*\",\"google/gemini-3*pro*\",\"google/nano-banana*\",\"gemini/gemini-3*pro*\"],\"gemini-3.1-flash\":[\"copilot/gemini-3.1*flash*\",\"google/gemini-3.1*flash*\",\"gemini/gemini-3.1*flash*\"],\"gemini-3.1-pro\":[\"copilot/gemini-3.1*pro*\",\"google/gemini-3.1*pro*\",\"gemini/gemini-3.1*pro*\"],\"gemini-3.5-flash\":[\"copilot/gemini-3.5*flash*\",\"google/gemini-3.5*flash*\",\"gemini/gemini-3.5*flash*\"],\"gemini-3.6-flash\":[\"copilot/gemini-3.6*flash*\",\"google/gemini-3.6*flash*\",\"gemini/gemini-3.6*flash*\"],\"gemini-3.7-flash\":[\"copilot/gemini-3.7*flash*\",\"google/gemini-3.7*flash*\",\"gemini/gemini-3.7*flash*\"],\"gemini-3.8-flash\":[\"copilot/gemini-3.8*flash*\",\"google/gemini-3.8*flash*\",\"gemini/gemini-3.8*flash*\"],\"gemini-flash\":[\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"],\"gemini-flash-lite\":[\"copilot/gemini-*flash*lite*\",\"google/gemini-*flash*lite*\",\"gemini/gemini-*flash*lite*\"],\"gemini-omni\":[\"copilot/gemini-omni*\",\"google/gemini-omni*\",\"gemini/gemini-omni*\"],\"gemini-pro\":[\"copilot/gemini-*pro*\",\"google/gemini-*pro*\",\"gemini/gemini-*pro*\"],\"gemma\":[\"copilot/gemma*\",\"google/gemma*\",\"gemini/gemma*\"],\"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*\"],\"gpt-5.1\":[\"copilot/gpt-5.1*\",\"openai/gpt-5.1*\"],\"gpt-5.2\":[\"copilot/gpt-5.2*\",\"openai/gpt-5.2*\"],\"gpt-5.3\":[\"copilot/gpt-5.3*\",\"openai/gpt-5.3*\"],\"gpt-5.4\":[\"copilot/gpt-5.4*\",\"openai/gpt-5.4*\"],\"gpt-5.5\":[\"copilot/gpt-5.5*\",\"openai/gpt-5.5*\"],\"gpt-5.6\":[\"copilot/gpt-5.6*\",\"openai/gpt-5.6*\"],\"gpt-6\":[\"copilot/gpt-6*\",\"openai/gpt-6*\"],\"grok\":[\"copilot/*grok*\",\"openai/*grok*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"image-generation\":[\"copilot/gpt-image*\",\"openai/gpt-image*\",\"openai/chatgpt-image*\",\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"google/imagen*\"],\"kimi\":[\"copilot/kimi*\",\"openai/kimi*\"],\"kiwi\":[\"copilot/kiwi*\",\"openai/kiwi*\"],\"large\":[\"sonnet\",\"gpt-6\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"lyria\":[\"google/lyria*\",\"gemini/lyria*\",\"copilot/lyria*\"],\"mai-code\":[\"copilot/MAI-Code*\",\"copilot/mai-code*\",\"openai/MAI-Code*\"],\"mini\":[\"haiku\",\"gpt-5-mini\",\"gpt-5-nano\",\"gemini-flash-lite\"],\"nano-banana\":[\"copilot/nano-banana*\",\"google/nano-banana*\",\"gemini/nano-banana*\"],\"opus\":[\"copilot/*opus*\",\"anthropic/*opus*\"],\"opusplan\":[\"opus?effort=high\"],\"raptor-mini\":[\"copilot/raptor*\",\"openai/raptor*\"],\"reasoning\":[\"copilot/o1*\",\"copilot/o3*\",\"copilot/o4*\",\"openai/o1*\",\"openai/o3*\",\"openai/o4*\"],\"robotics\":[\"copilot/*robotics*\",\"google/*robotics*\",\"gemini/*robotics*\"],\"small\":[\"mini\"],\"small-agent\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash\"],\"sonnet\":[\"copilot/*sonnet*\",\"anthropic/*sonnet*\"],\"sonnet-6x\":[\"copilot/*sonnet-4.5*\",\"copilot/*sonnet-4.6*\",\"copilot/*sonnet-5*\",\"copilot/*sonnet-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\",\"anthropic/*sonnet-5*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"veo\":[\"google/veo*\",\"gemini/veo*\"],\"vision\":[\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.29.0,squid=sha256:6e0cbf7f980beb78b5461563a8164f6439ca959bc93733d5a6b52972e523ed50,agent=sha256:b14bd399376180b5649a9324be3b50fbfc82bfe8f0c80045840416b5a4e65b96,api-proxy=sha256:baff00b856a4bdc93bce134928c70af3d3492f2e518757115042040674d56b0b,cli-proxy=sha256:087a8e4efff8ac62d46e106cd22005c002822b1481fc233097799511be353b5d\",\"agentTimeout\":10},\"logging\":{\"proxyLogsDir\":\"/tmp/gh-aw/sandbox/firewall/logs\",\"auditDir\":\"/tmp/gh-aw/sandbox/firewall/audit\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json" + cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json + export GH_AW_MODELS_JSON_PATH="/tmp/gh-aw/models.json" + GH_AW_DOCKER_HOST="" + if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then + GH_AW_DOCKER_HOST="${DOCKER_HOST}" + fi + if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then + _GH_AW_CHROOT_JSON=$(jq -c --arg src "${RUNNER_TEMP}/gh-aw" --arg user "$(id -un)" --argjson uid "$(id -u)" --argjson gid "$(id -g)" --arg home "${RUNNER_TEMP}/gh-aw/home" '.chroot={"binariesSourcePath":$src,"identity":{"user":$user,"uid":$uid,"gid":$gid,"home":$home}}' "${RUNNER_TEMP}/gh-aw/awf-config.json") || { echo "chroot config patch failed" >&2; exit 1; } + printf '%s\n' "$_GH_AW_CHROOT_JSON" > "${RUNNER_TEMP}/gh-aw/awf-config.json" + fi + GH_AW_TOOL_CACHE_MOUNT="" + GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}" + if [ -d "$GH_AW_TOOL_CACHE" ]; then + if [[ "$GH_AW_TOOL_CACHE" != /opt/* ]]; then + GH_AW_TOOL_CACHE_MOUNT="$GH_AW_TOOL_CACHE:$GH_AW_TOOL_CACHE:ro" + fi + fi + # shellcheck disable=SC1003,SC2016,SC2086 + 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" ${GH_AW_TOOL_CACHE_MOUNT:+--mount "$GH_AW_TOOL_CACHE_MOUNT"} ${GH_AW_DOCKER_HOST:+--docker-host "$GH_AW_DOCKER_HOST"} --env-all --exclude-env ACTIONS_ID_TOKEN_REQUEST_TOKEN --exclude-env ACTIONS_ID_TOKEN_REQUEST_URL --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GH_AW_OTLP_ALL_HEADERS --exclude-env GH_AW_OTLP_ENDPOINTS --exclude-env OTEL_EXPORTER_OTLP_ENDPOINT --exclude-env OTEL_EXPORTER_OTLP_HEADERS --mount /tmp/gh-aw:/tmp/gh-aw:rw --mount /tmp/gh-aw/threat-detection:/tmp/gh-aw/threat-detection:rw --log-level info --session-state-dir /tmp/gh-aw/sandbox/agent/session-state --skip-pull \ + -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/bin:$PATH" && : "${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"; GH_AW_TOOL_CACHE="$RUNNER_TOOL_CACHE"; GH_AW_TOOL_BINS="$(find "$GH_AW_TOOL_CACHE" -maxdepth 5 -type d -name bin 2>/dev/null | tr "\n" ":")"; GH_AW_TOOL_BINS="${GH_AW_TOOL_BINS%:}"; export PATH="$PATH${GH_AW_TOOL_BINS:+:}$GH_AW_TOOL_BINS"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true; [ -n "$ERLANG_HOME" ] && export PATH="$ERLANG_HOME/bin:$PATH" || true && threat-detect --engine copilot --output /tmp/gh-aw/threat-detection/detection_result.json /tmp/gh-aw/threat-detection' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log + - name: Copy detection firewall logs + if: always() && steps.detection_guard.outputs.run_detection == 'true' + continue-on-error: true + run: | + mkdir -p /tmp/gh-aw/threat-detection/sandbox/firewall + if [ -d /tmp/gh-aw/sandbox/firewall/logs ]; then mkdir -p /tmp/gh-aw/threat-detection/sandbox/firewall/logs && cp -r /tmp/gh-aw/sandbox/firewall/logs/. /tmp/gh-aw/threat-detection/sandbox/firewall/logs/; fi + if [ -d /tmp/gh-aw/sandbox/firewall/audit ]; then mkdir -p /tmp/gh-aw/threat-detection/sandbox/firewall/audit && cp -r /tmp/gh-aw/sandbox/firewall/audit/. /tmp/gh-aw/threat-detection/sandbox/firewall/audit/; fi + - name: Redact secrets in detection logs + id: redact_detection_logs + if: always() && steps.detection_guard.outputs.run_detection == 'true' + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_SECRET_NAMES: 'GH_AW_DEFAULT_OTLP_ENDPOINT,GH_AW_DEFAULT_OTLP_HEADERS' + SECRET_GH_AW_DEFAULT_OTLP_ENDPOINT: ${{ secrets.GH_AW_DEFAULT_OTLP_ENDPOINT }} + SECRET_GH_AW_DEFAULT_OTLP_HEADERS: ${{ secrets.GH_AW_DEFAULT_OTLP_HEADERS }} + with: + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'redact_secrets.cjs')); + const { persistDetectionMasks } = require(path.join(actionsDir, 'detection_mask_state.cjs')); + await main({ additionalDirectories: ["/tmp/gh-aw/threat-detection/sandbox/firewall"], persistDetectionMasks }); + - name: Parse threat detection token usage for step summary + id: parse_detection_token_usage + if: always() && steps.detection_guard.outputs.run_detection == 'true' && steps.redact_detection_logs.outcome == 'success' + continue-on-error: true + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_TOKEN_USAGE_SUMMARY_TITLE: Threat Detection Token Usage + GH_AW_PHASE: detection + GH_AW_AGENT_USAGE_PATH: /tmp/gh-aw/threat-detection/detection_usage.json + GH_AW_AGENT_USAGE_JSONL_PATH: /tmp/gh-aw/threat-detection/detection_usage.jsonl + GH_AW_WRITE_EMPTY_USAGE: "true" + with: + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'parse_token_usage.cjs')); + await main(); + - name: Redact secrets in detection artifacts + id: redact_detection_artifacts + if: always() && steps.detection_guard.outputs.run_detection == 'true' + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_SECRET_NAMES: 'GH_AW_DEFAULT_OTLP_ENDPOINT,GH_AW_DEFAULT_OTLP_HEADERS' + SECRET_GH_AW_DEFAULT_OTLP_ENDPOINT: ${{ secrets.GH_AW_DEFAULT_OTLP_ENDPOINT }} + SECRET_GH_AW_DEFAULT_OTLP_HEADERS: ${{ secrets.GH_AW_DEFAULT_OTLP_HEADERS }} + with: + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'redact_secrets.cjs')); + const { persistDetectionMasks } = require(path.join(actionsDir, 'detection_mask_state.cjs')); + await main({ additionalDirectories: ["/tmp/gh-aw/threat-detection/sandbox/firewall"], persistDetectionMasks }); + - name: Render detection log + if: always() && steps.detection_guard.outputs.run_detection == 'true' && steps.redact_detection_logs.outcome == 'success' && steps.redact_detection_artifacts.outcome == 'success' + continue-on-error: true + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'render_detection_log.cjs')); + await main(); + - name: Upload threat detection artifact + if: always() && steps.detection_guard.outputs.run_detection == 'true' && steps.redact_detection_logs.outcome == 'success' && steps.redact_detection_artifacts.outcome == 'success' + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + with: + name: detection + path: | + /tmp/gh-aw/threat-detection/detection_result.json + /tmp/gh-aw/threat-detection/execution.json + /tmp/gh-aw/threat-detection/detection_usage.json + /tmp/gh-aw/threat-detection/detection_usage.jsonl + /tmp/gh-aw/threat-detection/sandbox/firewall/logs/ + /tmp/gh-aw/threat-detection/sandbox/firewall/audit/ + if-no-files-found: ignore + retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }} + - name: Conclude threat detection + id: detection_conclusion + if: always() && steps.detection_guard.outputs.run_detection == 'false' || (always() && steps.detection_guard.outputs.run_detection == 'true' && steps.redact_detection_logs.outcome == 'success' && steps.redact_detection_artifacts.outcome == 'success') + continue-on-error: true + env: + RUN_DETECTION: ${{ steps.detection_guard.outputs.run_detection }} + DETECTION_AGENTIC_EXECUTION_OUTCOME: ${{ steps.detection_agentic_execution.outcome }} + THREAT_DETECT_INSTALL_OUTCOME: ${{ steps.threat_detect_install.outcome }} + GH_AW_DETECTION_CONTINUE_ON_ERROR: "true" + run: | + bash "${RUNNER_TEMP}/gh-aw/actions/conclude_threat_detection.sh" /tmp/gh-aw/threat-detection/detection_result.json + - name: Upload skipped detection execution evidence + if: always() && steps.detection_guard.outputs.run_detection == 'false' + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + with: + name: detection + path: /tmp/gh-aw/threat-detection/execution.json + if-no-files-found: ignore + retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }} + + pre_activation: + name: pre_activation + if: > + github.ref == 'refs/heads/main' && (github.event_name == 'workflow_dispatch' || (github.event.workflow_run.conclusion == 'success' && + github.event.workflow_run.event == 'workflow_dispatch' && github.event.workflow_run.head_repository.full_name == github.repository)) + runs-on: ubuntu-slim + environment: production + env: + GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }} + outputs: + activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} + matched_command: '' + setup-parent-span-id: ${{ steps.setup.outputs.parent-span-id || steps.setup.outputs.span-id }} + setup-span-id: ${{ steps.setup.outputs.span-id }} + setup-trace-id: ${{ steps.setup.outputs.trace-id }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@221ba4f4319de6b8e809d1a15528b3ae6a818aa5 # v1.0.1 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "Update CI Dependencies" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/update-ci-dependencies.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.103" + GH_AW_INFO_AWF_VERSION: "v0.29.0" + GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_SETUP_AW_CONTEXT: ${{ inputs.aw_context }} + - name: Check team membership for workflow + id: check_membership + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_REQUIRED_ROLES: "admin,maintainer,write" + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'check_membership.cjs')); + await main(); + + safe_outputs: + name: safe_outputs + needs: + - activation + - agent + - detection + if: (!cancelled()) && needs.agent.result != 'skipped' && needs.detection.result == 'success' + runs-on: ubuntu-latest # Safe-output code publication checks out repository files; ubuntu-slim is limited to 15 minutes. + environment: production + # Permissions for the safe_outputs job (workflow permissions default to none). + permissions: + contents: write + id-token: write + issues: write + pull-requests: write + timeout-minutes: 45 + env: + GH_AW_AGENT_AIC: ${{ needs.agent.outputs.aic }} + GH_AW_AIC: ${{ needs.agent.outputs.aic }} + GH_AW_AMBIENT_CONTEXT: ${{ needs.agent.outputs.ambient_context }} + GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/update-ci-dependencies" + GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }} + GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }} + GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }} + GH_AW_HEAD_SHA: ${{ github.event.workflow_run.head_sha }} + GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }} + GH_AW_RUN_DETECTION: ${{ needs.detection.outputs.run_detection }} + GH_AW_THREAT_DETECTION_AIC: ${{ needs.detection.outputs.aic }} + GH_AW_WORKFLOW_ID: "update-ci-dependencies" + GH_AW_WORKFLOW_NAME: "Update CI Dependencies" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/update-ci-dependencies.md" + outputs: + activation_comment_links: ${{ steps.process_safe_outputs.outputs.activation_comment_links }} + code_push_failure_count: ${{ steps.process_safe_outputs.outputs.code_push_failure_count }} + code_push_failure_errors: ${{ steps.process_safe_outputs.outputs.code_push_failure_errors }} + create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} + create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} + process_safe_outputs_items_applied: ${{ steps.process_safe_outputs.outputs.items_applied }} + process_safe_outputs_items_cancelled: ${{ steps.process_safe_outputs.outputs.items_cancelled }} + process_safe_outputs_items_deferred: ${{ steps.process_safe_outputs.outputs.items_deferred }} + process_safe_outputs_items_failed: ${{ steps.process_safe_outputs.outputs.items_failed }} + process_safe_outputs_items_skipped: ${{ steps.process_safe_outputs.outputs.items_skipped }} + process_safe_outputs_items_succeeded: ${{ steps.process_safe_outputs.outputs.items_succeeded }} + process_safe_outputs_items_warnings: ${{ steps.process_safe_outputs.outputs.items_warnings }} + process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }} + process_safe_outputs_status: ${{ steps.process_safe_outputs.outputs.status }} + push_commit_sha: ${{ steps.process_safe_outputs.outputs.push_commit_sha }} + push_commit_url: ${{ steps.process_safe_outputs.outputs.push_commit_url }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@221ba4f4319de6b8e809d1a15528b3ae6a818aa5 # v1.0.1 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "Update CI Dependencies" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/update-ci-dependencies.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.103" + GH_AW_INFO_AWF_VERSION: "v0.29.0" + GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_SETUP_AW_CONTEXT: ${{ inputs.aw_context }} + - name: App Token – Mint + id: repository-token + uses: microsoft/PR-Metrics/.github/actions/mint-github-app-token@5fe360db472f2604e1d2c0f5d33600d033db40ae + with: + azure-client-id: ${{ vars.AZURE_CLIENT_ID }} + azure-subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }} + azure-tenant-id: ${{ vars.AZURE_TENANT_ID }} + permissions: "{\"contents\":\"write\",\"pull_requests\":\"write\",\"workflows\":\"write\"}" + - name: Mask OTLP telemetry headers + run: bash "${RUNNER_TEMP}/gh-aw/actions/mask_otlp_headers.sh" + - name: Download agent output artifact + id: download-agent-output + continue-on-error: true + uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 + with: + pattern: "{agent,agent-output-fallback}" + merge-multiple: true + path: /tmp/gh-aw/ + - name: Setup agent output environment variable + id: setup-agent-output-env + if: steps.download-agent-output.outcome == 'success' + run: | + mkdir -p /tmp/gh-aw/ + find "/tmp/gh-aw/" -type f -print + if [ -f "/tmp/gh-aw/agent_output.json" ]; then + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" + fi + - name: Download patch artifact + continue-on-error: true + uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 + with: + name: agent + path: /tmp/gh-aw/ + - name: Checkout repository (gh-aw default) + if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch') + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: true + token: ${{ github.token }} + fetch-depth: 0 + - name: Fetch additional refs + if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch') + env: + GH_AW_FETCH_TOKEN: ${{ github.token }} + run: | + set -o pipefail + header=$(printf "x-access-token:%s" "${GH_AW_FETCH_TOKEN}" | base64 -w 0) + refspecs=('+refs/heads/*:refs/remotes/origin/*') + for refspec in "${refspecs[@]}"; do + source_ref=${refspec%%:*} + source_ref=${source_ref#+} + if matched=$(git -c "http.extraheader=Authorization: Basic ${header}" ls-remote --exit-code origin "$source_ref" | { + found=0 + while read -r _ remote_ref; do + # Match the configured ref glob, not a literal string. + # shellcheck disable=SC2254 + case "$remote_ref" in ($source_ref) found=1 ;; esac + done + printf '%s' "$found" + }); then + if [ "$matched" -eq 0 ]; then continue; fi + git -c "http.extraheader=Authorization: Basic ${header}" fetch origin "$refspec" + else + status=$? + if [ "$status" -ne 2 ]; then exit "$status"; fi + fi + done + - name: Configure Git credentials + if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch') + env: + GITHUB_REPOSITORY: ${{ github.repository }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GIT_TOKEN: ${{ steps.repository-token.outputs.token }} + run: bash "${RUNNER_TEMP}/gh-aw/actions/configure_git_credentials.sh" + - name: Configure GH_HOST for enterprise compatibility + id: ghes-host-config + shell: bash + run: | # zizmor: ignore[github-env] - GITHUB_SERVER_URL is set by GitHub Actions, not user input. + # Derive GH_HOST from GITHUB_SERVER_URL so the gh CLI targets the correct + # GitHub instance (GHES/GHEC). On github.com this is a harmless no-op. + GH_HOST="${GITHUB_SERVER_URL#https://}" + GH_HOST="${GH_HOST#http://}" + echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV" + - name: Process Safe Outputs + id: process_safe_outputs + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_JOB_CHECK_RUN_ID: ${{ job.check_run_id }} + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_COMMENT_ID: ${{ needs.activation.outputs.comment_id }} + GH_AW_MENTIONS_GITHUB_TOKEN: ${{ github.token }} + GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,docs.github.com,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,learn.microsoft.com,lfs.github.com,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,patch-diff.githubusercontent.com,patchdiff.githubusercontent.com,ppa.launchpad.net,raw.githubusercontent.com,s.symcb.com,s.symcd.com,security.ubuntu.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_report_incomplete_issue\":{},\"noop\":{\"max\":2,\"report-as-issue\":\"false\"},\"push_to_pull_request_branch\":{\"allowed_files\":[\".github/workflows/build.yml\",\".github/workflows/pr-automation.yml\",\".github/workflows/release-initiate.yml\",\".github/workflows/release-publish.yml\",\".github/workflows/actions.lock\",\".github/actions/mint-github-app-token/action.yml\",\".azure-devops/*.yml\",\"package.json\",\".nvmrc\"],\"github-token\":\"${{ steps.repository-token.outputs.token }}\",\"if_no_changes\":\"ignore\",\"max\":1,\"max_patch_size\":4096,\"protect_top_level_dot_folders\":true,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"CODEOWNERS\",\"DESIGN.md\",\"README.md\",\"CONTRIBUTING.md\",\"SECURITY.md\",\"CODE_OF_CONDUCT.md\",\"AGENTS.md\"],\"protected_files_policy\":\"allowed\",\"required_labels\":[\"release\"],\"target\":\"*\"},\"report_incomplete\":{},\"report_missing_data\":{},\"report_missing_tool\":{}}" + GH_AW_CI_TRIGGER_TOKEN: ${{ secrets.GH_AW_CI_TRIGGER_TOKEN }} + GITHUB_TOKEN: ${{ steps.repository-token.outputs.token }} + GH_AW_GITHUB_TOKEN_SOURCE: ${{ secrets.GH_AW_GITHUB_TOKEN != '' && 'pat' || 'github_actions' }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit, process.env.GH_AW_GITHUB_TOKEN_SOURCE); + const { main } = require(path.join(actionsDir, 'process_safe_outputs.cjs')); + await main(); + - name: Upload Safe Outputs Items + if: always() + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + with: + name: safe-outputs-items + path: | + /tmp/gh-aw/safe-output-items.jsonl + /tmp/gh-aw/safe-output-outcomes.jsonl + /tmp/gh-aw/temporary-id-map.json + /tmp/gh-aw/safe-output-errors.json + if-no-files-found: ignore + retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }} diff --git a/.github/workflows/update-ci-dependencies.md b/.github/workflows/update-ci-dependencies.md new file mode 100644 index 00000000..666a5cce --- /dev/null +++ b/.github/workflows/update-ci-dependencies.md @@ -0,0 +1,250 @@ +--- +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +name: Update CI Dependencies + +on: + workflow_run: + workflows: + - Release – Initiate + types: + - completed + branches: + - main + workflow_dispatch: null + +if: >- + github.ref == 'refs/heads/main' && + (github.event_name == 'workflow_dispatch' || + (github.event.workflow_run.conclusion == 'success' && + github.event.workflow_run.event == 'workflow_dispatch' && + github.event.workflow_run.head_repository.full_name == github.repository)) + +permissions: + actions: read + contents: read + copilot-requests: write + pull-requests: read + +concurrency: + group: update-ci-dependencies + cancel-in-progress: false + +engine: copilot + +network: + allowed: + - defaults + - github + - learn.microsoft.com + +tools: + edit: + bash: + - git * + - gh api * + - gh pr list * + - gh pr view * + - gh actions-lock + - gh actions-lock * + - jq * + - curl * + +checkout: + github-token: ${{ github.token }} + fetch: + - "*" + fetch-depth: 0 + +# PR preparation and publishing share a token reference, not a credential. +# The agent gets the native read token; only safe_outputs mints a write token. +pre-steps: + - name: Configure Read-Only Repository Token + id: repository-token + run: printf 'token=%s\n' "$GH_TOKEN" >> "$GITHUB_OUTPUT" + env: + GH_TOKEN: ${{ github.token }} + +steps: + - name: Install Workflow Lockfile Tool + run: gh extension install github/gh-actions-lock --pin v0.4.0 + env: + GH_TOKEN: ${{ github.token }} + +safe-outputs: + environment: production + push-to-pull-request-branch: + target: "*" + required-labels: + - release + max: 1 + if-no-changes: ignore + protected-files: allowed + allowed-files: + - .github/workflows/build.yml + - .github/workflows/pr-automation.yml + - .github/workflows/release-initiate.yml + - .github/workflows/release-publish.yml + - .github/workflows/actions.lock + - .github/actions/mint-github-app-token/action.yml + - .azure-devops/*.yml + - package.json + - .nvmrc + github-token: ${{ steps.repository-token.outputs.token }} + noop: + report-as-issue: false + +jobs: + safe_outputs: + permissions: + contents: read + id-token: write + pre-steps: + - name: App Token – Mint + id: repository-token + uses: microsoft/PR-Metrics/.github/actions/mint-github-app-token@5fe360db472f2604e1d2c0f5d33600d033db40ae + with: + azure-client-id: ${{ vars.AZURE_CLIENT_ID }} + azure-tenant-id: ${{ vars.AZURE_TENANT_ID }} + azure-subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }} + permissions: '{"contents":"write","pull_requests":"write","workflows":"write"}' +--- + +# Update CI Dependencies + +Refresh CI dependency pins on the existing release pull request after +`Release – Initiate` has finished its npm dependency updates. Do not create a +branch or a pull request. + +## Select the Release Pull Request + +Use the GitHub CLI to find open pull requests in `$GITHUB_REPOSITORY` that: + +- Target `main` and have the `release` label. +- Have their head branch in this repository, not a fork. +- Have a branch matching `release/vX.Y.Z`. +- Have `[Autogenerated] Release v` somewhere in the title. PR Metrics can + prepend size and coverage indicators, so do not require a title prefix. + +There must be exactly one matching pull request. If there are none or more than +one, make no changes and report the reason with the `noop` safe output. + +Fetch and check out the latest head of that release branch. Use repository +files as data; do not execute scripts, actions, or package lifecycle hooks from +the release branch. + +## Scope + +Edit only these files: + +- `.github/workflows/build.yml` +- `.github/workflows/pr-automation.yml` +- `.github/workflows/release-initiate.yml` +- `.github/workflows/release-publish.yml` +- `.github/workflows/actions.lock`, using its generator +- `.github/actions/mint-github-app-token/action.yml` +- `.azure-devops/*.yml` +- `package.json`, only to correct an inconsistent `engines.node` value +- `.nvmrc`, if present + +Do not edit this workflow, its generated `.lock.yml`, application code, npm +dependencies, `package-lock.json`, or `dist`. + +## GitHub Action Pins + +Inspect all actions in the permitted workflow and composite-action YAML files. +For each external action, resolve the latest stable release and its tag's commit +SHA. Update the 40-character SHA and the trailing `# vX.Y.Z` comment together. +Subpaths of one action repository, such as `github/codeql-action/init` and +`github/codeql-action/analyze`, must use the same release and SHA. + +```bash +gh api repos///releases/latest --jq '.tag_name' +gh api repos///git/refs/tags/ --jq '.object' +``` + +`releases/latest` can return a tag that is not an action version. For example, +CodeQL also publishes `codeql-bundle-*` releases. If necessary, list releases and +select the newest stable `vX.Y.Z` action release: + +```bash +gh api 'repos///releases?per_page=100' --paginate --jq '.[] | select(.draft == false and .prerelease == false) | .tag_name | select(test("^v[0-9]+\\.[0-9]+\\.[0-9]+$"))' +``` + +If a tag refers to an annotated tag object, dereference it through the Git tags +API until you reach a commit. Never use a tag-object SHA as an action pin. + +Preserve `$/` references to this repository's actions. Do not replace them with +`./` references or change the trusted signing action's implementation. Leave +deliberately moving 1ES template `release` references unchanged. + +Check open Dependabot pull requests before making an action update. If an open +pull request already covers that update, skip the duplicate and report it. Do +not merge or change another pull request. + +## Azure DevOps Task Versions + +In `.azure-devops/*.yml`, tasks use major versions such as `Npm@1`, `UseNode@1`, +and `EsrpCodeSigning@6`. For built-in tasks, check the `Tasks/` directories in +[`microsoft/azure-pipelines-tasks`][ado-tasks-repo] and the +[Azure Pipelines task reference][ado-tasks]. An `AzureCLIV3` directory confirms +that major version 3 exists. + +Review release notes and required inputs before changing a task major version. +Add newly required inputs and replace deprecated or renamed inputs. Use the +input names in the reference documentation's YAML syntax; do not replace a +supported name with an alias. For example, `AzureCLI@3` requires +`connectionType: azureRM` and still documents `azureSubscription`. + +Leave internal-extension tasks unchanged unless their release notes are +available. These include `EsrpCodeSigning`, `PoliCheck`, +`PublishSecurityAnalysisLogs`, `PostAnalysis`, and +`ComponentGovernanceComponentDetection`. Never update this product's own +`PRMetrics@N` task as part of this refresh. + +## Node.js Runtime Consistency + +Do not upgrade the Node.js runtime. Check that the existing intended pin agrees +across: + +- `actions/setup-node` inputs in the permitted workflows. +- `UseNode` inputs in `.azure-devops/*.yml`. +- `package.json`'s `engines.node`, preserving its comparison operator. +- `.nvmrc`, if present. + +If these values differ, use Git history to identify the most recent deliberate +runtime change and align only the divergent values. Updating the `UseNode` task +major does not authorize changing its Node.js version input. Do not change +compiler-managed runtimes in the generated agentic workflow. + +## Regenerate the Actions Lockfile + +After updating action references, regenerate the native GitHub Actions +dependency lockfile, including transitive dependencies: + +```bash +gh actions-lock --no-narrow --no-interactive +gh actions-lock --verify +``` + +Keep the generated `.github/workflows/actions.lock` in the same change as the +action updates. Do not edit it by hand. Do not regenerate the agentic workflow's +separate `update-ci-dependencies.lock.yml` during a dependency refresh. + +## Publish the Changes + +Preserve formatting, trailing newlines, and unrelated changes. Before +publishing, fetch the remote release branch again. Build automation can add +generated commits while you work. Integrate its latest head without discarding +those commits, and regenerate the Actions lockfile if the action inputs changed. +Never force-push. + +Use `push_to_pull_request_branch` to publish only the scoped changes to the +selected release pull request, with commit message `chore: refresh CI pins`. +Do not push directly or call write APIs. The trusted safe-output job signs and +publishes the commit with the repository's App token, so Build runs on the new +commit. If no updates are needed, report that through `noop`. + +[ado-tasks]: https://learn.microsoft.com/azure/devops/pipelines/tasks/reference/ +[ado-tasks-repo]: https://github.com/microsoft/azure-pipelines-tasks diff --git a/docs/dependency-management.md b/docs/dependency-management.md index 1d016958..ad9864ee 100644 --- a/docs/dependency-management.md +++ b/docs/dependency-management.md @@ -61,10 +61,13 @@ versions and `integrity` hashes recorded for each package (see - **[`package-lock.json`][packagelockjson]**: Records the exact resolved versions of all direct and transitive dependencies. This file is committed to version control to ensure deterministic builds. +- **[`.github/workflows/actions.lock`][actionslock]**: Locks GitHub Actions and + their transitive action dependencies. Build verifies this native workflow + dependency lockfile with `gh actions-lock --verify`. ## Updating -Dependencies are updated through two distinct processes: +Dependencies are updated through these processes: - **GitHub Actions dependencies**: Scheduled [Dependabot][dependabot] version updates are configured only for this ecosystem: Dependabot monitors GitHub @@ -84,6 +87,81 @@ Dependencies are updated through two distinct processes: [Dependabot security updates][dependabotsecurityupdates] continue to cover npm vulnerabilities and may open npm pull requests to remediate them. +### CI Dependency Refresh + +The [Update CI Dependencies agentic workflow][updatecidependencies] runs after a +successful `Release – Initiate` run on `main`, after the npm dependency commits +are complete. It updates action pins and supported Azure DevOps task major +versions on the existing release pull request. It also checks Node.js runtime +consistency without upgrading the runtime. Its file allowlist includes the +current PR automation workflow and `.azure-devops` pipelines. + +The workflow requires exactly one open, same-repository release pull request +targeting `main`. PR title indicators do not affect selection. If no unique +release pull request exists, the workflow reports the reason without making +changes. To retry it, run the workflow from `main`: + +```bash +gh workflow run update-ci-dependencies.lock.yml --ref main +``` + +Copilot inference uses the built-in `GITHUB_TOKEN` with +`copilot-requests: write`, so usage is billed to the organization rather than a +personal token. An organization administrator must enable **Copilot CLI** and +**Allow use of Copilot CLI billed to the organization** in Copilot policy +settings. Enterprise policies must also permit this use. See +[Copilot CLI organization billing][copilotbilling]. A personal +`COPILOT_GITHUB_TOKEN` is not required. + +The agent has read-only repository access and no production signing access. +Only the trusted safe-output job uses the `production` environment and the +existing Azure OIDC/Key Vault signing action. The `microsoft-pr-metrics` App and +its repository installation must grant `contents: write`, +`pull_requests: write`, and **`workflows: write`**. The workflow explicitly +requests these installation-token permissions. An App owner must add and an +installation owner must accept the workflow permission before the first run; +the existing contents permission alone cannot update workflow files. No App +private key is stored in GitHub. + +The compiler currently requires a versioned action reference rather than the +native `$/` syntax. The AI workflow therefore pins the trusted signing action +to a repository commit. Update that reference and recompile if the shared +signing implementation changes. The other workflows use `$/` to select the +action from their own workflow revision. + +### Workflow Lockfiles + +The native [Actions workflow dependency lockfile][workflowlockfiles], +`.github/workflows/actions.lock`, is distinct from the generated agentic +workflow, `update-ci-dependencies.lock.yml`. Both are committed. The latter is +compiled from `update-ci-dependencies.md`; do not edit either generated file by +hand. + +Install the pinned generators once: + +```bash +gh extension install github/gh-aw --pin v1.0.1 +gh extension install github/gh-actions-lock --pin v0.4.0 +``` + +After changing the agentic workflow source, compile it first. After changing +any action references, regenerate the native dependency lockfile: + +```bash +gh aw compile update-ci-dependencies +gh actions-lock --no-narrow --no-interactive +gh actions-lock --verify +``` + +Review any new actions or secrets before approving compiler manifest changes +with `gh aw compile update-ci-dependencies --approve`. Keep action changes and +their lockfile updates in the same commit. Dependabot also updates matching +lockfile entries when it updates an action in a locked workflow. + +Build recompiles the agentic workflow and rejects stale generated output. +Super-Linter excludes the generated `.lock.yml`; the compiler validates its +schema and action pins instead. + ## Security Scanning - [CodeQL][codeql] analyzes the codebase, including dependency usage, for @@ -96,9 +174,11 @@ Dependencies are updated through two distinct processes: - [Gitleaks][gitleaks] scans for accidentally committed secrets via [Super-Linter][superlinter]. +[actionslock]: https://github.com/microsoft/PR-Metrics/blob/main/.github/workflows/actions.lock [azuredevopstemplate]: https://github.com/microsoft/PR-Metrics/blob/main/.azure-devops/template.yml [azurepipelinestasksdk]: https://github.com/microsoft/azure-pipelines-task-lib [codeql]: https://codeql.github.com/ +[copilotbilling]: https://docs.github.com/copilot/how-tos/copilot-cli/use-copilot-cli-in-actions [dependabot]: https://github.com/microsoft/PR-Metrics/blob/main/.github/dependabot.yml [dependabotalerts]: https://docs.github.com/code-security/dependabot/dependabot-alerts/about-dependabot-alerts [dependabotsecurityupdates]: https://docs.github.com/code-security/dependabot/dependabot-security-updates/about-dependabot-security-updates @@ -115,3 +195,5 @@ Dependencies are updated through two distinct processes: [srctasknpmrc]: https://github.com/microsoft/PR-Metrics/blob/main/src/task/.npmrc [superlinter]: https://github.com/super-linter/super-linter [typescript]: https://www.typescriptlang.org/ +[updatecidependencies]: https://github.com/microsoft/PR-Metrics/blob/main/.github/workflows/update-ci-dependencies.md +[workflowlockfiles]: https://docs.github.com/actions/concepts/security/workflow-dependency-lockfiles From 91eb9ca04a44d29a95ed0909bc30815df20ca897 Mon Sep 17 00:00:00 2001 From: Muiris Woulfe Date: Thu, 29 Oct 2026 15:01:44 +0000 Subject: [PATCH 2/8] fix(ci): restrict billing probe to no tools Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: bbc1bf98-847f-4a02-9212-a22eaab288a5 --- .github/workflows/test-copilot-org-billing.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-copilot-org-billing.yml b/.github/workflows/test-copilot-org-billing.yml index cdf0a2ec..d36274b7 100644 --- a/.github/workflows/test-copilot-org-billing.yml +++ b/.github/workflows/test-copilot-org-billing.yml @@ -48,7 +48,7 @@ jobs: --no-custom-instructions \ --no-ask-user \ --disable-builtin-mcps \ - --deny-tool '*' \ + --available-tools \ --trust-folder \ | tee copilot-org-billing-response.txt From 22dc445430064c36b11edbe0de82bacd452d581b Mon Sep 17 00:00:00 2001 From: Muiris Woulfe Date: Thu, 29 Oct 2026 15:10:06 +0000 Subject: [PATCH 3/8] test(ci): match production Copilot version Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: bbc1bf98-847f-4a02-9212-a22eaab288a5 --- .github/workflows/test-copilot-org-billing.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-copilot-org-billing.yml b/.github/workflows/test-copilot-org-billing.yml index d36274b7..12cfe32c 100644 --- a/.github/workflows/test-copilot-org-billing.yml +++ b/.github/workflows/test-copilot-org-billing.yml @@ -29,7 +29,7 @@ jobs: node-version: 24.18.1 - name: Install Copilot CLI - run: npm install --global --no-audit --no-fund @github/copilot@1.0.105 + run: npm install --global --no-audit --no-fund @github/copilot@1.0.103 - name: Test Native Organization Billing id: inference From 13c61e527dd93a6e555e3e28b86e7d5352810a6f Mon Sep 17 00:00:00 2001 From: Muiris Woulfe Date: Thu, 29 Oct 2026 15:20:42 +0000 Subject: [PATCH 4/8] ci: remove temporary organization billing probe Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: bbc1bf98-847f-4a02-9212-a22eaab288a5 --- .gitattributes | 2 +- .github/workflows/actions.lock | 2 - .../workflows/test-copilot-org-billing.yml | 65 ------------------- docs/dependency-management.md | 10 +-- 4 files changed, 6 insertions(+), 73 deletions(-) delete mode 100644 .github/workflows/test-copilot-org-billing.yml diff --git a/.gitattributes b/.gitattributes index 1f7549b5..965a9c32 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1 @@ -.github/workflows/*.lock.yml linguist-generated=true \ No newline at end of file +.github/workflows/*.lock.yml linguist-generated=true diff --git a/.github/workflows/actions.lock b/.github/workflows/actions.lock index f7ae5425..b0463fab 100644 --- a/.github/workflows/actions.lock +++ b/.github/workflows/actions.lock @@ -26,8 +26,6 @@ workflows: - 'actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9' - 'azure/login@a641126d1b8aa4d1fa005f4f92df94a3a4c4c906' - 'sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6' - '.github/workflows/test-copilot-org-billing.yml': - - 'actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1' '.github/workflows/update-ci-dependencies.lock.yml': - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' - 'actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333' diff --git a/.github/workflows/test-copilot-org-billing.yml b/.github/workflows/test-copilot-org-billing.yml deleted file mode 100644 index 12cfe32c..00000000 --- a/.github/workflows/test-copilot-org-billing.yml +++ /dev/null @@ -1,65 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - ---- -name: Copilot Org Billing Test - -on: - push: - branches: - - test/copilot-org-billing - paths: - - .github/workflows/test-copilot-org-billing.yml - -permissions: {} - -jobs: - billing: - if: github.repository == 'microsoft/PR-Metrics' && github.ref == 'refs/heads/test/copilot-org-billing' - name: Test Organization-Billed Inference - runs-on: ubuntu-latest - timeout-minutes: 5 - permissions: - contents: read - copilot-requests: write - steps: - - name: Install Node.js - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 - with: - node-version: 24.18.1 - - - name: Install Copilot CLI - run: npm install --global --no-audit --no-fund @github/copilot@1.0.103 - - - name: Test Native Organization Billing - id: inference - shell: bash - working-directory: ${{ runner.temp }} - env: - COPILOT_GITHUB_TOKEN: ${{ github.token }} - run: | - set -euo pipefail - copilot \ - --prompt 'Do not use tools. Reply with exactly ORG_BILLING_OK and nothing else.' \ - --model auto \ - --silent \ - --no-color \ - --no-auto-update \ - --no-custom-instructions \ - --no-ask-user \ - --disable-builtin-mcps \ - --available-tools \ - --trust-folder \ - | tee copilot-org-billing-response.txt - - if [[ "$(cat copilot-org-billing-response.txt)" != 'ORG_BILLING_OK' ]]; then - echo '::error::Copilot did not return the expected billing test response.' - exit 1 - fi - - printf '%s\n' \ - '## Organization billing test passed' \ - 'Copilot returned the expected response using the native workflow GITHUB_TOKEN.' \ - 'No personal token, production credentials, or repository writes were used.' \ - 'This confirms inference access, not release pull request publishing.' \ - >> "$GITHUB_STEP_SUMMARY" diff --git a/docs/dependency-management.md b/docs/dependency-management.md index ad9864ee..2e5ee72b 100644 --- a/docs/dependency-management.md +++ b/docs/dependency-management.md @@ -114,14 +114,14 @@ settings. Enterprise policies must also permit this use. See `COPILOT_GITHUB_TOKEN` is not required. The agent has read-only repository access and no production signing access. -Only the trusted safe-output job uses the `production` environment and the +The trusted safe-output job uses the `production` environment and the existing Azure OIDC/Key Vault signing action. The `microsoft-pr-metrics` App and its repository installation must grant `contents: write`, `pull_requests: write`, and **`workflows: write`**. The workflow explicitly -requests these installation-token permissions. An App owner must add and an -installation owner must accept the workflow permission before the first run; -the existing contents permission alone cannot update workflow files. No App -private key is stored in GitHub. +requests these installation-token permissions. If an App permission changes, an +installation owner must accept the change before the first run. The existing +contents permission alone cannot update workflow files. No App private key is +stored in GitHub. The compiler currently requires a versioned action reference rather than the native `$/` syntax. The AI workflow therefore pins the trusted signing action From 01a7dcc4f810b7c14d0e99f4c750b72935602de0 Mon Sep 17 00:00:00 2001 From: Muiris Woulfe Date: Thu, 29 Oct 2026 15:58:03 +0000 Subject: [PATCH 5/8] fix(dependabot): exclude generated workflows Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: bbc1bf98-847f-4a02-9212-a22eaab288a5 --- .github/dependabot.yml | 2 ++ docs/dependency-management.md | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index a21f98af..ac2285b6 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -9,6 +9,8 @@ updates: directories: - / - /.github/actions/mint-github-app-token + exclude-paths: + - .github/workflows/*.lock.yml open-pull-requests-limit: 100 groups: codeql-action: diff --git a/docs/dependency-management.md b/docs/dependency-management.md index 2e5ee72b..5a7921e5 100644 --- a/docs/dependency-management.md +++ b/docs/dependency-management.md @@ -158,6 +158,11 @@ with `gh aw compile update-ci-dependencies --approve`. Keep action changes and their lockfile updates in the same commit. Dependabot also updates matching lockfile entries when it updates an action in a locked workflow. +Dependabot excludes generated `.github/workflows/*.lock.yml` files. To +refresh compiler-managed action pins, add `--force-refresh-action-pins` to the +compile command above. Commit any `.github/aw/actions-lock.json` changes with +the regenerated files. + Build recompiles the agentic workflow and rejects stale generated output. Super-Linter excludes the generated `.lock.yml`; the compiler validates its schema and action pins instead. From 416d7cab8760340de2ae8d5292b01ebe2cabd925 Mon Sep 17 00:00:00 2001 From: Muiris Woulfe Date: Thu, 29 Oct 2026 16:52:56 +0000 Subject: [PATCH 6/8] docs(dependency-management): update dependency management details - Added clarification on the verification of the actions lockfile. - Expanded on the Copilot CLI and agentic compiler updates. - Improved readability and structure of the document. --- .gitattributes | 6 + .../workflows/update-ci-dependencies.lock.yml | 26 +++-- .github/workflows/update-ci-dependencies.md | 109 ++++++++++++++---- docs/dependency-management.md | 47 ++++---- 4 files changed, 131 insertions(+), 57 deletions(-) diff --git a/.gitattributes b/.gitattributes index 965a9c32..464baad0 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,7 @@ +.github/aw/actions-lock.json linguist-generated=true .github/workflows/*.lock.yml linguist-generated=true +.github/workflows/actions.lock linguist-generated=true +dist/exec-child.js linguist-generated=true +dist/index.mjs linguist-generated=true +dist/lib.json linguist-generated=true +dist/resources.resjson linguist-generated=true diff --git a/.github/workflows/update-ci-dependencies.lock.yml b/.github/workflows/update-ci-dependencies.lock.yml index 4c73b270..810960b6 100644 --- a/.github/workflows/update-ci-dependencies.lock.yml +++ b/.github/workflows/update-ci-dependencies.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"83672948284a233c2dffb4bb365b3a3c22ca8b810f65ae545b27e3a851c82b14","body_hash":"480d779c1cfc2184da0b4930412fbc089a2bc8e68f52222db17a301700dbc09c","compiler_version":"v1.0.1","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.103"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"f5ed0e759e1664614fec775c9e6b331b223d6db250b4f0836f274a1687979e37","body_hash":"241b6032ce54d9b34cb137ae46f1097fe63a466712daea0c4aab2521c23979d2","compiler_version":"v1.0.1","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.103"}} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_CI_TRIGGER_TOKEN","GH_AW_DEFAULT_OTLP_ENDPOINT","GH_AW_DEFAULT_OTLP_HEADERS","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/download-artifact","sha":"9000827ccba6bdab643e8b6fd33ac0654aef8333","version":"v8.0.2"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"949feb2413d6458794dcd2491c4babbbce0c15c1","version":"v7.1.0"},{"repo":"actions/upload-artifact","sha":"cf430e030ddbb5b0abf93d22962f4752f3646cd9","version":"v7.0.2"},{"repo":"github/gh-aw-actions/setup","sha":"221ba4f4319de6b8e809d1a15528b3ae6a818aa5","version":"v1.0.1"},{"repo":"microsoft/PR-Metrics/.github/actions/mint-github-app-token","sha":"5fe360db472f2604e1d2c0f5d33600d033db40ae","version":"5fe360db472f2604e1d2c0f5d33600d033db40ae"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.29.0","digest":"sha256:b14bd399376180b5649a9324be3b50fbfc82bfe8f0c80045840416b5a4e65b96","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.29.0@sha256:b14bd399376180b5649a9324be3b50fbfc82bfe8f0c80045840416b5a4e65b96"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.29.0","digest":"sha256:baff00b856a4bdc93bce134928c70af3d3492f2e518757115042040674d56b0b","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.29.0@sha256:baff00b856a4bdc93bce134928c70af3d3492f2e518757115042040674d56b0b"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.29.0","digest":"sha256:6e0cbf7f980beb78b5461563a8164f6439ca959bc93733d5a6b52972e523ed50","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.29.0@sha256:6e0cbf7f980beb78b5461563a8164f6439ca959bc93733d5a6b52972e523ed50"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.5.0","digest":"sha256:d3544a4222e7efeeeb38669d8a1af0c72691c55b8f6506b15aa5920f7f31b7bc","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.5.0@sha256:d3544a4222e7efeeeb38669d8a1af0c72691c55b8f6506b15aa5920f7f31b7bc"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:2c2ea524e648b91c8333ce246e3838fcf5b19ac70e45baac1a51b9207299749f","pinned_image":"ghcr.io/github/gh-aw-node@sha256:2c2ea524e648b91c8333ce246e3838fcf5b19ac70e45baac1a51b9207299749f"},{"image":"ghcr.io/github/github-mcp-server:v2.0.3","digest":"sha256:250bc6ce70788207608ef74cef4397230ff2e8481218da74d6093e4bd9101132","pinned_image":"ghcr.io/github/github-mcp-server:v2.0.3@sha256:250bc6ce70788207608ef74cef4397230ff2e8481218da74d6093e4bd9101132"}],"mcp_servers":[{"name":"github","tools":["get_commit","get_file_contents","get_latest_release","get_me","get_pull_request","get_pull_request_comments","get_pull_request_diff","get_pull_request_files","get_pull_request_review_comments","get_pull_request_reviews","get_pull_request_status","get_release_by_tag","get_tag","issue_read","list_branches","list_commits","list_issue_types","list_issues","list_pull_requests","list_releases","list_starred_repositories","list_tags","pull_request_read","search_code","search_issues","search_pull_requests","search_repositories"]},{"name":"safeoutputs","tools":["noop","push_to_pull_request_branch","report_incomplete","report_missing_data","report_missing_tool"]}],"threat_detection":{"mode":"enabled"},"admission":false} # This file was automatically generated by gh-aw (v1.0.1). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # @@ -440,6 +440,7 @@ jobs: GH_AW_ASSETS_ALLOWED_EXTS: "" GH_AW_ASSETS_BRANCH: "" GH_AW_ASSETS_MAX_SIZE_KB: 0 + GH_AW_ENGINE_VERSION: "1.0.103" GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs GH_AW_PR_HEAD_BASE_BRANCH: "" GH_AW_PR_HEAD_BASE_PR_NUMBER: "" @@ -565,8 +566,10 @@ jobs: path: /tmp/gh-aw - env: GH_TOKEN: ${{ github.token }} - name: Install Workflow Lockfile Tool - run: gh extension install github/gh-actions-lock --pin v0.4.0 + name: Install Workflow Maintenance Tools + run: |- + gh extension install github/gh-aw --pin v1.0.1 + gh extension install github/gh-actions-lock --pin v0.4.0 - name: Configure Git credentials env: @@ -591,7 +594,7 @@ jobs: const { main } = require(path.join(actionsDir, 'checkout_pr_branch.cjs')); await main(); - name: Install GitHub Copilot CLI - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.103 --checksums-sha256 26cd3e4b32cde498e4961fb4d48e7b85d7859fc69af1a645a19201fdd577bdb2 --prefer-toolcache + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.103 --checksums-sha256 26cd3e4b32cde498e4961fb4d48e7b85d7859fc69af1a645a19201fdd577bdb2 env: GH_HOST: github.com GH_AW_COPILOT_MIN_VERSION: 1.0.35 @@ -636,7 +639,7 @@ jobs: env: GH_AW_FILE_ROOT: "${{ runner.temp }}/gh-aw" GH_AW_FILE_CONFIG: "{\"files\":[{\"path\":\"safeoutputs/config.json\",\"content_env\":\"GH_AW_SAFE_OUTPUTS_CONFIG\"}]}" - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_report_incomplete_issue\":{},\"noop\":{\"max\":2,\"report-as-issue\":\"false\"},\"push_to_pull_request_branch\":{\"allowed_files\":[\".github/workflows/build.yml\",\".github/workflows/pr-automation.yml\",\".github/workflows/release-initiate.yml\",\".github/workflows/release-publish.yml\",\".github/workflows/actions.lock\",\".github/actions/mint-github-app-token/action.yml\",\".azure-devops/*.yml\",\"package.json\",\".nvmrc\"],\"github-token\":\"${{ steps.repository-token.outputs.token }}\",\"if_no_changes\":\"ignore\",\"max\":1,\"max_patch_size\":4096,\"protect_top_level_dot_folders\":true,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"CODEOWNERS\",\"DESIGN.md\",\"README.md\",\"CONTRIBUTING.md\",\"SECURITY.md\",\"CODE_OF_CONDUCT.md\",\"AGENTS.md\"],\"protected_files_policy\":\"allowed\",\"required_labels\":[\"release\"],\"target\":\"*\"},\"report_incomplete\":{},\"report_missing_data\":{},\"report_missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_report_incomplete_issue\":{},\"noop\":{\"max\":2,\"report-as-issue\":\"false\"},\"push_to_pull_request_branch\":{\"allowed_files\":[\".github/workflows/build.yml\",\".github/workflows/pr-automation.yml\",\".github/workflows/release-initiate.yml\",\".github/workflows/release-publish.yml\",\".github/workflows/update-ci-dependencies.md\",\".github/workflows/update-ci-dependencies.lock.yml\",\".github/workflows/actions.lock\",\".github/aw/actions-lock.json\",\".github/actions/mint-github-app-token/action.yml\",\".azure-devops/*.yml\",\"package.json\",\".nvmrc\",\"docs/dependency-management.md\"],\"github-token\":\"${{ steps.repository-token.outputs.token }}\",\"if_no_changes\":\"ignore\",\"max\":1,\"max_patch_size\":4096,\"protect_top_level_dot_folders\":true,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"CODEOWNERS\",\"DESIGN.md\",\"README.md\",\"CONTRIBUTING.md\",\"SECURITY.md\",\"CODE_OF_CONDUCT.md\",\"AGENTS.md\"],\"protected_files_policy\":\"allowed\",\"required_labels\":[\"release\"],\"target\":\"*\"},\"report_incomplete\":{},\"report_missing_data\":{},\"report_missing_tool\":{}}" with: script: | const path = require('path'); @@ -935,6 +938,9 @@ jobs: # --allow-tool shell(echo) # --allow-tool shell(gh actions-lock) # --allow-tool shell(gh api) + # --allow-tool shell(gh aw compile update-ci-dependencies) + # --allow-tool shell(gh extension install github/gh-actions-lock) + # --allow-tool shell(gh extension install github/gh-aw) # --allow-tool shell(gh pr list) # --allow-tool shell(gh pr view) # --allow-tool shell(git add:*) @@ -1037,7 +1043,7 @@ jobs: GH_AW_AWF_ATTEMPT_LOG_NAME=copilot \ bash "${RUNNER_TEMP}/gh-aw/actions/run_awf_with_startup_retries.sh" -- \ 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" ${GH_AW_ENGINE_STEP_TIMEOUT_MINUTES:+--agent-timeout "$GH_AW_ENGINE_STEP_TIMEOUT_MINUTES"} ${GH_AW_TOOL_CACHE_MOUNT:+--mount "$GH_AW_TOOL_CACHE_MOUNT"} ${GH_AW_DOCKER_HOST:+--docker-host "$GH_AW_DOCKER_HOST"} --env-all --exclude-env ACTIONS_ID_TOKEN_REQUEST_TOKEN --exclude-env ACTIONS_ID_TOKEN_REQUEST_URL --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GH_AW_OTLP_ALL_HEADERS --exclude-env GH_AW_OTLP_ENDPOINTS --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_AGENT_ID --exclude-env OTEL_EXPORTER_OTLP_ENDPOINT --exclude-env OTEL_EXPORTER_OTLP_HEADERS --mount /tmp/gh-aw:/tmp/gh-aw:rw --log-level info --session-state-dir /tmp/gh-aw/sandbox/agent/session-state --skip-pull \ - -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && : "${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"; GH_AW_TOOL_CACHE="$RUNNER_TOOL_CACHE"; GH_AW_TOOL_BINS="$(find "$GH_AW_TOOL_CACHE" -maxdepth 5 -type d -name bin 2>/dev/null | tr "\n" ":")"; GH_AW_TOOL_BINS="${GH_AW_TOOL_BINS%:}"; export PATH="$PATH${GH_AW_TOOL_BINS:+:}$GH_AW_TOOL_BINS"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true; [ -n "$ERLANG_HOME" ] && export PATH="$ERLANG_HOME/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 || true)"; fi; if [ -z "$GH_AW_NODE_EXEC" ]; then echo "node runtime missing on this runner — check runtimes.node in workflow YAML" >&2; exit 127; fi; GH_AW_NPM_GLOBAL_ROOT="$(npm root -g 2>/dev/null || true)"; if [ -n "$GH_AW_NPM_GLOBAL_ROOT" ]; then export NODE_PATH="${GH_AW_NPM_GLOBAL_ROOT}${NODE_PATH:+:${NODE_PATH}}"; fi; "$GH_AW_NODE_EXEC" "${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs" "${RUNNER_TEMP}/gh-aw/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)'\'' --allow-tool '\''shell(curl:*)'\'' --allow-tool '\''shell(date)'\'' --allow-tool '\''shell(echo)'\'' --allow-tool '\''shell(gh actions-lock)'\'' --allow-tool '\''shell(gh api)'\'' --allow-tool '\''shell(gh pr list)'\'' --allow-tool '\''shell(gh pr view)'\'' --allow-tool '\''shell(git add:*)'\'' --allow-tool '\''shell(git branch:*)'\'' --allow-tool '\''shell(git checkout:*)'\'' --allow-tool '\''shell(git commit:*)'\'' --allow-tool '\''shell(git merge:*)'\'' --allow-tool '\''shell(git rm:*)'\'' --allow-tool '\''shell(git status)'\'' --allow-tool '\''shell(git switch:*)'\'' --allow-tool '\''shell(git:*)'\'' --allow-tool '\''shell(github:*)'\'' --allow-tool '\''shell(grep)'\'' --allow-tool '\''shell(head)'\'' --allow-tool '\''shell(jq)'\'' --allow-tool '\''shell(ls)'\'' --allow-tool '\''shell(printf)'\'' --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 write --deny-tool workflow --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' + -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && : "${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"; GH_AW_TOOL_CACHE="$RUNNER_TOOL_CACHE"; GH_AW_TOOL_BINS="$(find "$GH_AW_TOOL_CACHE" -maxdepth 5 -type d -name bin 2>/dev/null | tr "\n" ":")"; GH_AW_TOOL_BINS="${GH_AW_TOOL_BINS%:}"; export PATH="$PATH${GH_AW_TOOL_BINS:+:}$GH_AW_TOOL_BINS"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true; [ -n "$ERLANG_HOME" ] && export PATH="$ERLANG_HOME/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 || true)"; fi; if [ -z "$GH_AW_NODE_EXEC" ]; then echo "node runtime missing on this runner — check runtimes.node in workflow YAML" >&2; exit 127; fi; GH_AW_NPM_GLOBAL_ROOT="$(npm root -g 2>/dev/null || true)"; if [ -n "$GH_AW_NPM_GLOBAL_ROOT" ]; then export NODE_PATH="${GH_AW_NPM_GLOBAL_ROOT}${NODE_PATH:+:${NODE_PATH}}"; fi; "$GH_AW_NODE_EXEC" "${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs" "${RUNNER_TEMP}/gh-aw/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)'\'' --allow-tool '\''shell(curl:*)'\'' --allow-tool '\''shell(date)'\'' --allow-tool '\''shell(echo)'\'' --allow-tool '\''shell(gh actions-lock)'\'' --allow-tool '\''shell(gh api)'\'' --allow-tool '\''shell(gh aw compile update-ci-dependencies)'\'' --allow-tool '\''shell(gh extension install github/gh-actions-lock)'\'' --allow-tool '\''shell(gh extension install github/gh-aw)'\'' --allow-tool '\''shell(gh pr list)'\'' --allow-tool '\''shell(gh pr view)'\'' --allow-tool '\''shell(git add:*)'\'' --allow-tool '\''shell(git branch:*)'\'' --allow-tool '\''shell(git checkout:*)'\'' --allow-tool '\''shell(git commit:*)'\'' --allow-tool '\''shell(git merge:*)'\'' --allow-tool '\''shell(git rm:*)'\'' --allow-tool '\''shell(git status)'\'' --allow-tool '\''shell(git switch:*)'\'' --allow-tool '\''shell(git:*)'\'' --allow-tool '\''shell(github:*)'\'' --allow-tool '\''shell(grep)'\'' --allow-tool '\''shell(head)'\'' --allow-tool '\''shell(jq)'\'' --allow-tool '\''shell(ls)'\'' --allow-tool '\''shell(printf)'\'' --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 write --deny-tool workflow --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' env: AWF_REFLECT_ENABLED: 1 COPILOT_AGENT_RUNNER_TYPE: STANDALONE @@ -1404,6 +1410,7 @@ jobs: GH_AW_WORKFLOW_NAME: "Update CI Dependencies" GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/update-ci-dependencies.md" GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_VERSION: "1.0.103" GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }} GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} @@ -1449,6 +1456,7 @@ jobs: GH_AW_WORKFLOW_NAME: "Update CI Dependencies" GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/update-ci-dependencies.md" GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_VERSION: "1.0.103" GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }} with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} @@ -1468,6 +1476,7 @@ jobs: GH_AW_WORKFLOW_NAME: "Update CI Dependencies" GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/update-ci-dependencies.md" GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_VERSION: "1.0.103" GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }} with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} @@ -1795,7 +1804,7 @@ jobs: 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.103 --checksums-sha256 26cd3e4b32cde498e4961fb4d48e7b85d7859fc69af1a645a19201fdd577bdb2 --prefer-toolcache + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.103 --checksums-sha256 26cd3e4b32cde498e4961fb4d48e7b85d7859fc69af1a645a19201fdd577bdb2 env: GH_HOST: github.com GH_AW_COPILOT_MIN_VERSION: 1.0.35 @@ -2079,6 +2088,7 @@ jobs: GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }} GH_AW_ENGINE_ID: "copilot" GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }} + GH_AW_ENGINE_VERSION: "1.0.103" GH_AW_HEAD_SHA: ${{ github.event.workflow_run.head_sha }} GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }} GH_AW_RUN_DETECTION: ${{ needs.detection.outputs.run_detection }} @@ -2213,7 +2223,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,docs.github.com,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,learn.microsoft.com,lfs.github.com,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,patch-diff.githubusercontent.com,patchdiff.githubusercontent.com,ppa.launchpad.net,raw.githubusercontent.com,s.symcb.com,s.symcd.com,security.ubuntu.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_report_incomplete_issue\":{},\"noop\":{\"max\":2,\"report-as-issue\":\"false\"},\"push_to_pull_request_branch\":{\"allowed_files\":[\".github/workflows/build.yml\",\".github/workflows/pr-automation.yml\",\".github/workflows/release-initiate.yml\",\".github/workflows/release-publish.yml\",\".github/workflows/actions.lock\",\".github/actions/mint-github-app-token/action.yml\",\".azure-devops/*.yml\",\"package.json\",\".nvmrc\"],\"github-token\":\"${{ steps.repository-token.outputs.token }}\",\"if_no_changes\":\"ignore\",\"max\":1,\"max_patch_size\":4096,\"protect_top_level_dot_folders\":true,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"CODEOWNERS\",\"DESIGN.md\",\"README.md\",\"CONTRIBUTING.md\",\"SECURITY.md\",\"CODE_OF_CONDUCT.md\",\"AGENTS.md\"],\"protected_files_policy\":\"allowed\",\"required_labels\":[\"release\"],\"target\":\"*\"},\"report_incomplete\":{},\"report_missing_data\":{},\"report_missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_report_incomplete_issue\":{},\"noop\":{\"max\":2,\"report-as-issue\":\"false\"},\"push_to_pull_request_branch\":{\"allowed_files\":[\".github/workflows/build.yml\",\".github/workflows/pr-automation.yml\",\".github/workflows/release-initiate.yml\",\".github/workflows/release-publish.yml\",\".github/workflows/update-ci-dependencies.md\",\".github/workflows/update-ci-dependencies.lock.yml\",\".github/workflows/actions.lock\",\".github/aw/actions-lock.json\",\".github/actions/mint-github-app-token/action.yml\",\".azure-devops/*.yml\",\"package.json\",\".nvmrc\",\"docs/dependency-management.md\"],\"github-token\":\"${{ steps.repository-token.outputs.token }}\",\"if_no_changes\":\"ignore\",\"max\":1,\"max_patch_size\":4096,\"protect_top_level_dot_folders\":true,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"CODEOWNERS\",\"DESIGN.md\",\"README.md\",\"CONTRIBUTING.md\",\"SECURITY.md\",\"CODE_OF_CONDUCT.md\",\"AGENTS.md\"],\"protected_files_policy\":\"allowed\",\"required_labels\":[\"release\"],\"target\":\"*\"},\"report_incomplete\":{},\"report_missing_data\":{},\"report_missing_tool\":{}}" GH_AW_CI_TRIGGER_TOKEN: ${{ secrets.GH_AW_CI_TRIGGER_TOKEN }} GITHUB_TOKEN: ${{ steps.repository-token.outputs.token }} GH_AW_GITHUB_TOKEN_SOURCE: ${{ secrets.GH_AW_GITHUB_TOKEN != '' && 'pat' || 'github_actions' }} diff --git a/.github/workflows/update-ci-dependencies.md b/.github/workflows/update-ci-dependencies.md index 666a5cce..96fc41ba 100644 --- a/.github/workflows/update-ci-dependencies.md +++ b/.github/workflows/update-ci-dependencies.md @@ -31,7 +31,10 @@ concurrency: group: update-ci-dependencies cancel-in-progress: false -engine: copilot +engine: + id: copilot + version: "1.0.103" + checksums-sha256: 26cd3e4b32cde498e4961fb4d48e7b85d7859fc69af1a645a19201fdd577bdb2 network: allowed: @@ -46,6 +49,9 @@ tools: - gh api * - gh pr list * - gh pr view * + - gh aw compile update-ci-dependencies * + - gh extension install github/gh-aw * + - gh extension install github/gh-actions-lock * - gh actions-lock - gh actions-lock * - jq * @@ -67,8 +73,10 @@ pre-steps: GH_TOKEN: ${{ github.token }} steps: - - name: Install Workflow Lockfile Tool - run: gh extension install github/gh-actions-lock --pin v0.4.0 + - name: Install Workflow Maintenance Tools + run: | + gh extension install github/gh-aw --pin v1.0.1 + gh extension install github/gh-actions-lock --pin v0.4.0 env: GH_TOKEN: ${{ github.token }} @@ -86,11 +94,15 @@ safe-outputs: - .github/workflows/pr-automation.yml - .github/workflows/release-initiate.yml - .github/workflows/release-publish.yml + - .github/workflows/update-ci-dependencies.md + - .github/workflows/update-ci-dependencies.lock.yml - .github/workflows/actions.lock + - .github/aw/actions-lock.json - .github/actions/mint-github-app-token/action.yml - .azure-devops/*.yml - package.json - .nvmrc + - docs/dependency-management.md github-token: ${{ steps.repository-token.outputs.token }} noop: report-as-issue: false @@ -130,9 +142,9 @@ Use the GitHub CLI to find open pull requests in `$GITHUB_REPOSITORY` that: There must be exactly one matching pull request. If there are none or more than one, make no changes and report the reason with the `noop` safe output. -Fetch and check out the latest head of that release branch. Use repository -files as data; do not execute scripts, actions, or package lifecycle hooks from -the release branch. +Fetch and check out the latest head of that release branch. Use repository files +as data; do not execute scripts, actions, or package lifecycle hooks from the +release branch. ## Scope @@ -142,14 +154,19 @@ Edit only these files: - `.github/workflows/pr-automation.yml` - `.github/workflows/release-initiate.yml` - `.github/workflows/release-publish.yml` +- `.github/workflows/update-ci-dependencies.md`, only the tool pins described + below +- `.github/workflows/update-ci-dependencies.lock.yml`, using its compiler - `.github/workflows/actions.lock`, using its generator +- `.github/aw/actions-lock.json`, using the compiler - `.github/actions/mint-github-app-token/action.yml` - `.azure-devops/*.yml` - `package.json`, only to correct an inconsistent `engines.node` value - `.nvmrc`, if present +- `docs/dependency-management.md`, only matching generator installation versions -Do not edit this workflow, its generated `.lock.yml`, application code, npm -dependencies, `package-lock.json`, or `dist`. +Do not edit application code, npm dependencies, `package-lock.json`, or `dist`. +Do not edit generated files by hand. ## GitHub Action Pins @@ -165,8 +182,8 @@ gh api repos///git/refs/tags/ --jq '.object' ``` `releases/latest` can return a tag that is not an action version. For example, -CodeQL also publishes `codeql-bundle-*` releases. If necessary, list releases and -select the newest stable `vX.Y.Z` action release: +CodeQL also publishes `codeql-bundle-*` releases. If necessary, list releases +and select the newest stable `vX.Y.Z` action release: ```bash gh api 'repos///releases?per_page=100' --paginate --jq '.[] | select(.draft == false and .prerelease == false) | .tag_name | select(test("^v[0-9]+\\.[0-9]+\\.[0-9]+$"))' @@ -179,10 +196,6 @@ Preserve `$/` references to this repository's actions. Do not replace them with `./` references or change the trusted signing action's implementation. Leave deliberately moving 1ES template `release` references unchanged. -Check open Dependabot pull requests before making an action update. If an open -pull request already covers that update, skip the duplicate and report it. Do -not merge or change another pull request. - ## Azure DevOps Task Versions In `.azure-devops/*.yml`, tasks use major versions such as `Npm@1`, `UseNode@1`, @@ -200,8 +213,7 @@ supported name with an alias. For example, `AzureCLI@3` requires Leave internal-extension tasks unchanged unless their release notes are available. These include `EsrpCodeSigning`, `PoliCheck`, `PublishSecurityAnalysisLogs`, `PostAnalysis`, and -`ComponentGovernanceComponentDetection`. Never update this product's own -`PRMetrics@N` task as part of this refresh. +`ComponentGovernanceComponentDetection`. ## Node.js Runtime Consistency @@ -218,10 +230,57 @@ runtime change and align only the divergent values. Updating the `UseNode` task major does not authorize changing its Node.js version input. Do not change compiler-managed runtimes in the generated agentic workflow. +## Workflow Tool Versions + +Refresh the pinned stable releases of `github/copilot-cli`, `github/gh-aw`, and +`github/gh-actions-lock`. Check their release notes for compatibility. Do not +use drafts, prereleases, branches, or an unversioned `latest` reference. + +In this workflow's source, change only `engine.version`, +`engine.checksums-sha256`, and the two generator `--pin` values in `steps`. Do +not change its instructions, triggers, permissions, network rules, tool +allowlist, credentials, signing action, or safe-output policy. Keep the +generator pins identical here, in `.github/workflows/build.yml`, and in the +installation examples in `docs/dependency-management.md`. + +For Copilot CLI, obtain the `SHA256SUMS.txt` asset's `digest` from the selected +release's GitHub API metadata: + +```bash +gh api repos/github/copilot-cli/releases/tags/ --jq '.assets[] | select(.name == "SHA256SUMS.txt") | .digest' +``` + +Remove the `sha256:` prefix and require exactly 64 lowercase hexadecimal +characters. Update the version and checksum together. Do not substitute an +archive checksum or trust a digest computed from a downloaded checksum file. If +the release has no valid manifest digest, stop and report the reason through +`noop` without publishing changes. + +Install the selected generator versions in the agent environment before using +them, even if the setup step installed an earlier version: + +```bash +gh extension install github/gh-aw --pin --force +gh extension install github/gh-actions-lock --pin --force +``` + +Compile the workflow before regenerating the native dependency lockfile: + +```bash +gh aw compile update-ci-dependencies --validate --no-check-update --force-refresh-action-pins --force-refresh-container-pins +``` + +Let the compiler maintain generated action pins, container digests, and runtime +versions. Do not use `--approve`, `--fix`, `--allow-action-refs`, or disabled +validation to bypass a required policy change. If installation, compilation, or +validation fails, or the compiler requires new capabilities or approval, report +the actual reason through `noop` and do not publish partial changes. + ## Regenerate the Actions Lockfile -After updating action references, regenerate the native GitHub Actions -dependency lockfile, including transitive dependencies: +After compiling the agentic workflow and updating action references, regenerate +the native GitHub Actions dependency lockfile, including transitive +dependencies: ```bash gh actions-lock --no-narrow --no-interactive @@ -229,20 +288,22 @@ gh actions-lock --verify ``` Keep the generated `.github/workflows/actions.lock` in the same change as the -action updates. Do not edit it by hand. Do not regenerate the agentic workflow's -separate `update-ci-dependencies.lock.yml` during a dependency refresh. +action updates, compiled workflow, and `.github/aw/actions-lock.json`. If +lockfile generation or verification fails, report the actual reason through +`noop` and do not publish partial changes. ## Publish the Changes Preserve formatting, trailing newlines, and unrelated changes. Before publishing, fetch the remote release branch again. Build automation can add generated commits while you work. Integrate its latest head without discarding -those commits, and regenerate the Actions lockfile if the action inputs changed. -Never force-push. +those commits. If the workflow source or generator pins changed, reinstall the +matching generators and compile again. Regenerate the native Actions lockfile +last if action inputs or the compiled workflow changed. Never force-push. Use `push_to_pull_request_branch` to publish only the scoped changes to the -selected release pull request, with commit message `chore: refresh CI pins`. -Do not push directly or call write APIs. The trusted safe-output job signs and +selected release pull request, with commit message `chore: refresh CI pins`. Do +not push directly or call write APIs. The trusted safe-output job signs and publishes the commit with the repository's App token, so Build runs on the new commit. If no updates are needed, report that through `noop`. diff --git a/docs/dependency-management.md b/docs/dependency-management.md index 5a7921e5..2d874064 100644 --- a/docs/dependency-management.md +++ b/docs/dependency-management.md @@ -62,7 +62,7 @@ versions and `integrity` hashes recorded for each package (see versions of all direct and transitive dependencies. This file is committed to version control to ensure deterministic builds. - **[`.github/workflows/actions.lock`][actionslock]**: Locks GitHub Actions and - their transitive action dependencies. Build verifies this native workflow + their transitive action dependencies. The build verifies this native workflow dependency lockfile with `gh actions-lock --verify`. ## Updating @@ -96,6 +96,13 @@ versions on the existing release pull request. It also checks Node.js runtime consistency without upgrading the runtime. Its file allowlist includes the current PR automation workflow and `.azure-devops` pipelines. +It also refreshes its own Copilot CLI, agentic compiler, and native lockfile +generator pins. Generator versions stay consistent across the workflow, Build, +and the installation examples below. Self-updates change dependency pins and +generated output, not the workflow's instructions, permissions, billing, or +signing controls. These changes remain on the release pull request and require +the existing review and merge approvals. + The workflow requires exactly one open, same-repository release pull request targeting `main`. PR title indicators do not affect selection. If no unique release pull request exists, the workflow reports the reason without making @@ -105,23 +112,9 @@ changes. To retry it, run the workflow from `main`: gh workflow run update-ci-dependencies.lock.yml --ref main ``` -Copilot inference uses the built-in `GITHUB_TOKEN` with -`copilot-requests: write`, so usage is billed to the organization rather than a -personal token. An organization administrator must enable **Copilot CLI** and -**Allow use of Copilot CLI billed to the organization** in Copilot policy -settings. Enterprise policies must also permit this use. See -[Copilot CLI organization billing][copilotbilling]. A personal -`COPILOT_GITHUB_TOKEN` is not required. - -The agent has read-only repository access and no production signing access. -The trusted safe-output job uses the `production` environment and the -existing Azure OIDC/Key Vault signing action. The `microsoft-pr-metrics` App and -its repository installation must grant `contents: write`, -`pull_requests: write`, and **`workflows: write`**. The workflow explicitly -requests these installation-token permissions. If an App permission changes, an -installation owner must accept the change before the first run. The existing -contents permission alone cannot update workflow files. No App private key is -stored in GitHub. +The agent has read-only repository access and no production signing access. The +trusted safe-output job uses the `production` environment and the existing Azure +OIDC/Key Vault signing action. The compiler currently requires a versioned action reference rather than the native `$/` syntax. The AI workflow therefore pins the trusted signing action @@ -144,8 +137,13 @@ gh extension install github/gh-aw --pin v1.0.1 gh extension install github/gh-actions-lock --pin v0.4.0 ``` -After changing the agentic workflow source, compile it first. After changing -any action references, regenerate the native dependency lockfile: +The automated refresh installs the selected pinned generators in its agent +environment. Copilot CLI updates also pin the SHA-256 digest of the release's +`SHA256SUMS.txt` asset, obtained from GitHub release metadata. The workflow +reports failures without publishing partial updates. + +After changing the agentic workflow source, compile it first. After changing any +action references, regenerate the native dependency lockfile: ```bash gh aw compile update-ci-dependencies @@ -158,10 +156,10 @@ with `gh aw compile update-ci-dependencies --approve`. Keep action changes and their lockfile updates in the same commit. Dependabot also updates matching lockfile entries when it updates an action in a locked workflow. -Dependabot excludes generated `.github/workflows/*.lock.yml` files. To -refresh compiler-managed action pins, add `--force-refresh-action-pins` to the -compile command above. Commit any `.github/aw/actions-lock.json` changes with -the regenerated files. +Dependabot excludes generated `.github/workflows/*.lock.yml` files. To refresh +compiler-managed action pins, add `--force-refresh-action-pins` to the compile +command above. Commit any `.github/aw/actions-lock.json` changes with the +regenerated files. Build recompiles the agentic workflow and rejects stale generated output. Super-Linter excludes the generated `.lock.yml`; the compiler validates its @@ -183,7 +181,6 @@ schema and action pins instead. [azuredevopstemplate]: https://github.com/microsoft/PR-Metrics/blob/main/.azure-devops/template.yml [azurepipelinestasksdk]: https://github.com/microsoft/azure-pipelines-task-lib [codeql]: https://codeql.github.com/ -[copilotbilling]: https://docs.github.com/copilot/how-tos/copilot-cli/use-copilot-cli-in-actions [dependabot]: https://github.com/microsoft/PR-Metrics/blob/main/.github/dependabot.yml [dependabotalerts]: https://docs.github.com/code-security/dependabot/dependabot-alerts/about-dependabot-alerts [dependabotsecurityupdates]: https://docs.github.com/code-security/dependabot/dependabot-security-updates/about-dependabot-security-updates From 3df3cd0b241b6ba1928b45e9892b5b995bca9230 Mon Sep 17 00:00:00 2001 From: Muiris Woulfe Date: Thu, 29 Oct 2026 17:38:37 +0000 Subject: [PATCH 7/8] ci: remove native workflow lockfiles Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: bbc1bf98-847f-4a02-9212-a22eaab288a5 --- .gitattributes | 1 - .github/workflows/actions.lock | 121 ------------------ .github/workflows/build.yml | 5 - .github/workflows/pr-automation.yml | 4 +- .github/workflows/release-initiate.yml | 9 +- .github/workflows/release-publish.yml | 2 +- .../workflows/update-ci-dependencies.lock.yml | 14 +- .github/workflows/update-ci-dependencies.md | 38 +----- docs/dependency-management.md | 40 ++---- 9 files changed, 36 insertions(+), 198 deletions(-) delete mode 100644 .github/workflows/actions.lock diff --git a/.gitattributes b/.gitattributes index 464baad0..765e5adb 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,6 +1,5 @@ .github/aw/actions-lock.json linguist-generated=true .github/workflows/*.lock.yml linguist-generated=true -.github/workflows/actions.lock linguist-generated=true dist/exec-child.js linguist-generated=true dist/index.mjs linguist-generated=true dist/lib.json linguist-generated=true diff --git a/.github/workflows/actions.lock b/.github/workflows/actions.lock deleted file mode 100644 index b0463fab..00000000 --- a/.github/workflows/actions.lock +++ /dev/null @@ -1,121 +0,0 @@ -# This file is machine-generated by `gh actions-lock`. -# Do not edit by hand; run `gh actions-lock` to update. -# Docs: https://gh.io/actions-lockfile -version: 'v0.0.3' -workflows: - '.github/workflows/build.yml': - - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' - - 'actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1' - - 'actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9' - - 'github/codeql-action@9b3254085494b55a0f7c4c2b3d2d52cc712ce370' - - 'super-linter/super-linter@2da136927bd4a73596db63044b504547c62cb854' - '.github/workflows/pr-automation.yml': - - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' - - 'actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c' - - 'actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a' - - 'azure/login@a641126d1b8aa4d1fa005f4f92df94a3a4c4c906' - '.github/workflows/release-initiate.yml': - - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' - - 'actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1' - - 'azure/login@a641126d1b8aa4d1fa005f4f92df94a3a4c4c906' - - 'grafana/github-api-commit-action@b1d81091e8480dd11fcea8bc1f0ab977a0376ca5' - '.github/workflows/release-publish.yml': - - 'actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8' - - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' - - 'actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1' - - 'actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9' - - 'azure/login@a641126d1b8aa4d1fa005f4f92df94a3a4c4c906' - - 'sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6' - '.github/workflows/update-ci-dependencies.lock.yml': - - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' - - 'actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333' - - 'actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3' - - 'actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1' - - 'actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9' - - 'github/gh-aw-actions@221ba4f4319de6b8e809d1a15528b3ae6a818aa5' - - 'microsoft/pr-metrics@5fe360db472f2604e1d2c0f5d33600d033db40ae' -dependencies: - 'actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8': - ref: 'v4.2.2' - commit: 'sha1-4d101475d8b20a2381f78447822ac1eab6504dd8' - owner_id: 44036562 - repo_id: 760702757 - uses: - - 'actions/attest@508db95dd578ae2727ebd6217d5ba78e4fbda05d' - 'actions/attest@508db95dd578ae2727ebd6217d5ba78e4fbda05d': - ref: 'v4.2.1' - commit: 'sha1-508db95dd578ae2727ebd6217d5ba78e4fbda05d' - owner_id: 44036562 - repo_id: 760701061 - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1': - ref: 'v7.0.1' - commit: 'sha1-3d3c42e5aac5ba805825da76410c181273ba90b1' - owner_id: 44036562 - repo_id: 197814629 - 'actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c': - ref: 'v8.0.1' - commit: 'sha1-3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c' - owner_id: 44036562 - repo_id: 192626254 - 'actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333': - ref: 'v8.0.2' - commit: 'sha1-9000827ccba6bdab643e8b6fd33ac0654aef8333' - owner_id: 44036562 - repo_id: 192626254 - 'actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3': - ref: 'v9.0.0' - commit: 'sha1-3a2844b7e9c422d3c10d287c895573f7108da1b3' - owner_id: 44036562 - repo_id: 205262760 - 'actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1': - ref: 'v7.1.0' - commit: 'sha1-949feb2413d6458794dcd2491c4babbbce0c15c1' - owner_id: 44036562 - repo_id: 189476904 - 'actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a': - ref: 'v7.0.1' - commit: 'sha1-043fb46d1a93c77aae656e7c1c64a875d1fc6a0a' - owner_id: 44036562 - repo_id: 192625955 - 'actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9': - ref: 'v7.0.2' - commit: 'sha1-cf430e030ddbb5b0abf93d22962f4752f3646cd9' - owner_id: 44036562 - repo_id: 192625955 - 'azure/login@a641126d1b8aa4d1fa005f4f92df94a3a4c4c906': - ref: 'v3.1.0' - commit: 'sha1-a641126d1b8aa4d1fa005f4f92df94a3a4c4c906' - owner_id: 6844498 - repo_id: 210798615 - 'github/codeql-action@9b3254085494b55a0f7c4c2b3d2d52cc712ce370': - ref: 'v4.39.1' - commit: 'sha1-9b3254085494b55a0f7c4c2b3d2d52cc712ce370' - owner_id: 9919 - repo_id: 259445878 - 'github/gh-aw-actions@221ba4f4319de6b8e809d1a15528b3ae6a818aa5': - ref: 'v1.0.1' - commit: 'sha1-221ba4f4319de6b8e809d1a15528b3ae6a818aa5' - owner_id: 9919 - repo_id: 1156386970 - 'grafana/github-api-commit-action@b1d81091e8480dd11fcea8bc1f0ab977a0376ca5': - ref: 'v1.0.0' - commit: 'sha1-b1d81091e8480dd11fcea8bc1f0ab977a0376ca5' - owner_id: 7195757 - repo_id: 631276923 - 'microsoft/pr-metrics@5fe360db472f2604e1d2c0f5d33600d033db40ae': - ref: 'v1.8.3' - commit: 'sha1-5fe360db472f2604e1d2c0f5d33600d033db40ae' - owner_id: 6154722 - repo_id: 309438703 - uses: - - 'azure/login@a641126d1b8aa4d1fa005f4f92df94a3a4c4c906' - 'sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6': - ref: 'v4.1.2' - commit: 'sha1-6f9f17788090df1f26f669e9d70d6ae9567deba6' - owner_id: 71096353 - repo_id: 351211695 - 'super-linter/super-linter@2da136927bd4a73596db63044b504547c62cb854': - ref: 'v9.0.0' - commit: 'sha1-2da136927bd4a73596db63044b504547c62cb854' - owner_id: 74564708 - repo_id: 216581567 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index acaa64dc..58ac8d0e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -158,11 +158,6 @@ jobs: env: GH_TOKEN: ${{ github.token }} - - name: Workflow Lockfile – Verify - run: gh extension install github/gh-actions-lock --pin v0.4.0 && gh actions-lock --verify - env: - GH_TOKEN: ${{ github.token }} - - name: Install Node.js uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 with: diff --git a/.github/workflows/pr-automation.yml b/.github/workflows/pr-automation.yml index 05e72708..16541604 100644 --- a/.github/workflows/pr-automation.yml +++ b/.github/workflows/pr-automation.yml @@ -90,7 +90,7 @@ jobs: - name: App Token – Mint id: app-token # Use the controller action from the workflow's own revision. - uses: $/.github/actions/mint-github-app-token + uses: ./.github/actions/mint-github-app-token # zizmor: ignore[self-repository] with: azure-client-id: ${{ vars.AZURE_CLIENT_ID }} azure-tenant-id: ${{ vars.AZURE_TENANT_ID }} @@ -144,7 +144,7 @@ jobs: name: App Token – Mint id: app-token # Use the controller action from the workflow's own revision. - uses: $/.github/actions/mint-github-app-token + uses: ./.github/actions/mint-github-app-token # zizmor: ignore[self-repository] with: azure-client-id: ${{ vars.AZURE_CLIENT_ID }} azure-tenant-id: ${{ vars.AZURE_TENANT_ID }} diff --git a/.github/workflows/release-initiate.yml b/.github/workflows/release-initiate.yml index 6368cec6..3a0ed0c6 100644 --- a/.github/workflows/release-initiate.yml +++ b/.github/workflows/release-initiate.yml @@ -23,9 +23,16 @@ jobs: contents: read id-token: write steps: + - name: Checkout Trusted Action + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + ref: ${{ github.workflow_sha }} + sparse-checkout: .github/actions + - name: App Token – Mint id: app-token - uses: $/.github/actions/mint-github-app-token + uses: ./.github/actions/mint-github-app-token # zizmor: ignore[self-repository] with: azure-client-id: ${{ vars.AZURE_CLIENT_ID }} azure-tenant-id: ${{ vars.AZURE_TENANT_ID }} diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml index 25cf5692..36af4c9a 100644 --- a/.github/workflows/release-publish.yml +++ b/.github/workflows/release-publish.yml @@ -36,7 +36,7 @@ jobs: - name: App Token – Mint id: app-token - uses: $/.github/actions/mint-github-app-token + uses: ./.github/actions/mint-github-app-token # zizmor: ignore[self-repository] with: azure-client-id: ${{ vars.AZURE_CLIENT_ID }} azure-tenant-id: ${{ vars.AZURE_TENANT_ID }} diff --git a/.github/workflows/update-ci-dependencies.lock.yml b/.github/workflows/update-ci-dependencies.lock.yml index 810960b6..631a41d8 100644 --- a/.github/workflows/update-ci-dependencies.lock.yml +++ b/.github/workflows/update-ci-dependencies.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"f5ed0e759e1664614fec775c9e6b331b223d6db250b4f0836f274a1687979e37","body_hash":"241b6032ce54d9b34cb137ae46f1097fe63a466712daea0c4aab2521c23979d2","compiler_version":"v1.0.1","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.103"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"de8365b08b6897ecad3fa3a3b6940ecc2a83745055de3aa0ee49689f0c11dedb","body_hash":"e30c01d82467d76128d08e64d5bbbd34a10997a46921b518e23502a8cf941e78","compiler_version":"v1.0.1","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.103"}} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_CI_TRIGGER_TOKEN","GH_AW_DEFAULT_OTLP_ENDPOINT","GH_AW_DEFAULT_OTLP_HEADERS","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/download-artifact","sha":"9000827ccba6bdab643e8b6fd33ac0654aef8333","version":"v8.0.2"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"949feb2413d6458794dcd2491c4babbbce0c15c1","version":"v7.1.0"},{"repo":"actions/upload-artifact","sha":"cf430e030ddbb5b0abf93d22962f4752f3646cd9","version":"v7.0.2"},{"repo":"github/gh-aw-actions/setup","sha":"221ba4f4319de6b8e809d1a15528b3ae6a818aa5","version":"v1.0.1"},{"repo":"microsoft/PR-Metrics/.github/actions/mint-github-app-token","sha":"5fe360db472f2604e1d2c0f5d33600d033db40ae","version":"5fe360db472f2604e1d2c0f5d33600d033db40ae"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.29.0","digest":"sha256:b14bd399376180b5649a9324be3b50fbfc82bfe8f0c80045840416b5a4e65b96","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.29.0@sha256:b14bd399376180b5649a9324be3b50fbfc82bfe8f0c80045840416b5a4e65b96"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.29.0","digest":"sha256:baff00b856a4bdc93bce134928c70af3d3492f2e518757115042040674d56b0b","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.29.0@sha256:baff00b856a4bdc93bce134928c70af3d3492f2e518757115042040674d56b0b"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.29.0","digest":"sha256:6e0cbf7f980beb78b5461563a8164f6439ca959bc93733d5a6b52972e523ed50","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.29.0@sha256:6e0cbf7f980beb78b5461563a8164f6439ca959bc93733d5a6b52972e523ed50"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.5.0","digest":"sha256:d3544a4222e7efeeeb38669d8a1af0c72691c55b8f6506b15aa5920f7f31b7bc","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.5.0@sha256:d3544a4222e7efeeeb38669d8a1af0c72691c55b8f6506b15aa5920f7f31b7bc"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:2c2ea524e648b91c8333ce246e3838fcf5b19ac70e45baac1a51b9207299749f","pinned_image":"ghcr.io/github/gh-aw-node@sha256:2c2ea524e648b91c8333ce246e3838fcf5b19ac70e45baac1a51b9207299749f"},{"image":"ghcr.io/github/github-mcp-server:v2.0.3","digest":"sha256:250bc6ce70788207608ef74cef4397230ff2e8481218da74d6093e4bd9101132","pinned_image":"ghcr.io/github/github-mcp-server:v2.0.3@sha256:250bc6ce70788207608ef74cef4397230ff2e8481218da74d6093e4bd9101132"}],"mcp_servers":[{"name":"github","tools":["get_commit","get_file_contents","get_latest_release","get_me","get_pull_request","get_pull_request_comments","get_pull_request_diff","get_pull_request_files","get_pull_request_review_comments","get_pull_request_reviews","get_pull_request_status","get_release_by_tag","get_tag","issue_read","list_branches","list_commits","list_issue_types","list_issues","list_pull_requests","list_releases","list_starred_repositories","list_tags","pull_request_read","search_code","search_issues","search_pull_requests","search_repositories"]},{"name":"safeoutputs","tools":["noop","push_to_pull_request_branch","report_incomplete","report_missing_data","report_missing_tool"]}],"threat_detection":{"mode":"enabled"},"admission":false} # This file was automatically generated by gh-aw (v1.0.1). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # @@ -567,9 +567,7 @@ jobs: - env: GH_TOKEN: ${{ github.token }} name: Install Workflow Maintenance Tools - run: |- - gh extension install github/gh-aw --pin v1.0.1 - gh extension install github/gh-actions-lock --pin v0.4.0 + run: gh extension install github/gh-aw --pin v1.0.1 - name: Configure Git credentials env: @@ -639,7 +637,7 @@ jobs: env: GH_AW_FILE_ROOT: "${{ runner.temp }}/gh-aw" GH_AW_FILE_CONFIG: "{\"files\":[{\"path\":\"safeoutputs/config.json\",\"content_env\":\"GH_AW_SAFE_OUTPUTS_CONFIG\"}]}" - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_report_incomplete_issue\":{},\"noop\":{\"max\":2,\"report-as-issue\":\"false\"},\"push_to_pull_request_branch\":{\"allowed_files\":[\".github/workflows/build.yml\",\".github/workflows/pr-automation.yml\",\".github/workflows/release-initiate.yml\",\".github/workflows/release-publish.yml\",\".github/workflows/update-ci-dependencies.md\",\".github/workflows/update-ci-dependencies.lock.yml\",\".github/workflows/actions.lock\",\".github/aw/actions-lock.json\",\".github/actions/mint-github-app-token/action.yml\",\".azure-devops/*.yml\",\"package.json\",\".nvmrc\",\"docs/dependency-management.md\"],\"github-token\":\"${{ steps.repository-token.outputs.token }}\",\"if_no_changes\":\"ignore\",\"max\":1,\"max_patch_size\":4096,\"protect_top_level_dot_folders\":true,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"CODEOWNERS\",\"DESIGN.md\",\"README.md\",\"CONTRIBUTING.md\",\"SECURITY.md\",\"CODE_OF_CONDUCT.md\",\"AGENTS.md\"],\"protected_files_policy\":\"allowed\",\"required_labels\":[\"release\"],\"target\":\"*\"},\"report_incomplete\":{},\"report_missing_data\":{},\"report_missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_report_incomplete_issue\":{},\"noop\":{\"max\":2,\"report-as-issue\":\"false\"},\"push_to_pull_request_branch\":{\"allowed_files\":[\".github/workflows/build.yml\",\".github/workflows/pr-automation.yml\",\".github/workflows/release-initiate.yml\",\".github/workflows/release-publish.yml\",\".github/workflows/update-ci-dependencies.md\",\".github/workflows/update-ci-dependencies.lock.yml\",\".github/aw/actions-lock.json\",\".github/actions/mint-github-app-token/action.yml\",\".azure-devops/*.yml\",\"package.json\",\".nvmrc\",\"docs/dependency-management.md\"],\"github-token\":\"${{ steps.repository-token.outputs.token }}\",\"if_no_changes\":\"ignore\",\"max\":1,\"max_patch_size\":4096,\"protect_top_level_dot_folders\":true,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"CODEOWNERS\",\"DESIGN.md\",\"README.md\",\"CONTRIBUTING.md\",\"SECURITY.md\",\"CODE_OF_CONDUCT.md\",\"AGENTS.md\"],\"protected_files_policy\":\"allowed\",\"required_labels\":[\"release\"],\"target\":\"*\"},\"report_incomplete\":{},\"report_missing_data\":{},\"report_missing_tool\":{}}" with: script: | const path = require('path'); @@ -936,10 +934,8 @@ jobs: # --allow-tool shell(curl:*) # --allow-tool shell(date) # --allow-tool shell(echo) - # --allow-tool shell(gh actions-lock) # --allow-tool shell(gh api) # --allow-tool shell(gh aw compile update-ci-dependencies) - # --allow-tool shell(gh extension install github/gh-actions-lock) # --allow-tool shell(gh extension install github/gh-aw) # --allow-tool shell(gh pr list) # --allow-tool shell(gh pr view) @@ -1043,7 +1039,7 @@ jobs: GH_AW_AWF_ATTEMPT_LOG_NAME=copilot \ bash "${RUNNER_TEMP}/gh-aw/actions/run_awf_with_startup_retries.sh" -- \ 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" ${GH_AW_ENGINE_STEP_TIMEOUT_MINUTES:+--agent-timeout "$GH_AW_ENGINE_STEP_TIMEOUT_MINUTES"} ${GH_AW_TOOL_CACHE_MOUNT:+--mount "$GH_AW_TOOL_CACHE_MOUNT"} ${GH_AW_DOCKER_HOST:+--docker-host "$GH_AW_DOCKER_HOST"} --env-all --exclude-env ACTIONS_ID_TOKEN_REQUEST_TOKEN --exclude-env ACTIONS_ID_TOKEN_REQUEST_URL --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GH_AW_OTLP_ALL_HEADERS --exclude-env GH_AW_OTLP_ENDPOINTS --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_AGENT_ID --exclude-env OTEL_EXPORTER_OTLP_ENDPOINT --exclude-env OTEL_EXPORTER_OTLP_HEADERS --mount /tmp/gh-aw:/tmp/gh-aw:rw --log-level info --session-state-dir /tmp/gh-aw/sandbox/agent/session-state --skip-pull \ - -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && : "${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"; GH_AW_TOOL_CACHE="$RUNNER_TOOL_CACHE"; GH_AW_TOOL_BINS="$(find "$GH_AW_TOOL_CACHE" -maxdepth 5 -type d -name bin 2>/dev/null | tr "\n" ":")"; GH_AW_TOOL_BINS="${GH_AW_TOOL_BINS%:}"; export PATH="$PATH${GH_AW_TOOL_BINS:+:}$GH_AW_TOOL_BINS"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true; [ -n "$ERLANG_HOME" ] && export PATH="$ERLANG_HOME/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 || true)"; fi; if [ -z "$GH_AW_NODE_EXEC" ]; then echo "node runtime missing on this runner — check runtimes.node in workflow YAML" >&2; exit 127; fi; GH_AW_NPM_GLOBAL_ROOT="$(npm root -g 2>/dev/null || true)"; if [ -n "$GH_AW_NPM_GLOBAL_ROOT" ]; then export NODE_PATH="${GH_AW_NPM_GLOBAL_ROOT}${NODE_PATH:+:${NODE_PATH}}"; fi; "$GH_AW_NODE_EXEC" "${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs" "${RUNNER_TEMP}/gh-aw/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)'\'' --allow-tool '\''shell(curl:*)'\'' --allow-tool '\''shell(date)'\'' --allow-tool '\''shell(echo)'\'' --allow-tool '\''shell(gh actions-lock)'\'' --allow-tool '\''shell(gh api)'\'' --allow-tool '\''shell(gh aw compile update-ci-dependencies)'\'' --allow-tool '\''shell(gh extension install github/gh-actions-lock)'\'' --allow-tool '\''shell(gh extension install github/gh-aw)'\'' --allow-tool '\''shell(gh pr list)'\'' --allow-tool '\''shell(gh pr view)'\'' --allow-tool '\''shell(git add:*)'\'' --allow-tool '\''shell(git branch:*)'\'' --allow-tool '\''shell(git checkout:*)'\'' --allow-tool '\''shell(git commit:*)'\'' --allow-tool '\''shell(git merge:*)'\'' --allow-tool '\''shell(git rm:*)'\'' --allow-tool '\''shell(git status)'\'' --allow-tool '\''shell(git switch:*)'\'' --allow-tool '\''shell(git:*)'\'' --allow-tool '\''shell(github:*)'\'' --allow-tool '\''shell(grep)'\'' --allow-tool '\''shell(head)'\'' --allow-tool '\''shell(jq)'\'' --allow-tool '\''shell(ls)'\'' --allow-tool '\''shell(printf)'\'' --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 write --deny-tool workflow --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' + -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && : "${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"; GH_AW_TOOL_CACHE="$RUNNER_TOOL_CACHE"; GH_AW_TOOL_BINS="$(find "$GH_AW_TOOL_CACHE" -maxdepth 5 -type d -name bin 2>/dev/null | tr "\n" ":")"; GH_AW_TOOL_BINS="${GH_AW_TOOL_BINS%:}"; export PATH="$PATH${GH_AW_TOOL_BINS:+:}$GH_AW_TOOL_BINS"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true; [ -n "$ERLANG_HOME" ] && export PATH="$ERLANG_HOME/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 || true)"; fi; if [ -z "$GH_AW_NODE_EXEC" ]; then echo "node runtime missing on this runner — check runtimes.node in workflow YAML" >&2; exit 127; fi; GH_AW_NPM_GLOBAL_ROOT="$(npm root -g 2>/dev/null || true)"; if [ -n "$GH_AW_NPM_GLOBAL_ROOT" ]; then export NODE_PATH="${GH_AW_NPM_GLOBAL_ROOT}${NODE_PATH:+:${NODE_PATH}}"; fi; "$GH_AW_NODE_EXEC" "${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs" "${RUNNER_TEMP}/gh-aw/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)'\'' --allow-tool '\''shell(curl:*)'\'' --allow-tool '\''shell(date)'\'' --allow-tool '\''shell(echo)'\'' --allow-tool '\''shell(gh api)'\'' --allow-tool '\''shell(gh aw compile update-ci-dependencies)'\'' --allow-tool '\''shell(gh extension install github/gh-aw)'\'' --allow-tool '\''shell(gh pr list)'\'' --allow-tool '\''shell(gh pr view)'\'' --allow-tool '\''shell(git add:*)'\'' --allow-tool '\''shell(git branch:*)'\'' --allow-tool '\''shell(git checkout:*)'\'' --allow-tool '\''shell(git commit:*)'\'' --allow-tool '\''shell(git merge:*)'\'' --allow-tool '\''shell(git rm:*)'\'' --allow-tool '\''shell(git status)'\'' --allow-tool '\''shell(git switch:*)'\'' --allow-tool '\''shell(git:*)'\'' --allow-tool '\''shell(github:*)'\'' --allow-tool '\''shell(grep)'\'' --allow-tool '\''shell(head)'\'' --allow-tool '\''shell(jq)'\'' --allow-tool '\''shell(ls)'\'' --allow-tool '\''shell(printf)'\'' --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 write --deny-tool workflow --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' env: AWF_REFLECT_ENABLED: 1 COPILOT_AGENT_RUNNER_TYPE: STANDALONE @@ -2223,7 +2219,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,docs.github.com,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,learn.microsoft.com,lfs.github.com,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,patch-diff.githubusercontent.com,patchdiff.githubusercontent.com,ppa.launchpad.net,raw.githubusercontent.com,s.symcb.com,s.symcd.com,security.ubuntu.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_report_incomplete_issue\":{},\"noop\":{\"max\":2,\"report-as-issue\":\"false\"},\"push_to_pull_request_branch\":{\"allowed_files\":[\".github/workflows/build.yml\",\".github/workflows/pr-automation.yml\",\".github/workflows/release-initiate.yml\",\".github/workflows/release-publish.yml\",\".github/workflows/update-ci-dependencies.md\",\".github/workflows/update-ci-dependencies.lock.yml\",\".github/workflows/actions.lock\",\".github/aw/actions-lock.json\",\".github/actions/mint-github-app-token/action.yml\",\".azure-devops/*.yml\",\"package.json\",\".nvmrc\",\"docs/dependency-management.md\"],\"github-token\":\"${{ steps.repository-token.outputs.token }}\",\"if_no_changes\":\"ignore\",\"max\":1,\"max_patch_size\":4096,\"protect_top_level_dot_folders\":true,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"CODEOWNERS\",\"DESIGN.md\",\"README.md\",\"CONTRIBUTING.md\",\"SECURITY.md\",\"CODE_OF_CONDUCT.md\",\"AGENTS.md\"],\"protected_files_policy\":\"allowed\",\"required_labels\":[\"release\"],\"target\":\"*\"},\"report_incomplete\":{},\"report_missing_data\":{},\"report_missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_report_incomplete_issue\":{},\"noop\":{\"max\":2,\"report-as-issue\":\"false\"},\"push_to_pull_request_branch\":{\"allowed_files\":[\".github/workflows/build.yml\",\".github/workflows/pr-automation.yml\",\".github/workflows/release-initiate.yml\",\".github/workflows/release-publish.yml\",\".github/workflows/update-ci-dependencies.md\",\".github/workflows/update-ci-dependencies.lock.yml\",\".github/aw/actions-lock.json\",\".github/actions/mint-github-app-token/action.yml\",\".azure-devops/*.yml\",\"package.json\",\".nvmrc\",\"docs/dependency-management.md\"],\"github-token\":\"${{ steps.repository-token.outputs.token }}\",\"if_no_changes\":\"ignore\",\"max\":1,\"max_patch_size\":4096,\"protect_top_level_dot_folders\":true,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"CODEOWNERS\",\"DESIGN.md\",\"README.md\",\"CONTRIBUTING.md\",\"SECURITY.md\",\"CODE_OF_CONDUCT.md\",\"AGENTS.md\"],\"protected_files_policy\":\"allowed\",\"required_labels\":[\"release\"],\"target\":\"*\"},\"report_incomplete\":{},\"report_missing_data\":{},\"report_missing_tool\":{}}" GH_AW_CI_TRIGGER_TOKEN: ${{ secrets.GH_AW_CI_TRIGGER_TOKEN }} GITHUB_TOKEN: ${{ steps.repository-token.outputs.token }} GH_AW_GITHUB_TOKEN_SOURCE: ${{ secrets.GH_AW_GITHUB_TOKEN != '' && 'pat' || 'github_actions' }} diff --git a/.github/workflows/update-ci-dependencies.md b/.github/workflows/update-ci-dependencies.md index 96fc41ba..df43b54e 100644 --- a/.github/workflows/update-ci-dependencies.md +++ b/.github/workflows/update-ci-dependencies.md @@ -51,9 +51,6 @@ tools: - gh pr view * - gh aw compile update-ci-dependencies * - gh extension install github/gh-aw * - - gh extension install github/gh-actions-lock * - - gh actions-lock - - gh actions-lock * - jq * - curl * @@ -76,7 +73,6 @@ steps: - name: Install Workflow Maintenance Tools run: | gh extension install github/gh-aw --pin v1.0.1 - gh extension install github/gh-actions-lock --pin v0.4.0 env: GH_TOKEN: ${{ github.token }} @@ -96,7 +92,6 @@ safe-outputs: - .github/workflows/release-publish.yml - .github/workflows/update-ci-dependencies.md - .github/workflows/update-ci-dependencies.lock.yml - - .github/workflows/actions.lock - .github/aw/actions-lock.json - .github/actions/mint-github-app-token/action.yml - .azure-devops/*.yml @@ -157,7 +152,6 @@ Edit only these files: - `.github/workflows/update-ci-dependencies.md`, only the tool pins described below - `.github/workflows/update-ci-dependencies.lock.yml`, using its compiler -- `.github/workflows/actions.lock`, using its generator - `.github/aw/actions-lock.json`, using the compiler - `.github/actions/mint-github-app-token/action.yml` - `.azure-devops/*.yml` @@ -192,8 +186,8 @@ gh api 'repos///releases?per_page=100' --paginate --jq '.[] | selec If a tag refers to an annotated tag object, dereference it through the Git tags API until you reach a commit. Never use a tag-object SHA as an action pin. -Preserve `$/` references to this repository's actions. Do not replace them with -`./` references or change the trusted signing action's implementation. Leave +Preserve `./` references to this repository's actions and their trusted checkout +steps. Do not change the trusted signing action's implementation. Leave deliberately moving 1ES template `release` references unchanged. ## Azure DevOps Task Versions @@ -232,12 +226,12 @@ compiler-managed runtimes in the generated agentic workflow. ## Workflow Tool Versions -Refresh the pinned stable releases of `github/copilot-cli`, `github/gh-aw`, and -`github/gh-actions-lock`. Check their release notes for compatibility. Do not +Refresh the pinned stable releases of `github/copilot-cli` and `github/gh-aw`. +Check their release notes for compatibility. Do not use drafts, prereleases, branches, or an unversioned `latest` reference. In this workflow's source, change only `engine.version`, -`engine.checksums-sha256`, and the two generator `--pin` values in `steps`. Do +`engine.checksums-sha256`, and the compiler `--pin` value in `steps`. Do not change its instructions, triggers, permissions, network rules, tool allowlist, credentials, signing action, or safe-output policy. Keep the generator pins identical here, in `.github/workflows/build.yml`, and in the @@ -261,10 +255,9 @@ them, even if the setup step installed an earlier version: ```bash gh extension install github/gh-aw --pin --force -gh extension install github/gh-actions-lock --pin --force ``` -Compile the workflow before regenerating the native dependency lockfile: +Compile the workflow after updating its source or compiler pin: ```bash gh aw compile update-ci-dependencies --validate --no-check-update --force-refresh-action-pins --force-refresh-container-pins @@ -276,30 +269,13 @@ validation to bypass a required policy change. If installation, compilation, or validation fails, or the compiler requires new capabilities or approval, report the actual reason through `noop` and do not publish partial changes. -## Regenerate the Actions Lockfile - -After compiling the agentic workflow and updating action references, regenerate -the native GitHub Actions dependency lockfile, including transitive -dependencies: - -```bash -gh actions-lock --no-narrow --no-interactive -gh actions-lock --verify -``` - -Keep the generated `.github/workflows/actions.lock` in the same change as the -action updates, compiled workflow, and `.github/aw/actions-lock.json`. If -lockfile generation or verification fails, report the actual reason through -`noop` and do not publish partial changes. - ## Publish the Changes Preserve formatting, trailing newlines, and unrelated changes. Before publishing, fetch the remote release branch again. Build automation can add generated commits while you work. Integrate its latest head without discarding those commits. If the workflow source or generator pins changed, reinstall the -matching generators and compile again. Regenerate the native Actions lockfile -last if action inputs or the compiled workflow changed. Never force-push. +matching compiler and compile again. Never force-push. Use `push_to_pull_request_branch` to publish only the scoped changes to the selected release pull request, with commit message `chore: refresh CI pins`. Do diff --git a/docs/dependency-management.md b/docs/dependency-management.md index 2d874064..091f1672 100644 --- a/docs/dependency-management.md +++ b/docs/dependency-management.md @@ -61,9 +61,6 @@ versions and `integrity` hashes recorded for each package (see - **[`package-lock.json`][packagelockjson]**: Records the exact resolved versions of all direct and transitive dependencies. This file is committed to version control to ensure deterministic builds. -- **[`.github/workflows/actions.lock`][actionslock]**: Locks GitHub Actions and - their transitive action dependencies. The build verifies this native workflow - dependency lockfile with `gh actions-lock --verify`. ## Updating @@ -96,8 +93,8 @@ versions on the existing release pull request. It also checks Node.js runtime consistency without upgrading the runtime. Its file allowlist includes the current PR automation workflow and `.azure-devops` pipelines. -It also refreshes its own Copilot CLI, agentic compiler, and native lockfile -generator pins. Generator versions stay consistent across the workflow, Build, +It also refreshes its own Copilot CLI and agentic compiler pins. +Compiler versions stay consistent across the workflow, Build, and the installation examples below. Self-updates change dependency pins and generated output, not the workflow's instructions, permissions, billing, or signing controls. These changes remain on the release pull request and require @@ -116,45 +113,36 @@ The agent has read-only repository access and no production signing access. The trusted safe-output job uses the `production` environment and the existing Azure OIDC/Key Vault signing action. -The compiler currently requires a versioned action reference rather than the -native `$/` syntax. The AI workflow therefore pins the trusted signing action +The AI workflow pins the trusted signing action to a repository commit. Update that reference and recompile if the shared -signing implementation changes. The other workflows use `$/` to select the -action from their own workflow revision. +signing implementation changes. The other workflows use `./` references after +checking out trusted repository code. -### Workflow Lockfiles +### Agentic Workflow Compilation -The native [Actions workflow dependency lockfile][workflowlockfiles], -`.github/workflows/actions.lock`, is distinct from the generated agentic -workflow, `update-ci-dependencies.lock.yml`. Both are committed. The latter is -compiled from `update-ci-dependencies.md`; do not edit either generated file by -hand. +The generated agentic workflow, `update-ci-dependencies.lock.yml`, is compiled +from `update-ci-dependencies.md`. It is an executable workflow, not a native +Actions dependency lockfile. Do not edit the generated workflow by hand. -Install the pinned generators once: +Install the pinned compiler once: ```bash gh extension install github/gh-aw --pin v1.0.1 -gh extension install github/gh-actions-lock --pin v0.4.0 ``` -The automated refresh installs the selected pinned generators in its agent +The automated refresh installs the selected pinned compiler in its agent environment. Copilot CLI updates also pin the SHA-256 digest of the release's `SHA256SUMS.txt` asset, obtained from GitHub release metadata. The workflow reports failures without publishing partial updates. -After changing the agentic workflow source, compile it first. After changing any -action references, regenerate the native dependency lockfile: +After changing the agentic workflow source, compile it: ```bash gh aw compile update-ci-dependencies -gh actions-lock --no-narrow --no-interactive -gh actions-lock --verify ``` Review any new actions or secrets before approving compiler manifest changes -with `gh aw compile update-ci-dependencies --approve`. Keep action changes and -their lockfile updates in the same commit. Dependabot also updates matching -lockfile entries when it updates an action in a locked workflow. +with `gh aw compile update-ci-dependencies --approve`. Dependabot excludes generated `.github/workflows/*.lock.yml` files. To refresh compiler-managed action pins, add `--force-refresh-action-pins` to the compile @@ -177,7 +165,6 @@ schema and action pins instead. - [Gitleaks][gitleaks] scans for accidentally committed secrets via [Super-Linter][superlinter]. -[actionslock]: https://github.com/microsoft/PR-Metrics/blob/main/.github/workflows/actions.lock [azuredevopstemplate]: https://github.com/microsoft/PR-Metrics/blob/main/.azure-devops/template.yml [azurepipelinestasksdk]: https://github.com/microsoft/azure-pipelines-task-lib [codeql]: https://codeql.github.com/ @@ -198,4 +185,3 @@ schema and action pins instead. [superlinter]: https://github.com/super-linter/super-linter [typescript]: https://www.typescriptlang.org/ [updatecidependencies]: https://github.com/microsoft/PR-Metrics/blob/main/.github/workflows/update-ci-dependencies.md -[workflowlockfiles]: https://docs.github.com/actions/concepts/security/workflow-dependency-lockfiles From 78850be07135c49b8bd61d681ac5206100fc2faf Mon Sep 17 00:00:00 2001 From: Muiris Woulfe Date: Thu, 29 Oct 2026 17:46:56 +0000 Subject: [PATCH 8/8] docs(dependency-management): improve formatting and clarity - Adjust line breaks for better readability - Ensure consistent presentation of information --- .../workflows/update-ci-dependencies.lock.yml | 2 +- .github/workflows/update-ci-dependencies.md | 14 +++++++------- docs/dependency-management.md | 17 ++++++----------- 3 files changed, 14 insertions(+), 19 deletions(-) diff --git a/.github/workflows/update-ci-dependencies.lock.yml b/.github/workflows/update-ci-dependencies.lock.yml index 631a41d8..108992e5 100644 --- a/.github/workflows/update-ci-dependencies.lock.yml +++ b/.github/workflows/update-ci-dependencies.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"de8365b08b6897ecad3fa3a3b6940ecc2a83745055de3aa0ee49689f0c11dedb","body_hash":"e30c01d82467d76128d08e64d5bbbd34a10997a46921b518e23502a8cf941e78","compiler_version":"v1.0.1","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.103"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"de8365b08b6897ecad3fa3a3b6940ecc2a83745055de3aa0ee49689f0c11dedb","body_hash":"fdb2424b664b72dfdf47135f75fb0a614291fbd8f24b1611eed4971d4ec4241a","compiler_version":"v1.0.1","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.103"}} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_CI_TRIGGER_TOKEN","GH_AW_DEFAULT_OTLP_ENDPOINT","GH_AW_DEFAULT_OTLP_HEADERS","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/download-artifact","sha":"9000827ccba6bdab643e8b6fd33ac0654aef8333","version":"v8.0.2"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"949feb2413d6458794dcd2491c4babbbce0c15c1","version":"v7.1.0"},{"repo":"actions/upload-artifact","sha":"cf430e030ddbb5b0abf93d22962f4752f3646cd9","version":"v7.0.2"},{"repo":"github/gh-aw-actions/setup","sha":"221ba4f4319de6b8e809d1a15528b3ae6a818aa5","version":"v1.0.1"},{"repo":"microsoft/PR-Metrics/.github/actions/mint-github-app-token","sha":"5fe360db472f2604e1d2c0f5d33600d033db40ae","version":"5fe360db472f2604e1d2c0f5d33600d033db40ae"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.29.0","digest":"sha256:b14bd399376180b5649a9324be3b50fbfc82bfe8f0c80045840416b5a4e65b96","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.29.0@sha256:b14bd399376180b5649a9324be3b50fbfc82bfe8f0c80045840416b5a4e65b96"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.29.0","digest":"sha256:baff00b856a4bdc93bce134928c70af3d3492f2e518757115042040674d56b0b","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.29.0@sha256:baff00b856a4bdc93bce134928c70af3d3492f2e518757115042040674d56b0b"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.29.0","digest":"sha256:6e0cbf7f980beb78b5461563a8164f6439ca959bc93733d5a6b52972e523ed50","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.29.0@sha256:6e0cbf7f980beb78b5461563a8164f6439ca959bc93733d5a6b52972e523ed50"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.5.0","digest":"sha256:d3544a4222e7efeeeb38669d8a1af0c72691c55b8f6506b15aa5920f7f31b7bc","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.5.0@sha256:d3544a4222e7efeeeb38669d8a1af0c72691c55b8f6506b15aa5920f7f31b7bc"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:2c2ea524e648b91c8333ce246e3838fcf5b19ac70e45baac1a51b9207299749f","pinned_image":"ghcr.io/github/gh-aw-node@sha256:2c2ea524e648b91c8333ce246e3838fcf5b19ac70e45baac1a51b9207299749f"},{"image":"ghcr.io/github/github-mcp-server:v2.0.3","digest":"sha256:250bc6ce70788207608ef74cef4397230ff2e8481218da74d6093e4bd9101132","pinned_image":"ghcr.io/github/github-mcp-server:v2.0.3@sha256:250bc6ce70788207608ef74cef4397230ff2e8481218da74d6093e4bd9101132"}],"mcp_servers":[{"name":"github","tools":["get_commit","get_file_contents","get_latest_release","get_me","get_pull_request","get_pull_request_comments","get_pull_request_diff","get_pull_request_files","get_pull_request_review_comments","get_pull_request_reviews","get_pull_request_status","get_release_by_tag","get_tag","issue_read","list_branches","list_commits","list_issue_types","list_issues","list_pull_requests","list_releases","list_starred_repositories","list_tags","pull_request_read","search_code","search_issues","search_pull_requests","search_repositories"]},{"name":"safeoutputs","tools":["noop","push_to_pull_request_branch","report_incomplete","report_missing_data","report_missing_tool"]}],"threat_detection":{"mode":"enabled"},"admission":false} # This file was automatically generated by gh-aw (v1.0.1). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # diff --git a/.github/workflows/update-ci-dependencies.md b/.github/workflows/update-ci-dependencies.md index df43b54e..3709d91c 100644 --- a/.github/workflows/update-ci-dependencies.md +++ b/.github/workflows/update-ci-dependencies.md @@ -227,15 +227,15 @@ compiler-managed runtimes in the generated agentic workflow. ## Workflow Tool Versions Refresh the pinned stable releases of `github/copilot-cli` and `github/gh-aw`. -Check their release notes for compatibility. Do not -use drafts, prereleases, branches, or an unversioned `latest` reference. +Check their release notes for compatibility. Do not use drafts, prereleases, +branches, or an unversioned `latest` reference. In this workflow's source, change only `engine.version`, -`engine.checksums-sha256`, and the compiler `--pin` value in `steps`. Do -not change its instructions, triggers, permissions, network rules, tool -allowlist, credentials, signing action, or safe-output policy. Keep the -generator pins identical here, in `.github/workflows/build.yml`, and in the -installation examples in `docs/dependency-management.md`. +`engine.checksums-sha256`, and the compiler `--pin` value in `steps`. Do not +change its instructions, triggers, permissions, network rules, tool allowlist, +credentials, signing action, or safe-output policy. Keep the generator pins +identical here, in `.github/workflows/build.yml`, and in the installation +examples in `docs/dependency-management.md`. For Copilot CLI, obtain the `SHA256SUMS.txt` asset's `digest` from the selected release's GitHub API metadata: diff --git a/docs/dependency-management.md b/docs/dependency-management.md index 091f1672..c1666cbd 100644 --- a/docs/dependency-management.md +++ b/docs/dependency-management.md @@ -93,12 +93,12 @@ versions on the existing release pull request. It also checks Node.js runtime consistency without upgrading the runtime. Its file allowlist includes the current PR automation workflow and `.azure-devops` pipelines. -It also refreshes its own Copilot CLI and agentic compiler pins. -Compiler versions stay consistent across the workflow, Build, -and the installation examples below. Self-updates change dependency pins and -generated output, not the workflow's instructions, permissions, billing, or -signing controls. These changes remain on the release pull request and require -the existing review and merge approvals. +It also refreshes its own Copilot CLI and agentic compiler pins. Compiler +versions stay consistent across the workflow, Build, and the installation +examples below. Self-updates change dependency pins and generated output, not +the workflow's instructions, permissions, billing, or signing controls. These +changes remain on the release pull request and require the existing review and +merge approvals. The workflow requires exactly one open, same-repository release pull request targeting `main`. PR title indicators do not affect selection. If no unique @@ -113,11 +113,6 @@ The agent has read-only repository access and no production signing access. The trusted safe-output job uses the `production` environment and the existing Azure OIDC/Key Vault signing action. -The AI workflow pins the trusted signing action -to a repository commit. Update that reference and recompile if the shared -signing implementation changes. The other workflows use `./` references after -checking out trusted repository code. - ### Agentic Workflow Compilation The generated agentic workflow, `update-ci-dependencies.lock.yml`, is compiled