bug(_release.yml): cut-path manifest push to main blocked by branch protection pre-receive hook (workflow token is not admin) #78
Labels
No labels
bump
major
bump
minor
bump
patch
kind/bug
kind/chore
kind/docs
kind/feature
priority/critical
priority/high
priority/low
priority/medium
size/L
size/M
size/S
size/XL
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
frankenbit/release-toolkit#78
Loading…
Add table
Add a link
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
The v0.4.0 cut-path workflow completed most of its work but failed at the final manifest-update push to main:
Surfaced live during the v0.4.0 cut (actions/runs/6238 —
decide + acttask 13107).What completed before the failure
The cut-path's act-step got these substantive actions done:
mode=cutdraft-release.sh --version 0.4.0succeeded → Forgejo draft release #121 created at target5f4812dgit commitsucceeded →[main 0b20424] chore(manifest): update for v0.4.0git push origin HEAD:mainrejected by branch protection pre-receive hookSo the user-facing artifact (draft release) IS created, but the substrate-state (manifest) update never landed on main.
Root cause (verified at source)
mainbranch protection in this repo (/api/v1/repos/frankenbit/release-toolkit/branch_protections/main):The
apply_to_admins: falsesetting means admin pushes bypass the protection but non-admin pushes (including the workflow'sGITHUB_TOKEN-authed push) hit the pre-receive hook. The defaultGITHUB_TOKENin Forgejo Actions does NOT have admin scope — so the cut-path push is blocked.This is the same class as #70 + #73 — slice 1b's
_release.ymlreusable assumes the workflow can push to main, which works when the consumer's repo has no branch protection but fails when the consumer enables it.Why slice 2's first-fire didn't catch this
Slice 2's first fire was
mode=noop— the act-step short-circuits before the push. The first content-having attempt silently dry-ran (#70). The second got past dry-run but failed at git commit (#73). Only THIS attempt (post-#70-fix + post-#73-fix) actually reached the push.Recovery (already done for v0.4.0 cut)
Manifest pushed manually as
quartermaster(admin; bypassesapply_to_admins: falseprotection) at commit595c10f. v0.4.0 draft release remains valid; operator's Gate 3 Publish click is the final step.The next workflow run (triggered by the manual manifest push) walks from
5f4812d..HEAD→ finds only the manifest commit →chore(manifest):is not release-relevant per cc → mode=noop. No loop.Proposed fix options for v0.4.1+
Three candidate surfaces:
release_token: <PAT>secrets.RELEASE_TOOLKIT_TOKEN;_release.ymluses it for the push if set, falls back toGITHUB_TOKENif notapply_to_admins:falsefor main, OR exemptforgejo-actionsfrom protection, OR use option (A)I lean (A) + (C): support a consumer-provided PAT for the substrate-mutation actions, document the branch protection compatibility matrix, and clearly explain when (A) is needed.
Sibling silent-failure-class lessons — same shape as #73 / #70
This is the THIRD instance of "slice 1b's
_release.ymlreusable didn't carry forward an implicit assumption from v0.3.x." Promotes the carry-forward class n=2 → n=3:Per
feedback_reusable_redesign_carry_forward_enumeration.md(banked at n=2), this is now n=3 for the carry-forward class. Empirical promotion-bar met. Surveyor / operator can decide if this warrants a named project pattern + ADR-class capture, or stays as the implementer pre-flight checklist memory entry.Refs
595c10f)feedback_reusable_redesign_carry_forward_enumeration.md— promotes to n=3 with this instanceFiled: 2026-06-25 from live cut-path catch (third dogfood surface in the v0.4.0 arc).