ci: read the bot PAT from an environment in every workflow - #6169
Conversation
The generated tend-*.yaml jobs already name the `tend` environment; the hand-written consumers still read `TEND_BOT_TOKEN` at repo level, where every workflow the repo runs can reach it. Gate the remaining five: `tests.yaml:update-rust-toolchain` and `pull-request-target.yaml:backport` run on `main`, so they take `tend`; the three release-time jobs run on a tag, so they take `release`. Restrict the backport job to a `main` base while doing so, since `pull_request_target` runs at the base branch's ref and the `tend` environment admits only `main`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
prql-bot
left a comment
There was a problem hiding this comment.
Checked each job's ref against the environment it now names, and the pairing holds: tend's deployment policy is the main branch only, release's is the *.*.* tag pattern. update-rust-toolchain is gated on nightly-upstream, which is github.event_name == 'schedule' && github.repository_owner == 'prql', so its ref is always main; the backport job's new base.ref == 'main' condition is what turns a would-be refused-environment failure on web-based PRs into a skip; and the three release jobs are all if: github.event_name == 'release', so the unconditional environment: release is right there rather than the ${{ ... || '' }} form publish-js/publish-to-cargo need for their off-release dry runs. Every remaining secrets.TEND_BOT_TOKEN reference now sits in a job that names an environment.
One note on the two secret operations: the ordering in the description is load-bearing rather than stylistic. The release environment currently holds only SNAPCRAFT_STORE_CREDENTIALS, so deleting the repo-level copy before gh secret set ... --env release lands would leave brew-dispatcher, publish-winget and push-web-branch reading an empty token — and that wouldn't surface until the next release.
The one red check, nightly / nightly-release / build-prqlc (macos-15-intel, ...), is a transient rustup fetch failure (dns error: failed to lookup address information pulling rustc-1.96.1-x86_64-apple-darwin.tar.xz), unrelated to this change. nightly is in check-ok-to-merge's allowed-failures, and that gate is green.
tend checkfailsrepo-secret-allowlist:TEND_BOT_TOKENis a repo-level secret, so every workflow the repo runs can read the bot's PAT, including workflows a same-repo PR branch adds. The allowlist escape hatch isn't available for this one — tend refusesTEND_BOT_TOKENinsecrets.allowedat config load, on the grounds that a repo-level copy is exactly what the environment gate exists to prevent.So every consumer moves behind an environment. The generated
tend-*.yamljobs already do this. The five hand-written ones split by the ref they run at, which is what decides the environment: a deployment branch policy is evaluated against the run's ref, and a job naming an environment that doesn't admit its ref is refused before its first step.tests.yaml:update-rust-toolchainmain(schedule-only)tendpull-request-target.yaml:backporttendrelease.yaml:brew-dispatcherreleaserelease.yaml:publish-wingetreleaserelease.yaml:push-web-branchreleasebackportalso gains abase.ref == 'main'condition.pull_request_targetruns at the base branch's ref, andtendadmits onlymain, so without it the backport PRs that merge intowebwould hit a refused environment rather than skipping. Backports flow out ofmain, so this doesn't lose anything.The three release jobs pick up the required reviewers already on the
releaseenvironment. GitHub approves per job rather than per environment, so a release will ask for approval in a couple more rounds than it does today.Secret operations
releasenow holds its ownTEND_BOT_TOKEN, copied from the bot'sghcredential per the install skill's step 8c, so the three release jobs have a token the moment this lands.That leaves the deletion, which is what makes the check pass. It goes after this merges, not before: a job naming an environment can still read a repo-level secret of the same name, so the workflows keep working across the merge, and deleting early would leave the ungated jobs on
mainwith an empty token.Why the release jobs can't use the
tendenvironmenttendholds the token already, but its policy admits onlymain, and tend's ownenvironmentcheck asserts that. A release job runs atrefs/tags/X.Y.Z.releaseis the environment whose policy covers that ref, and tend'scredential-environmentscheck requires required reviewers on any environment a workflow reaches on arelease:trigger, whichreleasehas.