release.yml fails on tag push: secrets.GITHUB_TOKEN lacks release-write scope #6
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Symptom
v2026.05.0tag push on 2026-05-09 triggeredrelease.ymlon the macmini Forgejo Runner (task 2871). Run finished withstatus=failure(run id3125, html_url https://git.kapteinis.lv/ojars/latvian-apostrofs/actions/runs/19) within seconds. The first release was created manually via API from the operator MacBook so the README PR (#5) and the Homebrew Cask bump (homebrew-pareizrakstiba0856cbf) could land tonight.Root cause
release.ymluses${{ secrets.GITHUB_TOKEN }}for theCreate Forgejo releasestep (introduced in00fcf79per PR #4 review feedback — to avoid the manualFORGEJO_RELEASE_TOKENsetup that spell-checker requires). On this Forgejo instance, the auto-providedGITHUB_TOKENdoes not carry release-write scope. Thecurl -fsS -X POSTto/api/v1/repos/{}/releasesreturns 401,set -euo pipefailfails the step, run is marked failure.Spell-checker (
latvian-spell-checker/.forgejo/workflows/release.yml) explicitly usessecrets.FORGEJO_RELEASE_TOKENfor this exact reason.Fix options
FORGEJO_RELEASE_TOKENon this repo (Settings → Secrets → Add Secret, value from SOPSforgejo.release_token). Restorerelease.ymlto use it. Symmetric with spell-checker. Pro: zero manual work per release. Con: re-introduces the cross-repo-token concern that motivated the GITHUB_TOKEN attempt.release.ymlentirely + document the manual release procedure indocs/RELEASING.md(build PKG locally withVERSION=X bash build-pkg.sh, create release via API + upload asset, sed-bump the cask). Apostrofs releases are rare (the underlying layout last changed in 2013); manual is proportional. Pro: no secret to manage. Con: no CI safety net.permissions:block explicitly grantingcontents: write(Forgejo Actions sometimes requires explicit permission declaration for the runtime token to gain write scope, even withGITHUB_TOKEN). Untested — would need to verify against Forgejo runtime token semantics for this version.My recommendation: option 2 (delete
release.yml, shipdocs/RELEASING.md). The CI complexity isn't proportional to the once-every-few-years release cadence of a static keyboard layout.Acceptance
release.ymlremoved and replaced with documented manual procedure (option 2).Closed — fixed end-to-end on 2026-05-10
Two bugs fixed in this session:
(1) Token scope — switched
secrets.GITHUB_TOKEN→secrets.FORGEJO_RELEASE_TOKEN. The Forgejo-auto-injectedGITHUB_TOKENlacks release-write scope on this Forgejo, hence the HTTP 401. New secret value sourced from existingforgejo.ojars_tokenPAT in SOPS (full repo + release-write scope, no new credential created).(2)
doesn'theredoc-in-$() gotcha — discovered while diagnosing #6. The release body was built viaBODY=$(cat <<EOF ... EOF). Bash$()command-substitution tracks single quotes within the heredoc body, so the apostrophe inLog out and back in if it doesn't appear immediately.was treated as an unmatched single quote. Bash matched it against'.id'further down (jq -r '.id') and reportedunexpected EOF while looking for matching''with no useful line context. Fully reproducible withbash -n` on the extracted run: block.Fix: write the body to a temp file outside the
$()context, read it back viajq --rawfile body "$BODY_FILE"instead of--arg body "$BODY". Apostrophes (and any other shell-quote-special characters) in the body are now safe.Validation:
v2026.05.1(real workflow re-trigger, not a no-op) — task 2878 succeeded end-to-end.6e28f9d).Cross-cutting fix: spell-checker had the same token issue + a separate version-substitution bug (
Pareizrakstiba/Info.plisthardcoded2026.01-fork.1so any tag != fork.1 silently mismatched the .pkg filename). Both fixed inojars/latvian-spell-checker@b5e070f; tagv2026.01-fork.2proved the pipeline. Cask auto-bumped (homebrew-pareizrakstiba@9fe9895).Commits:
ojars/latvian-apostrofs@b7e1772— release.yml heredoc + token fixojars/latvian-spell-checker@b5e070f— Info.plist$(VERSION)substitutionojars/homebrew-pareizrakstiba@6e28f9d+9fe9895— Cask bumpstokens.enc.yaml—ojars_noteupdated to record FORGEJO_RELEASE_TOKEN deployment.Closing as fixed.