From 1e01a4bbe7ebf35cb1452c2e0c95f886dc9c758f Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Fri, 17 Jul 2026 15:52:59 -0700 Subject: [PATCH] fix(ci): restore fork-safe token fallback on PR gates broken by #66373 (#66577) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #66373 swapped GITHUB_TOKEN -> AUTOFIX_BOT_PAT across the workflows. That PAT is empty on fork PRs (forks get no repo secrets), which broke every fork PR two ways: 1. detect-changes classified with the empty PAT -> the compare API failed all 3 retries -> the classifier failed open and force-enabled the ci_review lane on EVERY fork PR. 2. The ci-reviewed / mcp-catalog-reviewed label gates then read labels with the same empty PAT via a hard-failing retry step -> the job failed with no recovery a fork contributor could perform (they can't self-add the label; re-running can't fix it). Restores the pre-#66373 fork-safe behavior without reverting the commit's real improvements (job timeouts, per-file flake retry, network-install retries): - detect-changes + ci.yml: token falls back to the built-in read-only github.token when AUTOFIX_BOT_PAT is empty. On main it uses the PAT (authoritative); on forks it uses github.token, which can read the public compare endpoint. (An input `default:` only applies on omission, not on an empty passed value — hence the explicit `|| github.token`.) - lint ci-review + supply-chain mcp-catalog gates: restore the inline `gh pr view ... || true` label read with the github.token fallback, dropping the hard-failing retry "Fetch PR labels" step. Graceful degrade to "label absent" on an API blip, same as before #66373. Same-repo enforcement is unchanged (byte-identical logic; the PAT is still used there). Fork PRs classify correctly and the gates read labels via the read-only token exactly as they did before the regression. --- .github/actions/detect-changes/action.yml | 7 ++++++- .github/workflows/ci.yml | 4 +++- .github/workflows/lint.yml | 21 +++++++++++---------- .github/workflows/supply-chain-audit.yml | 16 +++++++--------- 4 files changed, 27 insertions(+), 21 deletions(-) diff --git a/.github/actions/detect-changes/action.yml b/.github/actions/detect-changes/action.yml index 18df8d78a4ea..106379428eca 100644 --- a/.github/actions/detect-changes/action.yml +++ b/.github/actions/detect-changes/action.yml @@ -47,7 +47,12 @@ runs: id: classify shell: bash env: - GH_TOKEN: ${{ inputs.github-token }} + # Fall back to the built-in read-only token when the caller passes an + # empty value. Fork PRs get no repo secrets, so AUTOFIX_BOT_PAT is "" + # there, and an input `default:` only applies when the input is omitted, + # not when it's passed empty. Without this fallback the compare API + # fails on forks and the classifier fails open (every lane forced on). + GH_TOKEN: ${{ inputs.github-token || github.token }} REPO: ${{ github.repository }} EVENT_NAME: ${{ github.event_name }} BASE_SHA: ${{ github.event.pull_request.base.sha }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7528116d14ac..72e34a06d64c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -53,7 +53,9 @@ jobs: id: classify uses: ./.github/actions/detect-changes with: - github-token: ${{ secrets.AUTOFIX_BOT_PAT }} + # Forks get no repo secrets (AUTOFIX_BOT_PAT is empty); fall back to + # the built-in read-only token so classification still works there. + github-token: ${{ secrets.AUTOFIX_BOT_PAT || github.token }} # ───────────────────────────────────────────────────────────────────── # Lane-gated sub-workflows. Each runs in parallel after detect finishes. diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 3b83b6f7923d..28df38ad3e5d 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -177,18 +177,19 @@ jobs: steps: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - name: Fetch PR labels - id: pr-labels - uses: ./.github/actions/retry - env: - GH_TOKEN: ${{ secrets.AUTOFIX_BOT_PAT }} - with: - command: gh pr view "${{ github.event.pull_request.number }}" --json labels --jq '.labels[].name' - name: Require ci-reviewed label id: label-check + env: + # Read-only label lookup. Use the built-in GITHUB_TOKEN (present and + # read-only on forks) so the gate works on fork PRs; fall back to it + # when AUTOFIX_BOT_PAT is empty. `|| true` degrades an API blip to + # "label absent" rather than hard-failing the step. + GH_TOKEN: ${{ secrets.AUTOFIX_BOT_PAT || github.token }} run: | set -euo pipefail - if echo "${{ steps.pr-labels.outputs.stdout }}" | grep -Fxq 'ci-reviewed'; then + PR="${{ github.event.pull_request.number }}" + LABELS=$(gh pr view "$PR" --json labels --jq '.labels[].name' || true) + if echo "$LABELS" | grep -Fxq 'ci-reviewed'; then echo "reviewed=true" >> "$GITHUB_OUTPUT" echo "ci-reviewed label present." exit 0 @@ -203,7 +204,7 @@ jobs: - name: Post or update review warning if: steps.label-check.outputs.reviewed != 'true' && github.event.pull_request.head.repo.fork != true env: - GH_TOKEN: ${{ secrets.AUTOFIX_BOT_PAT }} + GH_TOKEN: ${{ secrets.AUTOFIX_BOT_PAT || github.token }} run: | set -euo pipefail PR="${{ github.event.pull_request.number }}" @@ -251,7 +252,7 @@ jobs: - name: Update previous warning to passed if: steps.label-check.outputs.reviewed == 'true' && github.event.pull_request.head.repo.fork != true env: - GH_TOKEN: ${{ secrets.AUTOFIX_BOT_PAT }} + GH_TOKEN: ${{ secrets.AUTOFIX_BOT_PAT || github.token }} run: | set -euo pipefail PR="${{ github.event.pull_request.number }}" diff --git a/.github/workflows/supply-chain-audit.yml b/.github/workflows/supply-chain-audit.yml index 4007668b7952..648a1f7c6a63 100644 --- a/.github/workflows/supply-chain-audit.yml +++ b/.github/workflows/supply-chain-audit.yml @@ -238,20 +238,18 @@ jobs: with: fetch-depth: 0 - - name: Fetch PR labels - id: pr-labels - uses: ./.github/actions/retry - env: - GH_TOKEN: ${{ secrets.AUTOFIX_BOT_PAT }} - with: - command: gh pr view "${{ github.event.pull_request.number }}" --json labels --jq '.labels[].name' - name: Require explicit MCP catalog review label env: - GH_TOKEN: ${{ secrets.AUTOFIX_BOT_PAT }} + # Read-only label lookup. Use the built-in GITHUB_TOKEN (present and + # read-only on forks) so the gate works on fork PRs; fall back to it + # when AUTOFIX_BOT_PAT is empty. `|| true` degrades an API blip to + # "label absent" rather than hard-failing the step. + GH_TOKEN: ${{ secrets.AUTOFIX_BOT_PAT || github.token }} run: | set -euo pipefail PR="${{ github.event.pull_request.number }}" - if echo "${{ steps.pr-labels.outputs.stdout }}" | grep -Fxq 'mcp-catalog-reviewed'; then + LABELS=$(gh pr view "$PR" --json labels --jq '.labels[].name' || true) + if echo "$LABELS" | grep -Fxq 'mcp-catalog-reviewed'; then echo "MCP catalog review label present." exit 0 fi