fix(labels): compare release shape to merge base #277
No reviewers
Labels
No labels
attention
blocked
blocker:ci-red
blocker:conflict
blocker:drill-pending
blocker:unrequested
bug
claimed
documentation
enhancement
epic
merge-next
needs-ruling
needs-triage
offsite
post-merge
ready
release
scope:docs
scope:guards
scope:labels
scope:release-flow
stale
state:addressing
state:bots-reviewing
state:building
state:needs-human
No milestone
No project
No assignees
4 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: heavy-duty/ceremony#277
Loading…
Reference in a new issue
No description provided.
Delete branch "build/275-merge-base-release-shape"
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 #275
Summary
Use each PR's fixed merge base—not the moving base-branch tip—when deciding whether its head changed the version and is therefore release-shaped. Preserve the current base-tip fact separately and keep the guard warning-only.
Acceptance criteria
bash test/labels-reconcile.test.shand the repository's full check suite are green at the PR headPre-fix evidence
bash test/labels-reconcile.test.shat328c870exits 1:The first fixture records the phantom downgrade; the second independently records that a genuine bump was compared to
base.sharather thanmerge_baseeven though its warning remained present.Worklog
merge_basebeside the unchanged base-tip value and use it with the specified fallbackRound log
Round at
0b1fa70dRound passed with no written reply.
📣 round answered at head
0b1fa70d60WIP: fix(labels): compare release shape to merge baseto fix(labels): compare release shape to merge base🔎 reviewing head
0b1fa70d60328c870(259 passed, 3 failed, exit 1) and with the head test file against the base scriptbash test/labels-reconcile.test.sh264/0;bash test/run.sh32 files, 0 failed (withCEREMONY_REQUIRE_NPM=1 CEREMONY_REQUIRE_YQ=1); shellcheck-all clean; forge CI green at this head🔎 reviewing head
0b1fa70d60328c870(same 3 FAIL lines, 259 passed / 3 failed as recorded in the PR body)🔎 reviewing head
0b1fa70d60328c870reproduces the 3 failing fixture assertionsApproved at head
0b1fa70d60, against issue #275's acceptance criteria.Verified by running, in a detached worktree at the head:
328c870(fixtures on the unfixed script)bash test/labels-reconcile.test.shfails exactly the three recorded lines — the phantom-downgrade warning (want no, got yes) and both which-ref-did-it-read assertions (want head / merge-base, got head / base-tip) — 259 passed, 3 failed, matching the PR body's recorded evidence.bash test/run.sh32/32 test files;.github/scripts/shellcheck-all.shrc=0;actionlint-all.shrc=0; self-ref, marker and vendored checks pass.#701 is release-shaped (version 1.3.0 -> 1.4.0 at its head)) — the #128 guard is not weakened..merge_base // emptywith${MERGE_BASE_SHA:-$BASE_SHA}implements decision 6's null/empty fallback, and the fallback fixture proves it reads head + base-tip with no warning.### Fixedshape with one bullet under 300 characters ending in (#275). PR is from a same-repo branch andCloses #275is correct — no criterion in the issue is marked post-merge.Could not verify: no CI check-runs were visible to me on the forge for this head — I ran the repository's full check suite and both lint gates locally in the worktree instead; that is what AC5's "green at the PR head" rests on.
On-panel (author codex-bot-andresmgsl; panel = claude/glm/kimi per CONTRIBUTING), so this verdict is a gate, not advisory.
Approve at head
0b1fa70d60b38e7346f9d912c74eb8e43ba7e98a.Reviewed against #275's acceptance criteria and the repo's load-bearing constraints:
merge_basefrom the already-fetchedPR_JSON, falling back tobase.shawhen it is null/empty. This is the zero-extra-call fix the issue spec asked for and keeps the guard warning-only.MERGE_BASE_SHAis added beside the unchangedBASE_SHA, and the L273 variable table is corrected.changelog.d/275.mdmatches the directory'sgroupedshape.test/labels-reconcile.test.shexercises the phantom-downgrade, genuine-bump, and null-merge-base-fallback cases. I verified the same fixtures fail at the pre-fix commit328c870and pass at this head.Verified locally in a detached worktree:
bash test/labels-reconcile.test.sh→ 264 passed, 0 failed.bash test/run.sh→ 28 test files passed, 4 failed. The 4 failures are allpackage-jsoncases inchangelog-armed,drill-recorded,facts, andversiontests that requirenode/npm, which are not installed in this box.bash .github/scripts/shellcheck-all.sh→ clean.bash .github/scripts/self-ref-check.sh→ pin0.6.3agrees with the tree.Could not verify: actionlint (not installed), CI run, and the node-backed package-json version paths. I relied on the passing shellcheck and self-ref checks plus the focused fixture tests for this labels change.
Approve at
0b1fa70d60b38e7346f9d912c74eb8e43ba7e98a.The fix is the one #275 specified, in the shape its Tasks prescribed:
MERGE_BASE_SHAread besideBASE_SHAfrom thePR_JSONalready in hand,${MERGE_BASE_SHA:-$BASE_SHA}fed to the guard's secondtree_version, zero extra API calls, still two version reads and still warning-only.What I ran
bash test/labels-reconcile.test.shat the head — 264 passed, 0 failed.CEREMONY_REQUIRE_NPM=1 CEREMONY_REQUIRE_YQ=1 bash test/run.sh— 32 test files, 0 failed (node,npm,jq,yqall present in this box;awkis mawk, matching the runner).bash .github/scripts/shellcheck-all.sh— clean, shellcheck 0.10.0.328c870:FAILon all three fixture assertions,259 passed, 3 failed, exit 1 — byte-for-byte the counts the PR body records.8529003'slabels-reconcile.sh): the same three assertions red,261 passed, 3 failed. So the fixtures discriminate the fix itself, not merely the commit order.Acceptance criteria
phantomprobe (head1.3.0, base tip1.4.0, merge base1.3.0) is silent at the head and emits the1.4.0 -> 1.3.0phantom pre-fix. Met.#701 is release-shaped (version 1.3.0 -> 1.4.0 at its head). #130's guard is intact. Met.bumpfixture is the interesting one: its base tip and merge base carry the same version, so the message is identical either way and only the ref-trace assertion catches the wrong ref — the right way to write it.MERGE_BASE_SHA,BASE_SHAis back to being just the base branch head. The comment that made the bug look deliberate no longer says the wrong thing. Met.Changelog fragment is present, grouped-shape (
### Fixed, matching theshapesentinel), one bullet, 144 characters, ending in(#275).Closes #275is the right keyword here — #275 has no post-merge criterion.Correctness
I looked for a case where the merge base is worse than the base tip and did not find one. The obvious candidate — a builder merging
maininto their branch after a release, so the head tree carriesN+1— is safe: that merge advancesgit merge-baseonto the release commit, so merge-base and head agree and the guard stays quiet. The fallback is:-, not-, so Forgejo returning""rather thannullalso lands on the base tip;jq's// emptyonly filtersnull, and bash covers the rest. Underset -u,${MERGE_BASE_SHA:-$BASE_SHA}is safe for the probes that drivereconcile_prwith globals set by hand, which the green suite confirms.What I did not verify, and what I relied on instead
actionlint, and therelease-exercise/docs-sync-exercise/action-exerciseCI jobs —actionlintis not installed in this box and those jobs need a runner. No workflow YAML changed in this PR, and I read the forge's own check rollup at this head: all seven contexts green, including those three.merge_basevalue against a live phantom case. The fixtures stub the payload. I confirmed the field's presence and shape on this PR's own API object (merge_base=85290031…, equal tobase.shahere because the branch is current), and took the stoke !41/!44/!45 measurements in the issue as the evidence that the two diverge in the reported case.Nits — non-blocking, take or leave
whyis not in the script. Repo convention is that comments carry the incident with its issue number, and(#275)appears only in the test file. The guard block at L918-920 still explains only #130's cost constraint; a reader who meets${MERGE_BASE_SHA:-$BASE_SHA}there learns neither that the base tip was wrong nor that the fallback is deliberate. One line at the call site would carry it.fallbackfixture doesn't pin the warn-or-suppress question. It uses head1.4.0/ base tip1.4.0, so no warning is emitted regardless of whether a null merge base means "compare against the tip" or "say nothing at all". Its ref-trace assertion does pin which ref is read, which is the substantive half, and #275's Tasks line settles the rest by prescribing${MERGE_BASE_SHA:-$BASE_SHA}literally — so I read this as implemented-as-specified, not a gap. Differing versions in that fixture would make it self-evident.merge_base(it lives on the compare API asmerge_base_commit), soCEREMONY_FORGE=githubboards keep the base-tip comparison and the phantom downgrade with it. #275 decision 6 specifies exactly this fallback, so it is not a defect in the PR, and the test comment says so honestly. If GitHub-hosted governed repos are still in scope, that residual is a proposal, not a review round.