Repository navigation
ci: create releases with the built-in token instead of the release app - #401
Conversation
OneAsterisk
left a comment
There was a problem hiding this comment.
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; |
|
| 1.21.1 expected to be the last release | ||
| 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_TOKENcannot create the v1.21.1 tag either —.github/workflows/release-please.yml:38. The app token'sResource not accessible by integrationwas 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 target50e819a6is four commits behindmain, and #397–#400 changedci.yml,e2e.ymlandrelease-please.yml. GitHub refuses to create a ref whose.github/workflows/tree differs from every branch tip unless the App token holdsworkflows, andGITHUB_TOKENcannot hold it (community discussion 151442 is this exact case withGITHUB_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 appworkflows: 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 (anyfeat/fix/docs/refactor/perfcommit after the tag while Actions cannot open PRs) throws after the release exists. The job fails,pypi-publishis skipped because itsneedsjob failed, and a rerun cannot recover: release-please then throwsDuplicateReleaseErrorandrelease_createdstays false. The action setsrelease_createdbefore it attempts the PR (release-please-action v4src/index.ts:144-150), and runpod-python guards exactly this withif: ${{ always() && needs.release-please.outputs.release_created ... }}(cd.yml:76). Not triggered by what is onmaintoday (allci:), 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 bygithub-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
permissionscover what release-please does on the release path withGITHUB_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
releaseevents or tag pushes, so the built-in token's no-trigger limitation is moot. - Commits on
mainafter 50e819a are allci:(hidden inrelease-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_KEYare org secrets with no other references in the repo;RELEASE_SYSTEM.mdnever 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
- 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?
- 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.
- 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 }} |
There was a problem hiding this comment.
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:
- The same release app, permissions unchanged since 2025-10-10, created runpod/host v2.276.3 and v3.0.0 and runpod/main-ui v4.128.0–v4.131.0 this week with workflow files in range. Those tags were at the tip of
main. So were the runpod-python tags in the description. - https://github.com/orgs/community/discussions/151442 is this exact case with
GITHUB_TOKEN: a tag on an oldermaincommit rejected because.github/workflows/differs from the latest commit on any branch. - fix(release): the release token carries the workflows permission — the tag a release creates needs it since the history collapse coreplanelabs/switchboard#901: app token with contents + pull-requests gets 403 on release creation, 201 once
workflowsis added.
Two ways out:
- 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 ignorestarget_commitishwhen 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_createdis true, and PyPI publish runs. - 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.
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 apprunpod-release-pleaseforcontents,issues,pull-requestsandworkflows. The app only hascontents: write,pull_requests: writeandmetadata: 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 grantscontents,pull-requestsandissueswrite.Why this works for 1.21.1
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.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-flashstopped 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.