Skip to content

ci: create releases with the built-in token instead of the release app - #401

Merged
deanq merged 2 commits into
mainfrom
ci/release-token-drop-issues
Oct 30, 2026
Merged

deanq merged 2 commits into
mainfrom
ci/release-token-drop-issues

Conversation

@justinwlin

@justinwlin justinwlin commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

The Release job fails at token creation: The permissions requested are not granted to this installation (422). Since #399, the token step asks the release app runpod-release-please for contents, issues, pull-requests and workflows. The app only has contents: write, pull_requests: write and metadata: read (gh api apps/runpod-release-please-bot). Granting more needs an org owner.

This drops the app token and gives release-please the built-in GITHUB_TOKEN, as runpod-python does. The workflow already grants contents, pull-requests and issues write.

Why this works for 1.21.1

  • Release PR chore: release 1.21.1 #391 is merged, so release-please only has to create the release and tag.
  • github-actions[bot] created runpod-python v1.9.0 to v1.12.0 with the built-in token, and those release ranges changed .github/workflows/. So the token can tag releases like this one.
  • PyPI publish runs in the same workflow run from release_created, and no flash workflow triggers on release events. The built-in token not triggering other workflows doesn't matter here.

Trade-off
#97 moved to the app because the built-in token stopped working, most likely because flash disallows Actions from creating PRs. If that setting is still off, release-please can't open the next release PR with this token. runpod-flash stopped getting fixes on 2026-10-29, so 1.21.1 is expected to be the last release.

