fix(ci): grant Package Release the token permissions its callee needs - #206
fix(ci): grant Package Release the token permissions its callee needs#206thedavidmeister wants to merge 1 commit into
Conversation
rainix-autopublish's release job declares `contents: write` and `id-token: write`. A called workflow can only narrow the token it is handed, never widen it, and this caller declared no permissions block, so the job was handed this repository's default of `read`. GitHub rejects the run at startup: "The nested job 'release' is requesting 'contents: write, id-token: write', but is only allowed 'contents: read, id-token: none'." Every Package Release run on this repo has ended in startup_failure as a result. Grant the set explicitly on the calling job so the request is no longer an upgrade, and so the workflow is correct under either repository default rather than depending on an invisible setting. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
WalkthroughThe package release job now grants ChangesRelease workflow permissions
Estimated code review effort: 2 (Simple) | ~10 minutes Mergeability Score: ⚪ Minimal · up to This narrowly enables the release workflow with the permissions its existing release process requires; no actionable merge-blocking risk remains beyond normal checks and review. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Grants the
releasejob the token permissions the called workflow needs, soPackage Releasecan start at all.Problem
Every
Package Releaserun on this repo has ended instartup_failure— the run is rejected before a single job is created, so there are no job logs. The literal rejection, from the run page for run 30342068489 (identical on all five recent runs, and on the oldest one, so this is not a recentrainixregression):rainix-autopublish.yaml'sreleasejob declarespermissions: {id-token: write, contents: write}— it has to, since it pushes the version-bump commit, tags and GitHub releases. A called workflow can only narrow the token it is handed, never widen it. This caller declared nopermissions:block, so the job was handed the repository default, which on this repo isread(default_workflow_permissions: read). Requesting write against a read allowance is an upgrade, and GitHub rejects the whole run at startup.The comparator repos that publish successfully (
rain.math.binary,rainlang.interface,rain.solmem,rain.string,rain.math.fixedpoint, and 22 others) do not declare apermissions:block either — they work only because their repository default happens to bewrite. Across all 30 repos in the org that callrainix-autopublish, the correlation is exact and total: all 3 repos whose default isreadproducestartup_failure, all 27 whose default iswritestart normally. There are no exceptions.Fix
Declare the grant explicitly on the calling job, rather than depending on a repository setting that is invisible from the codebase:
This is the set the callee already declares, so the request is no longer an upgrade. It is also GitHub's recommended posture — a read-only default plus explicit per-workflow grants — and it makes the workflow correct under either repository setting instead of silently depending on one. The repository-level default is a default, not a cap: the
permissions:key raises it (the documented "you typically can't grant write" caveat applies to workflows triggered by pull requests from forks; this one triggers onpushtomain).Deliberately not done: flipping this repo's Actions setting to
write. That would fix the symptom out-of-band, leave the codebase still dependent on an invisible setting, and leave the same trap armed on the other repos.Out of scope, flagged
rain.verify.interfacehas the identical latent misconfiguration —default_workflow_permissions: read, no callerpermissions:block, and three consecutivestartup_failures. It needs the same one-line fix; not touched here.foundry.toml[package].versionis0.1.2and the latest publishedrain-flarerevision on the Soldeer registry is also0.1.2, which violatesrainix-autopublish's next-version invariant (the in-dev version must be ahead of what is published). So the first run after this merges will start — which is the point of this PR — and then fail loud on the version gate. Bumping the version slot has been ruled out of scope separately.Verification
Verified: the workflow file parses and
actionlint 1.7.12reports zero findings on it. The requested permission set is exactly the setrainix-autopublish.yaml'sreleasejob declares, so the "requesting X but only allowed Y" condition that produced the rejection is satisfied by construction. Root cause is established by the literal error string above plus the 30-repo correlation, not by inference from the file looking correct.Not verified, and cannot be from a PR branch:
Package Releasetriggers only onpushtomain, so no branch build can exercise it end to end. Final proof is the first push tomainafter this merges producing a run that creates itsreleasejob instead ofstartup_failure. Note the version-slot issue above means that run is still expected to fail — at the Soldeer version gate, which is a completely different and much later failure than the startup rejection this PR fixes.QA
pushtomainand has no local or PR-branch test surface. The discriminating signal is the run conclusion itself:startup_failurebefore, a createdreleasejob after.permissions:block) is exactly the pre-change state, which is already known to producestartup_failureon five consecutive runs; that is the mutant, and the observed failures are it being killed.rainix-autopublish(3/3readfail at startup, 27/27writestart).rainix-autopublishconsumer in the org rather than just this repo. The category is "caller grants no permissions and the repository default isread" — three repos match: this one,rain.tofu.erc20-decimals(fixed in its own PR), andrain.verify.interface(flagged above, untouched).🤖 Generated with Claude Code
Summary by CodeRabbit