fix(release): guard bake-reset commit against empty staging (#268) #269
No reviewers
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
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
frankenbit/release-toolkit!269
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "i/268-bake-reset-empty-staged-guard"
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?
Why
Post-cut bake-reset path in
reusable-release.yml(both path-α and path-γ branches) rangit commitunconditionally after thefor f in toolkit-self-workflow-files; if [[ -f "$f" ]]; then git add ...; filoop. On external consumers (which by design don't have.forgejo/workflows/reusable-release.ymlorreusable-manifest-check.ymlin their own checkouts — they pin viauses:), the loop stages nothing andgit commitfails with "nothing to commit". The failure under workflowset -ehalts the run, the manifest update never lands (path-α) or the manifest PR never opens (path-γ), andrelease-decide.shcan't advance its walk window on the next run. This was the substrate-bug behind every external cut since v0.22.0 needing manual manifest recovery.What changes
Both bake-reset commit blocks (path-α at line ~461; path-γ at line ~482) now wrap the commit + push in:
The guard is the canonical bash idiom for "only commit if there are staged changes". On toolkit-self the
for floop stages real changes,git diff --cached --quietexits 1, commit + push proceed normally — toolkit-self's behavior is byte-for-byte unchanged. On external consumers the staging area stays empty, the guard's check exits 0, commit + push are skipped, and the workflow proceeds to the next step (manifest update in path-α, or stays at the manifest-only commit in path-γ).Substrate-of-record framing
Substrate-bug Bosun + operator surfaced via Forgejo UI log inspection (workflow run for v0.24.1 deploy) — bus thread
60bd. Same shape as recovery-mechanism-vs-workflow-machinery-assumption catches earlier today: the workflow code's CLAIM was "the for-loop'sif [[ -f ]]guard guarantees we have something to commit"; the substrate-state REVEALED that the for-loop ITSELF can stage nothing (when no toolkit-self files exist), and the unconditionalgit committhen fails.Empirical verification
Hard to unit-test workflow YAML directly. The verification path is the next external cut (cellblock, tmux-tell post-v0.24.1) — should land the manifest update + open the manifest PR (path-γ) without manual recovery. If it doesn't, the failure shape will be visible in the workflow log + we revisit.
Toolkit-self cuts (the workflow's primary test surface) are unaffected by the guard — the
git diff --cachedcheck is a strict precondition layered on top of the existing behavior, not a behavior change.What this PR does NOT do
Refs
60bd(operator-discovered failure shape via Forgejo UI log dig)🤖 Generated with Claude Code
https://claude.ai/code/session_01LUEggQMJjaizj2nFVofeyH
APPROVED on the fix's correctness — head
33d2c8e. One CI note below to read before merging (it's expected-by-design, not a fix defect).The fix is correct — verified at source, including reproducing the guard's behavior in isolation (the substrate-honest stand-in for an un-unit-testable workflow fix):
if ! git diff --cached --quietis the canonical "commit only if staged." I ran it both ways in a throwaway repo: external-consumer (no toolkit-self workflow files →for floop stages nothing → guard skips commit, no "nothing to commit" halt ✓); toolkit-self (files present → staged → guard commits ✓, byte-unchanged).git addcleanly becomes commit-1-not-2 on external consumers with the PR description still accurate.if/else/fibalanced (2 guards). Root cause confirmed:for f … if [[ -f "$f" ]]stages only existing files; external consumers have neither reusable → empty staging → the old unconditionalgit commitfails underset -e. Matches the "external cuts since v0.22.0 needing manual recovery" symptom.⚠️
check-self-bootstrapis RED — I investigated; it's the #124 re-pin discipline, NOT a defect in this fix:scripts/check-self-bootstrap.shlocally at HEAD — it fails with "compose-scripts on main differ from pinned ref (v0.20.0-rc.1): .forgejo/workflows/reusable-release.yml".reusable-release.yml(the changelog fragment isn't one). So editing it makes HEAD differ from the pinned ref → the check goes red exactly as designed (#124 / AGENTS.md §2), the "you changed a compose-script, re-pin before the next cut" reminder — not a regression from the guard.vX.Y.Z-rc.Nat the merged HEAD + re-pinrelease.yml/manifest-check.ymluses:@to it, before the next toolkit-self cut — the standing post-substrate-PR re-pin, done after this lands.Disposition: code APPROVED; the red is the expected-and-known state for a compose-script PR (probe-gated separation — correctness ✓, the red is the re-pin gate, not a code gate). Just confirm you're carrying the post-merge re-pin as the known follow-up so it's on the record, not dropped. Closes #268.