Skip to content

fix(ci): grant Package Release the token permissions its callee needs - #206

Open
thedavidmeister wants to merge 1 commit into
mainfrom
fix/package-release-token-permissions
Open

fix(ci): grant Package Release the token permissions its callee needs#206
thedavidmeister wants to merge 1 commit into
mainfrom
fix/package-release-token-permissions

Conversation

@thedavidmeister

@thedavidmeister thedavidmeister commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

Grants the release job the token permissions the called workflow needs, so Package Release can start at all.

Problem

Every Package Release run on this repo has ended in startup_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 recent rainix regression):

The workflow is not valid. .github/workflows/package-release.yaml (Line: 7, Col: 3):
Error calling workflow 'rainlanguage/rainix/.github/workflows/rainix-autopublish.yaml@main'.
The nested job 'release' is requesting 'contents: write, id-token: write',
but is only allowed 'contents: read, id-token: none'.

rainix-autopublish.yaml's release job declares permissions: {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 no permissions: block, so the job was handed the repository default, which on this repo is read (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 a permissions: block either — they work only because their repository default happens to be write. Across all 30 repos in the org that call rainix-autopublish, the correlation is exact and total: all 3 repos whose default is read produce startup_failure, all 27 whose default is write start 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:

    permissions:
      contents: write
      id-token: write

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 on push to main).

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.interface has the identical latent misconfigurationdefault_workflow_permissions: read, no caller permissions: block, and three consecutive startup_failures. It needs the same one-line fix; not touched here.
  • This repo's version slot blocks the run that follows. foundry.toml [package].version is 0.1.2 and the latest published rain-flare revision on the Soldeer registry is also 0.1.2, which violates rainix-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.12 reports zero findings on it. The requested permission set is exactly the set rainix-autopublish.yaml's release job 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 Release triggers only on push to main, so no branch build can exercise it end to end. Final proof is the first push to main after this merges producing a run that creates its release job instead of startup_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

  • Discriminating tests: n/a — CI workflow configuration. The behaviour under change is GitHub's run-startup permission check, which executes on GitHub's side on push to main and has no local or PR-branch test surface. The discriminating signal is the run conclusion itself: startup_failure before, a created release job after.
  • Mutations applied: n/a — no executable repository code changed. The only mutation available (removing or narrowing the permissions: block) is exactly the pre-change state, which is already known to produce startup_failure on five consecutive runs; that is the mutant, and the observed failures are it being killed.
  • Oracle: the literal GitHub startup rejection quoted above, which names the mechanism explicitly, corroborated by an exact 30/30 correlation across every repo in the org calling rainix-autopublish (3/3 read fail at startup, 27/27 write start).
  • Category check: swept every rainix-autopublish consumer in the org rather than just this repo. The category is "caller grants no permissions and the repository default is read" — three repos match: this one, rain.tofu.erc20-decimals (fixed in its own PR), and rain.verify.interface (flagged above, untouched).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Chores
    • Updated the release process permissions to support publishing packages and generating trusted release credentials.
    • Added documentation clarifying the permissions required during releases.

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>
@thedavidmeister thedavidmeister self-assigned this Aug 13, 2026
@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 142f3c54-8268-409a-ba18-e6b51c109283

📥 Commits

Reviewing files that changed from the base of the PR and between b634aad and 385cbec.

📒 Files selected for processing (1)
  • .github/workflows/package-release.yaml

Walkthrough

The package release job now grants contents: write and id-token: write permissions to the reusable publishing workflow. Comments document the required token scopes.

Changes

Release workflow permissions

Layer / File(s) Summary
Configure release permissions
.github/workflows/package-release.yaml
The release job explicitly grants repository content write access and OIDC token write access. Comments document these permissions.

Estimated code review effort: 2 (Simple) | ~10 minutes

Mergeability Score: ⚪ Minimal · up to 385cb

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)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the change to grant the Package Release workflow the permissions required by its reusable workflow.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/package-release-token-permissions

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant