Skip to content

fix(ci): edit PRs through REST so the bot token does not need read:org (v5) - #25379

Open
AztecBot wants to merge 1 commit into
merge-train/spartan-v5from
cb/gh-pr-edit-read-org-v5
Open

fix(ci): edit PRs through REST so the bot token does not need read:org (v5)#25379
AztecBot wants to merge 1 commit into
merge-train/spartan-v5from
cb/gh-pr-edit-read-org-v5

Conversation

@AztecBot

@AztecBot AztecBot commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

Port of #25378 onto the spartan-v5 train.

Why

gh pr edit resolves the PR through a GraphQL query that always selects the PR's review requests, whose User.login / Team.name / Team.slug fields classic PATs gate behind read:org. AZTEC_BOT_GITHUB_TOKEN carries only repo + workflow, so every gh pr edit run under it is rejected before the edit is attempted:

GraphQL: Your token has not been granted the required scopes to execute this query.
The 'login' field requires one of the following scopes: ['read:org'], but your token has only
been granted the: ['repo', 'workflow'] scopes.

The equivalent REST endpoints need only the repo scope, so nothing about the token changes. That is the same conversion #25378 makes on next.

The four sites #25378 fixes, ported as-is

Site Call
scripts/merge-train/update-pr-body.sh --bodyPATCH .../pulls/{n}
scripts/merge-train/wakeup-prs.sh --add-label ci-wakeup-pr-after-mergePOST .../issues/{n}/labels
.github/workflows/ci3.yml --remove-label ci-wakeup-pr-after-mergeDELETE .../labels/{name}
.github/ci3.sh --remove-label ci-release-prDELETE .../labels/{name}
.github/workflows/ci3-external.yml (x2) --remove-label ci-externalDELETE .../labels/{name}

Bodies and label lists are built with jq rather than -f body=..., so a commit subject containing quotes, $ or @ cannot corrupt the request.

Four more sites that exist only on this branch

ci3.yml and ci3_success.sh have diverged from next, and the v5 copies carry four additional gh pr edit calls under the same token. They are the same one-line transform, so they are converted here too — two of them are currently hard failures rather than silent ones:

  • ci3.yml--remove-label ci-network-scenario (guarded by || true, silent)
  • ci3.yml--remove-label ci-network-bench (guarded by || true, silent)
  • ci3.yml--remove-label ci-network-kindno guard, and it is the first step of the ci-network-kind job, so that job fails immediately on every labelled PR and the KIND tests never run. Converted, and given the || true its three sibling one-time-use strips already have, so a missing label cannot kill a 3-hour run.
  • ci3_success.sh--remove-label ci-squash-and-mergeno guard, and it sits between squash-pr.sh and gh pr merge --auto, so ci-squash-and-merge currently aborts before the auto-merge is ever enabled.

That last one also picks up the ordering next already uses: the label is dropped before squash-pr.sh runs, because that script force-pushes and the resulting synchronize event would otherwise re-enter this path with the label still set. This is the one place where the port carries a next-side behavioural fix along with the scope fix rather than being a pure like-for-like swap.

Testing

bash -n on the four shell scripts, YAML parse on both workflows, and the jq payloads checked against subjects containing quotes, & and $. The endpoints cannot be exercised from a sandbox; the proof is the next merge-train/spartan-v5 push updating the PR body instead of exiting 1.

Deliberately not included

Sites that need a bespoke transform (PR URL → number, or a dynamically built label list) rather than the one-liner above, same exclusions as #25378 plus the two that are v5-only:

  • .github/workflows/release-canary-pr-update.yml:135 — builds --add-label flags in a string; it is what applies ci-release-pr and ci-network-kind in the first place, so those two labels are likely never being set on this branch at all
  • .github/workflows/auto-rebase-pr.yml, .github/workflows/pull-noir.yml, scripts/socket-fix-ci.sh, scripts/backport_to_staging.sh

ci3-external.yml's ci-external-once strip is untouched on purpose: it runs under github.token, which is not scope-limited this way.


Created by claudebox · group: slackbot · requested by ludamad (@ludamad) · Slack thread

gh pr edit resolves the PR through a GraphQL query that selects the review
requests, whose User.login / Team.name / Team.slug fields classic PATs gate
behind read:org. AZTEC_BOT_GITHUB_TOKEN carries only repo + workflow, so every
gh pr edit run under it is rejected before the edit is attempted. The
equivalent REST endpoints need only the repo scope.
@AztecBot AztecBot added ci-draft Run CI on draft PRs. ci-no-fail-fast Sets NO_FAIL_FAST in the CI so the run is not aborted on the first failure claudebox Owned by claudebox. it can push to this PR. labels Sep 1, 2026
@ludamad
ludamad marked this pull request as ready for review September 1, 2026 15:05
@ludamad
ludamad requested a review from charlielye as a code owner September 1, 2026 15:05
@ludamad
ludamad enabled auto-merge (squash) September 1, 2026 15:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci-draft Run CI on draft PRs. ci-no-fail-fast Sets NO_FAIL_FAST in the CI so the run is not aborted on the first failure claudebox Owned by claudebox. it can push to this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants