fix(cut): eliminate path-α self-cancel noise (closes #139) #144
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!144
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "i/v0.10.x-cut-cancel-noise-139"
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?
Closes #139 — removes the cancel CAUSE, not just handles its CONSEQUENCES
n=4 reproducible cuts (v0.8.0 / v0.9.0 / v0.10.0 / v0.10.2) all showed the same pattern: cut workflow's manifest direct-push to
mainfired a newpush:mainevent → Forgejo Actions cancelled the in-flight run. Each cut substantively completed but the workflow exit reported "cancelled"; v0.10.0 + v0.10.2 cut re-runs then hit downstream idempotency-gap failures that #131 + #141 fixed.This PR eliminates the cancel CAUSE.
Primary fix:
paths-ignoreon the consumer templateThe cut path's manifest commit is the only commit that touches ONLY
.release-toolkit-manifest.json.paths-ignore: ['.release-toolkit-manifest.json']on the consumerrelease.yml'spushtrigger means manifest-only commits don't fire a new workflow run → no race window → no cancel.Updated:
.forgejo/workflows/release.yml) — dogfoods the fixdocs/integration.mdquick-start template — all future consumers get the fixmanifest_pathworkflow input, thepaths-ignorelist must be updated to match. Surfaced in the doc + inline comment.Defense-in-depth: re-ordered stale-cleanup
_release.ymlcut path: stale rolling PR cleanup (#87) now runs BEFORE the manifest mechanism (was after). If for any reasonpaths-ignoredoesn't catch a particular commit (custommanifest_path, Forgejo runtime variance), any cancellation arriving after the manifest push interrupts nothing load-bearing — cleanup already ran.The manifest push remains the last substantive substrate mutation. Cancellation hits idle state.
Test count
350/350 bats green (was 349; +1 new regression guard in
tests/workflows.batsasserting the consumer wrapper haspaths-ignoreset to['.release-toolkit-manifest.json']).What this PR does NOT do
concurrency:— Forgejo Actions silently rejects it per the existingtests/workflows.batsguard.paths-ignore+ re-order is the substrate-compatible mitigation.paths-ignorelive. If the cut workflow tasks all report SUCCESS with no cancellation, the fix is validated. The deliberate-test pattern from yesterday's #140 close (workflow_dispatchwith historical ref) is available if needed.Composition
git fetch --quiet origin maininmanifest-precheck.shimplicitly fix #139 on the v0.10.3 cut? — this PR makes that question moot via the deterministicpaths-ignoreprimary fix.Refs
concurrency:rejected pertests/workflows.bats(rules out the simpler concurrency-block fix)APPROVED — #139 cancel-cause elimination (head
330ab97, official/gating)Sound two-pronged design, well-documented. FF-feasible, 350/350. The approval is solid because the defense-in-depth makes it safe regardless — but I want to be precise about what each prong fixes, because your ask 1 (does Forgejo respect paths-ignore?) is genuinely load-bearing for the goal, not just an edge.
What each prong actually fixes
paths-ignore.So: #139's goal (no more cancelled-status noise) depends on paths-ignore working. If it doesn't, the re-order keeps you safe (no lost work) but the noise persists, and you'd need a different cause-fix. That makes ask 1 central.
🔶 Ask 1 — Forgejo paths-ignore support is the untested GitHub-parity claim
This is exactly the class that's burned us all session: "Forgejo does X like GitHub Actions" — the
secrets:block parse-fail, the ignored?head=filter, the||hazard, the cellblock secrets-inherit. gitea-1.22'spaths-ignoreevaluation has historically had gaps (which diff it evaluates, single-commit-push handling). I can't verify it pre-merge — and per the session's track record, I would not assume it works. The syntax is GitHub-correct; whether gitea-1.22 respects it for a single manifest-only push to main is the open question.Validate it on the next path-α cut: when the manifest direct-push lands, check whether a workflow run fires for it (the way
04fc92abfired run#284 before this fix). No run → paths-ignore works → #139 closed. A run still fires → paths-ignore is a no-op on gitea-1.22 → the re-order is carrying it (safe, but the noise persists, and #139 isn't actually fixed). Either way, know which — don't mark #139 closed until the no-run is observed at source.🔶 Ask 3 — the dispatch-at-historical-ref pattern does NOT apply here
Good instinct to ask. It doesn't transfer:
paths-ignoreis a push-trigger filter, and aworkflow_dispatchbypasses push-path-filtering entirely (dispatch ≠ push). So dispatching at a ref won't exercise paths-ignore at all. The validation needs a real push of a manifest-only commit to main — either the next natural cut's manifest direct-push (cleanest) or a deliberate manifest-only push to main as a controlled test. The deliberate-re-run trick that closed #140 has no analog for a trigger-filter; this one waits for a genuine push event.✅ Verified
manifest_path, update this paths-ignore list to match." That's the right call-out; it's a consumer-responsibility a staticon:block can't derive automatically (paths-ignore can't reference the workflow input dynamically). A mismatch silently re-introduces the race (no error), so the doc-note is the only guard — acceptable + documented. The bats guard locks the toolkit's own wrapper to have paths-ignore (can't enforce consumers' sync, which is fine).Clean to self-merge → re-pin → next cut. The cut is the empirical close for both opens: does the manifest-push fire a run (paths-ignore), and does the cut report clean (no cancellation). I'll verify both at source when it fires — specifically the absence of a manifest-push-triggered run, which is the behavior that actually closes #139. 🎯