After merge
The push to main runs Release. It should create v1.21.1 and publish to PyPI from the static-IP runner (#400). Merge runpod-workers/flash#112 first (worker 1.6.1), because 1.21.1 includes #390.

@justinwlin justinwlin changed the title ci: stop requesting issues permission for the release token ci: create releases with the built-in token instead of the release app Oct 30, 2026
@deanq
deanq merged commit 407785f into main Oct 30, 2026
10 checks passed
@deanq
deanq deleted the ci/release-token-drop-issues branch October 30, 2026 17:18

@OneAsterisk OneAsterisk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude review, round 1

Verdict: Needs discussion — the change itself is harmless, but it most likely does not fix the failing release: GitHub will reject the v1.21.1 tag from GITHUB_TOKEN for the same reason it rejected the app token in the #397 and #398 runs, and the body's central claim ("the token can tag releases like this one") does not cover this case.
Approval gate: 0 Critical, 1 High, 2 Medium+Low → not approved: one High.

Existing feedback

No prior reviews or comments on this PR.

PR description vs code

Claim Status Where
Release job fails at token creation with 422 "permissions requested are not granted" ✅ runs 40991928237, 41090876796
Since #399 the token step asks for contents, issues, pull-requests, workflows ✅ removed lines; #399 diff
App has only contents: write, pull_requests: write, metadata: read ✅ gh api apps/runpod-release-please-bot; app updated_at 2025-10-10
Workflow already grants contents, pull-requests, issues write ✅ release-please.yml:7-10
runpod-python uses the built-in token ✅ runpod-python cd.yml:69
#391 merged; only release + tag remain ✅ merge 50e819a; no v1.21.1 tag or release exists
github-actions[bot] created runpod-python v1.9.0–v1.12.0 and those ranges changed .github/workflows/ ✅ 5 of 6 ranges (v1.10.0..v1.10.1 did not)
"So the token can tag releases like this one" ❌ those tags sat at the tip of main; v1.21.1 would not. See High
PyPI publish runs from release_created; no flash workflow triggers on release events ✅ ci.yml:3-7 (pull_request, push main), e2e.yml:3-4 (workflow_dispatch)
#97 moved to the app because GITHUB_TOKEN stopped working ✅ swap in #97 diff; ⚠️ the "Actions can't create PRs" cause isn't readable without admin
1.21.1 expected to be the last release ⚠️ not verifiable from the repo; consistent with the deprecation notice shipped in v1.21.0 (#387)
After merge: the push creates v1.21.1 and publishes to PyPI ❌ see High
Merge runpod-workers/flash#112 first; 1.21.1 includes #390 ✅ #112 still open; #390 is in v1.21.0..50e819a

Findings

High

  • GITHUB_TOKEN cannot create the v1.21.1 tag either — .github/workflows/release-please.yml:38. The app token's Resource not accessible by integration was not about workflow changes in range: the same app, with permissions unchanged since 2025-10-10, created runpod/host v2.276.3 and v3.0.0 and main-ui v4.128.0–v4.131.0 this week with workflow files in range. The difference on flash is that the tag target 50e819a6 is four commits behind main, and #397–#400 changed ci.yml, e2e.yml and release-please.yml. GitHub refuses to create a ref whose .github/workflows/ tree differs from every branch tip unless the App token holds workflows, and GITHUB_TOKEN cannot hold it (community discussion 151442 is this exact case with GITHUB_TOKEN; coreplanelabs/switchboard#901 shows the same 403 → 201 flip with an app token). Details and two fixes in the inline comment: pre-create the tag from a user account (then this PR works as written) or have an org owner grant the app workflows: write (then #399's step is the right one). The "Why this works" and "After merge" sections need rewriting either way.

Low

  • PyPI publish is skipped if release-please fails after creating the release — .github/workflows/release-please.yml:44. The Trade-off section's PR-creation failure (any feat/fix/docs/refactor/perf commit after the tag while Actions cannot open PRs) throws after the release exists. The job fails, pypi-publish is skipped because its needs job failed, and a rerun cannot recover: release-please then throws DuplicateReleaseError and release_created stays false. The action sets release_created before it attempts the PR (release-please-action v4 src/index.ts:144-150), and runpod-python guards exactly this with if: ${{ always() && needs.release-please.outputs.release_created ... }} (cd.yml:76). Not triggered by what is on main today (all ci:), so fine as a follow-up.
  • CI's release-PR bypass still keys on the app's login — .github/workflows/ci.yml:133-136. BOT_AUTHOR='runpod-release-please-bot[bot]' and the comment above it describe a bot that no longer authors release PRs. Any release PR this token does open would be by github-actions[bot], so the bypass falls through to the full matrix (safe, just slower) and the comment is stale. A one-line comment update is enough if the "last release" premise holds.

Nits

None.

Simplification opportunities

None; the PR already removes the only extra step.

Verified clean

  • The diff is exactly the token-step removal and the token swap; all CI checks pass at 090d6f8.
  • Workflow-level permissions cover what release-please does on the release path with GITHUB_TOKEN: create release (contents), relabel and comment on #391 (issues / pull-requests).
  • The 422 at token creation in the last two Release runs is exactly as described, and the app's permissions match the body.
  • No flash workflow listens for release events or tag pushes, so the built-in token's no-trigger limitation is moot.
  • Commits on main after 50e819a are all ci: (hidden in release-please-config.json), so once a release exists release-please will not try to open a PR on that run.
  • RELEASE_APP_ID / RELEASE_APP_PRIVATE_KEY are org secrets with no other references in the repo; RELEASE_SYSTEM.md never mentioned the app token, so no doc change is needed.
  • Only the org "formal code review on main" branch ruleset applies; no tag ruleset, so rulesets are not the blocker.
  • The Release job runs on Blacksmith, whose IPs are on the org allow list (API calls from the #398 run succeeded), so the allow list is not in play for the job.

Questions for the author

  1. The 1.21.1 CHANGELOG and release-PR body list #389, #395 and #392 only. #390, #394 and #396 merged after the release PR was last updated (the Release runs were already failing) and are in the tag's code but not in the notes. Ship as-is, or regenerate before tagging?
  2. Can an admin confirm "Allow GitHub Actions to create and approve pull requests" is off for this repo? That setting is not readable with my token, so the reason given for #97 stays unverified.
  3. Which fix do you prefer: a maintainer pushes the tag by hand and this PR merges as written, or an org owner adds Workflows: Read and write to the app and this PR closes?

Reviewed by Claude (claude-fable-5-1) via the pr-review skill. Tokens: 802 in / 63,826 out / 2,472,301 cache read / 141,392 cache write = 2,678,321. Estimated cost: $6.65 at $10/M input, $50/M output, $0.25/M cache read, $20/M 1-hour cache write (Anthropic rate card looked up 2026-10-30). Round 1 of this PR. This is automated assistance; a human owns the final call.

# workflows permission #399 requested, so its token can't be created.
# The workflow-level permissions grant contents, pull-requests and
# issues write.
token: ${{ secrets.GITHUB_TOKEN }}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

High: This token will hit the same Resource not accessible by integration that the app token hit in the #397 and #398 runs, so the merge run most likely still won't create v1.21.1.

The check that fails is not "workflow changes in range". It is that the tag's commit has a different .github/workflows/ tree from every branch tip: 50e819a6 is four commits behind main, and #397–#400 changed ci.yml, e2e.yml and release-please.yml. GitHub refuses to create such a ref from any GitHub App token without the workflows permission, and GITHUB_TOKEN cannot have that permission.

Evidence:

Two ways out:

  1. Keep this PR and have a maintainer push the tag from a user account first: git push origin 50e819a65a4b39fa7a198860e1c9f3039fc0cbab:refs/tags/v1.21.1. The create-release API ignores target_commitish when the tag already exists, so no ref is created and the check never runs. release-please then creates the release on the existing tag, release_created is true, and PyPI publish runs.
  2. Or an org owner grants the app Workflows: Read and write and ci: request workflows permission for the release token #399's token step stays, as ci: publish to PyPI from the static-IP GitHub-hosted runner #400 asked.

Either way, the "Why this works" and "After merge" sections need rewriting.

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.

3 participants