diff --git a/.github/workflows/auto-rebase-reusable.yml b/.github/workflows/auto-rebase-reusable.yml index a18220de0..a66a339cf 100644 --- a/.github/workflows/auto-rebase-reusable.yml +++ b/.github/workflows/auto-rebase-reusable.yml @@ -76,6 +76,9 @@ on: default: '' type: string secrets: + GH_PAT_DON_PETRY: + description: "Canonical org PAT — preferred over GH_PAT_WORKFLOWS when present" + required: false GH_PAT_WORKFLOWS: description: "PAT with workflows scope — required for sentinel comment to trigger dev-lead rebase" required: false @@ -104,8 +107,8 @@ jobs: - name: Update behind non-Dependabot PRs env: - GH_TOKEN: ${{ secrets.GH_PAT_WORKFLOWS || github.token }} - HAS_PAT: ${{ secrets.GH_PAT_WORKFLOWS != '' }} + GH_TOKEN: ${{ secrets.GH_PAT_DON_PETRY || secrets.GH_PAT_WORKFLOWS || github.token }} + HAS_PAT: ${{ (secrets.GH_PAT_DON_PETRY || secrets.GH_PAT_WORKFLOWS) != '' }} REPO: ${{ github.repository }} ELIGIBILITY: ${{ inputs.eligibility }} READY_LABEL: ${{ inputs.ready_label }} diff --git a/.github/workflows/daily-org-status.yml b/.github/workflows/daily-org-status.yml index f58424493..cbb37131c 100644 --- a/.github/workflows/daily-org-status.yml +++ b/.github/workflows/daily-org-status.yml @@ -22,7 +22,7 @@ jobs: - name: Generate org status report env: - GH_TOKEN: ${{ secrets.GH_PAT_WORKFLOWS }} + GH_TOKEN: ${{ secrets.GH_PAT_DON_PETRY || secrets.GH_PAT_WORKFLOWS }} run: | chmod +x scripts/org_status.sh scripts/org_report.sh bash scripts/org_status.sh > /tmp/report.md @@ -47,7 +47,7 @@ jobs: - name: Create daily-report issue env: - GH_TOKEN: ${{ secrets.GH_PAT_WORKFLOWS }} + GH_TOKEN: ${{ secrets.GH_PAT_DON_PETRY || secrets.GH_PAT_WORKFLOWS }} run: | DATE=$(date -u +%Y-%m-%d) # This digest embeds the date in its title, so a fresh issue is created diff --git a/.github/workflows/feature-ideation.yml b/.github/workflows/feature-ideation.yml index ba85dce05..5ad1c732b 100644 --- a/.github/workflows/feature-ideation.yml +++ b/.github/workflows/feature-ideation.yml @@ -107,15 +107,15 @@ jobs: # A workflow_dispatch fired with GITHUB_TOKEN is accepted but never starts # a run (loop prevention), so a PAT is required (same as initiative-planner). env: - GH_TOKEN: ${{ secrets.GH_PAT_WORKFLOWS }} + GH_TOKEN: ${{ secrets.GH_PAT_DON_PETRY || secrets.GH_PAT_WORKFLOWS }} run: | if [ -z "${GH_TOKEN}" ]; then - echo "::error::GH_PAT_WORKFLOWS is required — a workflow_dispatch fired with GITHUB_TOKEN will not start a run." + echo "::error::GH_PAT_DON_PETRY (or legacy GH_PAT_WORKFLOWS) is required — a workflow_dispatch fired with GITHUB_TOKEN will not start a run." exit 1 fi - name: Re-dispatch under workflow_dispatch env: - GH_TOKEN: ${{ secrets.GH_PAT_WORKFLOWS }} + GH_TOKEN: ${{ secrets.GH_PAT_DON_PETRY || secrets.GH_PAT_WORKFLOWS }} REPO: ${{ github.repository }} DISCUSSION_NUMBER: ${{ github.event.discussion.number }} run: | diff --git a/.github/workflows/idea-enhancer-reusable.yml b/.github/workflows/idea-enhancer-reusable.yml index 00d4b98a5..e7a40c7de 100644 --- a/.github/workflows/idea-enhancer-reusable.yml +++ b/.github/workflows/idea-enhancer-reusable.yml @@ -30,6 +30,9 @@ on: default: "petry-projects/.github-private" type: string secrets: + GH_PAT_DON_PETRY: + description: "Canonical org PAT — preferred over GH_PAT_WORKFLOWS when present" + required: false GH_PAT_WORKFLOWS: description: "Classic PAT with repo + workflow scope used to dispatch the central idea-enhancer (GITHUB_TOKEN cannot start a workflow_dispatch run)." required: true @@ -51,16 +54,16 @@ jobs: steps: - name: Guard — PAT present env: - GH_TOKEN: ${{ secrets.GH_PAT_WORKFLOWS }} + GH_TOKEN: ${{ secrets.GH_PAT_DON_PETRY || secrets.GH_PAT_WORKFLOWS }} run: | if [ -z "${GH_TOKEN}" ]; then - echo "::error::GH_PAT_WORKFLOWS is required — a workflow_dispatch fired with GITHUB_TOKEN will not start a run." + echo "::error::GH_PAT_DON_PETRY (or legacy GH_PAT_WORKFLOWS) is required — a workflow_dispatch fired with GITHUB_TOKEN will not start a run." exit 1 fi - name: Dispatch central idea-enhancer for this repo env: - GH_TOKEN: ${{ secrets.GH_PAT_WORKFLOWS }} + GH_TOKEN: ${{ secrets.GH_PAT_DON_PETRY || secrets.GH_PAT_WORKFLOWS }} CENTRAL_REPO: ${{ inputs.central_repo }} TARGET_REPO: ${{ github.repository }} run: | diff --git a/.github/workflows/idea-triage-reusable.yml b/.github/workflows/idea-triage-reusable.yml index 42231db2d..785154b8b 100644 --- a/.github/workflows/idea-triage-reusable.yml +++ b/.github/workflows/idea-triage-reusable.yml @@ -27,6 +27,9 @@ on: default: "petry-projects/.github-private" type: string secrets: + GH_PAT_DON_PETRY: + description: "Canonical org PAT — preferred over GH_PAT_WORKFLOWS when present" + required: false GH_PAT_WORKFLOWS: description: "Classic PAT with repo + workflow scope used to dispatch the central idea-triage (GITHUB_TOKEN cannot start a workflow_dispatch run)." required: true @@ -41,16 +44,16 @@ jobs: steps: - name: Guard — PAT present env: - GH_TOKEN: ${{ secrets.GH_PAT_WORKFLOWS }} + GH_TOKEN: ${{ secrets.GH_PAT_DON_PETRY || secrets.GH_PAT_WORKFLOWS }} run: | if [ -z "${GH_TOKEN}" ]; then - echo "::error::GH_PAT_WORKFLOWS is required — a workflow_dispatch fired with GITHUB_TOKEN will not start a run." + echo "::error::GH_PAT_DON_PETRY (or legacy GH_PAT_WORKFLOWS) is required — a workflow_dispatch fired with GITHUB_TOKEN will not start a run." exit 1 fi - name: Dispatch central idea-triage for this repo env: - GH_TOKEN: ${{ secrets.GH_PAT_WORKFLOWS }} + GH_TOKEN: ${{ secrets.GH_PAT_DON_PETRY || secrets.GH_PAT_WORKFLOWS }} CENTRAL_REPO: ${{ inputs.central_repo }} TARGET_REPO: ${{ github.repository }} run: | diff --git a/.github/workflows/initiative-driver.yml b/.github/workflows/initiative-driver.yml index 7b3a67cc1..2f4f13d39 100644 --- a/.github/workflows/initiative-driver.yml +++ b/.github/workflows/initiative-driver.yml @@ -73,16 +73,16 @@ jobs: - name: Guard — PAT present # PAT required: a workflow_dispatch fired with GITHUB_TOKEN never starts a run. env: - GH_TOKEN: ${{ secrets.GH_PAT_WORKFLOWS }} + GH_TOKEN: ${{ secrets.GH_PAT_DON_PETRY || secrets.GH_PAT_WORKFLOWS }} run: | if [ -z "${GH_TOKEN}" ]; then - echo "::error::GH_PAT_WORKFLOWS is required — a workflow_dispatch fired with GITHUB_TOKEN never starts a run." + echo "::error::GH_PAT_DON_PETRY (or legacy GH_PAT_WORKFLOWS) is required — a workflow_dispatch fired with GITHUB_TOKEN never starts a run." exit 1 fi - name: Dispatch central initiative-driver env: - GH_TOKEN: ${{ secrets.GH_PAT_WORKFLOWS }} + GH_TOKEN: ${{ secrets.GH_PAT_DON_PETRY || secrets.GH_PAT_WORKFLOWS }} run: | gh workflow run initiative-driver.yml \ -R petry-projects/.github-private \ diff --git a/.github/workflows/initiative-planner-reusable.yml b/.github/workflows/initiative-planner-reusable.yml index 266cd595b..43ffa9134 100644 --- a/.github/workflows/initiative-planner-reusable.yml +++ b/.github/workflows/initiative-planner-reusable.yml @@ -33,6 +33,9 @@ on: default: "petry-projects/.github-private" type: string secrets: + GH_PAT_DON_PETRY: + description: "Canonical org PAT — preferred over GH_PAT_WORKFLOWS when present" + required: false GH_PAT_WORKFLOWS: description: "Classic PAT with repo + workflow scope used to dispatch the central initiative-planner (GITHUB_TOKEN cannot start a workflow_dispatch run)." required: true @@ -54,17 +57,17 @@ jobs: steps: - name: Guard — PAT present env: - GH_TOKEN: ${{ secrets.GH_PAT_WORKFLOWS }} + GH_TOKEN: ${{ secrets.GH_PAT_DON_PETRY || secrets.GH_PAT_WORKFLOWS }} run: | if [ -z "${GH_TOKEN}" ]; then - echo "::error::GH_PAT_WORKFLOWS is required — a workflow_dispatch fired with GITHUB_TOKEN will not start a run." + echo "::error::GH_PAT_DON_PETRY (or legacy GH_PAT_WORKFLOWS) is required — a workflow_dispatch fired with GITHUB_TOKEN will not start a run." exit 1 fi - name: Guard — trusted actor id: trust env: - GH_TOKEN: ${{ secrets.GH_PAT_WORKFLOWS }} + GH_TOKEN: ${{ secrets.GH_PAT_DON_PETRY || secrets.GH_PAT_WORKFLOWS }} REPO: ${{ github.repository }} ACTOR: ${{ github.event.sender.login }} run: | @@ -86,7 +89,7 @@ jobs: - name: Dispatch central planner for this repo if: steps.trust.outputs.trusted == 'true' env: - GH_TOKEN: ${{ secrets.GH_PAT_WORKFLOWS }} + GH_TOKEN: ${{ secrets.GH_PAT_DON_PETRY || secrets.GH_PAT_WORKFLOWS }} PLANNER_REPO: ${{ inputs.planner_repo }} TARGET_REPO: ${{ github.repository }} DISCUSSION_NUMBER: ${{ github.event.discussion.number }} diff --git a/.github/workflows/persona-mention-reusable.yml b/.github/workflows/persona-mention-reusable.yml index aef3becfc..1c4253ce2 100644 --- a/.github/workflows/persona-mention-reusable.yml +++ b/.github/workflows/persona-mention-reusable.yml @@ -46,6 +46,9 @@ on: default: 'main' type: string secrets: + GH_PAT_DON_PETRY: + description: "Canonical org PAT — preferred over GH_PAT_WORKFLOWS when present" + required: false GH_PAT_WORKFLOWS: description: 'Classic PAT with repo scope, used for API calls and dispatching the persona' required: true @@ -118,7 +121,7 @@ jobs: - name: Route the mention env: - GH_TOKEN: ${{ secrets.GH_PAT_WORKFLOWS }} + GH_TOKEN: ${{ secrets.GH_PAT_DON_PETRY || secrets.GH_PAT_WORKFLOWS }} PERSONA_REF: ${{ inputs.persona_ref }} # Every event field arrives via env, never interpolated inline into the # run: body. A comment body and a login are attacker-controlled, and an diff --git a/.github/workflows/pinned-version-report.yml b/.github/workflows/pinned-version-report.yml index 340b61f50..f478bc2ac 100644 --- a/.github/workflows/pinned-version-report.yml +++ b/.github/workflows/pinned-version-report.yml @@ -21,15 +21,15 @@ jobs: persist-credentials: false - name: Guard — PAT present env: - GH_TOKEN: ${{ secrets.GH_PAT_WORKFLOWS }} + GH_TOKEN: ${{ secrets.GH_PAT_DON_PETRY || secrets.GH_PAT_WORKFLOWS }} run: | if [ -z "${GH_TOKEN}" ]; then - echo "::error::GH_PAT_WORKFLOWS is required — cross-repo reads need the org PAT, not github.token." + echo "::error::GH_PAT_DON_PETRY (or legacy GH_PAT_WORKFLOWS) is required — cross-repo reads need the org PAT, not github.token." exit 1 fi - name: Generate pinned-version report env: # Needs cross-repo read on consumers + tag read on the host repos. - GH_TOKEN: ${{ secrets.GH_PAT_WORKFLOWS }} + GH_TOKEN: ${{ secrets.GH_PAT_DON_PETRY || secrets.GH_PAT_WORKFLOWS }} ORG: petry-projects run: bash scripts/pinned-version-report.sh diff --git a/.github/workflows/pr-auto-review.yml b/.github/workflows/pr-auto-review.yml index f3e9781b5..7d132dc32 100644 --- a/.github/workflows/pr-auto-review.yml +++ b/.github/workflows/pr-auto-review.yml @@ -49,4 +49,4 @@ jobs: actions: read uses: ./.github/workflows/pr-auto-review-reusable.yml # local ref — always current secrets: - GH_PAT_WORKFLOWS: ${{ secrets.GH_PAT_WORKFLOWS }} + GH_PAT_WORKFLOWS: ${{ secrets.GH_PAT_DON_PETRY || secrets.GH_PAT_WORKFLOWS }} diff --git a/.github/workflows/pr-review-mention-reusable.yml b/.github/workflows/pr-review-mention-reusable.yml index 4ad53010e..c53e0adb0 100644 --- a/.github/workflows/pr-review-mention-reusable.yml +++ b/.github/workflows/pr-review-mention-reusable.yml @@ -16,6 +16,9 @@ name: PR Review — Mention Trigger (Reusable) on: workflow_call: secrets: + GH_PAT_DON_PETRY: + description: "Canonical org PAT — preferred over GH_PAT_WORKFLOWS when present" + required: false GH_PAT_WORKFLOWS: description: "Classic PAT with repo scope used for API calls and dispatching the review agent" required: true @@ -73,7 +76,7 @@ jobs: - name: Check commenter trust level id: trust env: - GH_TOKEN: ${{ secrets.GH_PAT_WORKFLOWS }} + GH_TOKEN: ${{ secrets.GH_PAT_DON_PETRY || secrets.GH_PAT_WORKFLOWS }} run: | # Only OWNER, MEMBER, and COLLABORATOR can trigger reviews. # This prevents external contributors or bots from burning review quota. @@ -115,7 +118,7 @@ jobs: id: pr if: steps.trust.outputs.trusted == 'true' env: - GH_TOKEN: ${{ secrets.GH_PAT_WORKFLOWS }} + GH_TOKEN: ${{ secrets.GH_PAT_DON_PETRY || secrets.GH_PAT_WORKFLOWS }} # Resolve by event name: review_requested and review-comment payloads # expose the PR directly; only issue_comment needs a gh api round-trip. # Guard the empty case so we never call `gh api ""` (#500). @@ -192,7 +195,7 @@ jobs: - name: Trigger review agent if: steps.trust.outputs.trusted == 'true' env: - GH_TOKEN: ${{ secrets.GH_PAT_WORKFLOWS }} + GH_TOKEN: ${{ secrets.GH_PAT_DON_PETRY || secrets.GH_PAT_WORKFLOWS }} PR_URL: ${{ steps.pr.outputs.pr_url }} run: | # repository_dispatch requires only Contents: write, not Actions: write. diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json index c3e2ca61a..4cfab8dcd 100644 --- a/node_modules/.package-lock.json +++ b/node_modules/.package-lock.json @@ -1,5 +1,5 @@ { - "name": "pr-821", + "name": "pr-834", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/package-lock.json b/package-lock.json index 226b2af96..7e18afbef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "pr-821", + "name": "pr-834", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/test/workflows/pr-review-mention/reusable-secrets.bats b/test/workflows/pr-review-mention/reusable-secrets.bats new file mode 100644 index 000000000..65af2d102 --- /dev/null +++ b/test/workflows/pr-review-mention/reusable-secrets.bats @@ -0,0 +1,38 @@ +#!/usr/bin/env bats +# Pins the credential fallback wiring inside the reusable +# pr-review-mention-reusable.yml (issue #833). +# +# The thin caller invokes this reusable with `secrets: inherit`, so both +# GH_PAT_DON_PETRY (canonical org secret) and GH_PAT_WORKFLOWS (legacy) resolve +# inside its steps. Every GH_TOKEN must prefer the canonical secret with the old +# name as a `||` fallback, so retiring GH_PAT_WORKFLOWS org-wide leaves behavior +# intact (.github-private#1326). + +setup() { + load 'helpers/setup' +} + +FALLBACK='${{ secrets.GH_PAT_DON_PETRY || secrets.GH_PAT_WORKFLOWS }}' + +gh_token_for_step() { + local step_name="$1" + yq -r ".jobs.handle-mention.steps[] | select(.name == \"${step_name}\") | .env.GH_TOKEN" "$TT_WORKFLOW" +} + +@test "reusable: 'Check commenter trust level' GH_TOKEN uses the canonical fallback" { + run gh_token_for_step "Check commenter trust level" + [ "$status" -eq 0 ] + [ "$output" = "$FALLBACK" ] +} + +@test "reusable: 'Resolve PR URL' GH_TOKEN uses the canonical fallback" { + run gh_token_for_step "Resolve PR URL" + [ "$status" -eq 0 ] + [ "$output" = "$FALLBACK" ] +} + +@test "reusable: 'Trigger review agent' GH_TOKEN uses the canonical fallback" { + run gh_token_for_step "Trigger review agent" + [ "$status" -eq 0 ] + [ "$output" = "$FALLBACK" ] +}