diff --git a/.github/workflows/release-candidate.yml b/.github/workflows/release-candidate.yml index 5b598ee14..9ab00c0bd 100644 --- a/.github/workflows/release-candidate.yml +++ b/.github/workflows/release-candidate.yml @@ -123,7 +123,16 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 20 permissions: - contents: write # push rc tag + marker + # The default GITHUB_TOKEN cannot be granted `workflows: write`, so + # tag pushes that reach a commit which modified `.github/workflows/**` + # are rejected with: "refusing to allow a GitHub App to create or + # update workflow ... without `workflows` permission". We pass a + # fine-grained PAT (RELEASE_PUSH_TOKEN, scoped to this repo with + # Contents: write + Workflows: write) to `actions/checkout` so that + # the subsequent `git push --atomic` of the v-tag and rc marker + # carries the PAT's identity. Job-level GITHUB_TOKEN keeps its + # scoped permissions for everything else (npm provenance, etc.). + contents: write # push rc tag + marker (via PAT) id-token: write # npm provenance outputs: vtag: ${{ steps.reltag.outputs.vtag }} @@ -132,6 +141,11 @@ jobs: with: fetch-depth: 0 fetch-tags: true + # Use the PAT so `origin` is preauthed for `git push`. Without + # this the default GITHUB_TOKEN is wired into the remote, and a + # workflows-touching tag push is rejected — see the permissions + # block above. + token: ${{ secrets.RELEASE_PUSH_TOKEN }} - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: