Repository navigation
fix(ci): open coreutils drift PRs with a token permitted to create them - #2760
Merged
Merged
Conversation
The weekly Coreutils Args Drift run regenerated the drift, force-pushed it to `chore/coreutils-args-drift`, then died on `gh pr create` with "GitHub Actions is not permitted to create or approve pull requests" (run 39234801977). The run went red after all regeneration and tests were green, and no PR ever opened, so the drift stayed invisible — the exact silent-absorption mode the open-PR-only lookup was added to prevent. The job token can push (it only needs `contents: write`) but cannot open a pull request while "Allow GitHub Actions to create and approve pull requests" is off, which is the setting worth keeping since the same switch also governs approvals. So the step is split in two: the branch goes up on `github.token`, and the PR is opened with a PAT read from Doppler's `GITHUB_TOKEN`, gated on `DOPPLER_TOKEN` and masked before it crosses a step boundary — the pattern `ci.yml` already uses for privileged CI credentials. With no PAT the PR step fails naming the branch instead of skipping the PR: the drift is pushed by then, so a green run without a PR would reintroduce silent absorption. Regression tests pin both halves: a missing PAT is a red run that touches no PR, and the push keeps the job token while only the PR step gets the PAT.
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
bashkit | e8c0474 | Commit Preview URL Branch Preview URL |
Oct 20 2026, 09:43 AM |
Introducing a credential into this workflow makes the job split a security contract, not just a layout: `regenerate` executes third-party uutils code and must stay secret-free, `open-pr` holds the PAT and must never build or run uutils. Write it down next to the token-split rationale so a later change does not move a Doppler step into the wrong job.
2 tasks done
chaliy
added a commit
that referenced
this pull request
Oct 20, 2026
… modules (#2759) Regenerated by `bashkit-coreutils-port` against uutils/coreutils@d2d96946b (was 8613dffab). Utilities: cat ls mktemp od readlink realpath shuf stat tac tee truncate. Vendored module: format. Two upstream argument-surface changes; the rest is the rev header bump. - `od`: the hidden FILENAME positional gains `value_parser(OsStringValueParser::new())`. No consumer change needed — #2754 landed `helpers::string_value` / `string_values`, which read od's arguments without naming the value type, so the switch is absorbed. - `tac`: `-s/--separator` gains `allow_hyphen_values(true)`, so a hyphen-leading separator parses as a value rather than a flag, matching upstream. This drift was produced by run 39234801977, which regenerated and pushed it but could not open a PR: the Actions job token is not permitted to create pull requests. The workflow's token is fixed separately in #2760. Verified on the pinned toolchain (1.95.0): `cargo build -p bashkit` clean, 48 od unit tests and 14 tac unit tests pass, and the bash spec suite passes — the same gate the drift workflow runs before proposing a diff.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
The Coreutils Args Drift workflow's
open-prjob now uses two tokens instead ofone. The drift branch is pushed with
github.token(that only needscontents: write), and the pull request is opened with a PAT read fromDoppler's
GITHUB_TOKEN, gated onDOPPLER_TOKENbeing configured and maskedbefore it crosses a step boundary — the pattern
ci.ymlalready uses forprivileged CI credentials.
If no PAT is available the PR step fails with a message naming the branch the
drift was pushed to, rather than skipping the PR.
Why
The weekly run regenerated the drift, force-pushed it to
chore/coreutils-args-drift, then died ongh pr create:(run 39234801977).
Everything before that was green — regeneration, build, cat/tac spec tests and
the differential harness all passed — so the run went red at the last step with
no PR to show for it, and the drift stayed invisible. That is the same
silent-absorption failure the open-PR-only lookup was added to prevent (#2161),
arriving through a different door.
The job token cannot open a PR while "Allow GitHub Actions to create and approve
pull requests" is off. Leaving that setting off is the right call — the same
switch also lets Actions approve PRs, which would weaken review gating — so
the fix gives the PR step its own credential instead of widening what the job
token may do.
Failing loudly on a missing PAT is deliberate. The drift is already pushed by
the time that step runs, so a green run with no PR would recreate exactly the
invisible-drift mode; a red run with the branch name in the error is
recoverable by hand.
The pending drift this run produced is in #2759.
Before / After
Before —
Open pull request if driftedfails on every drifted run:After — the push and the PR run on separate tokens, and the no-PAT path is a
named error instead of a GraphQL failure that reads like a bug in the drift
tooling. Both halves are pinned by tests that execute the workflow's own
runscripts with stubbed
gh/git:Also checked: every
runblock in the workflow passesbash -n(this file hasbeen broken by shell/YAML slips before), the YAML parses,
just check-okfreports conformant, and
just check-doc-linksis clean.The secret boundary this workflow documents is preserved, and verified
mechanically: the
regeneratejob — the only one that builds or executesthird-party uutils code — has no Doppler step and no secret access. The PAT
lives only in
open-pr, which never checks out, builds or runs uutils; its tworemaining mentions of "uutils" are the commit message and the PR body text. The
workflow is also
schedule+workflow_dispatchonly, so no pull-requesttrigger can reach the secret.
Risk
workflow_dispatch, and the change is confined toits
open-prjob; no library or runtime code is touched.GITHUB_TOKENwithpull-requests: writeon this repository. I could notverify that from the sandbox — reading the secret store is blocked there — so
if the key is absent or under-scoped, the next drifted run will say so
explicitly in its error rather than failing obscurely. Worth a
workflow_dispatchrun to confirm end to end.Checklist
plus two new ones: the fail-loud guard and the token split