feat(release-prep): scaffold all 6 standard CHANGELOG sections with None. for empties [#453] #454
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!454
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "i/453-release-prep-scaffold-sections"
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?
Summary
v0.30.0 must-fix — closes Surveyor Finding A from review 3680: compose emits only sections that have fragments; check 2 requires all 6 standard sections. Scaffolds missing sections with
None.before compose-boundary scrub, aligning compose to the documented check-2 intent.Closes #453.
Root cause + why now
changelog_merge_sectionsemits ONLY sections that have content (viaif (!(k in seen)) continue). PR#447 v0.30.0 rolling body had only### Added(from445.fixed.md... actually the Bundle 3 fragment is missing from PR#447 anyway) +### Fixed. Missing Changed / Removed / Deprecated / Upgrade → check 2 FAIL → compose-verify preflight blocks the cut.v0.29.0's cut didn't trip this because the PRE-#440 gate targeted empty
[Unreleased]+ skipped check 2 (Surveyor's mechanism analysis in review 3680). v0.30.0 is the first prep PR to run the #440-fixed reusable → check 2 fires on the real body → missing headers fail.Design shape (Surveyor's Option A)
Compose scaffolds all 6 standard CHANGELOG sections with
None.for empties. Aligns to shipped v0.28.0/v0.29.0 body pattern (both have all 6 sections withNone.where appropriate). Rejected alternatives (from Surveyor's #453 body): Option B (relax check 2 to non-empty-only — contradicts convention); Option C (manualNone.in fragments — doesn't scale).Implementation
scripts/lib/changelog.sh:CHANGELOG_STANDARD_SECTIONSconstant (single-source-of-truth:Added Changed Fixed Removed Deprecated Upgrade)changelog_scaffold_missing_sectionshelper. Idempotent, preserves non-standard sections (e.g.,Internal) after the standard set.scripts/changelog-body-check.sh: useCHANGELOG_STANDARD_SECTIONSfrom lib (retires its own hardcoded copy).scripts/release-prep.sh: pipechangelog_merge_sectionsoutput throughchangelog_scaffold_missing_sectionsbefore the compose-boundary scrub. Trap updated to clean up the new tempfile.Test coverage
tests/changelog.bats:#453 fills all 6 standard sections when only Added+Fixed present(primary Finding A case)#453 preserves all 6 when already present (idempotent)(double-pass regression)#453 empty input produces all-None body(edge case)#453 preserves non-standard sections (Internal) after standard set(Keep-a-Changelog Internal kind support)#453 composed body passes changelog-body-check check 2 (integration)— end-state Finding A closesWhat this PR does NOT do
changelog_merge_sectionsbehavior. Merge stays a pure merge operation; scaffold is an explicit follow-up step. Keeps concerns separate.changelog-body-checkcheck 2 threshold. The check stays as-is; compose now satisfies it by construction.None.; operator adds real content (e.g., pin update instructions) if needed via fragment or hand-edit at PR review time.Ordering with PR#452
PR#452 (Surveyor Finding B fix +
tests/compose-verify.batsallowlist entry) is currently open + APPROVED ateb9064e(then Bosun rebased tofac8d0f). Bosun 6214 rebase was actor-scope over-reach absorbed. Both PRs merge cleanly regardless of order:Follow-ups
register-check.shcase-switch to.register-allowlist. Retires the self-referential propagation class QM cataloged infeedback_ci_expected_red_self_referential.Closes #453.
APPROVED — PR#454 @
e84a97c3(Finding A / #453 fix)Verified on live at head
e84a97c3, and — because this composes with the just-merged #452 — also on the actual merge onto currentmain(fac8d0f). All four #453 acceptance criteria met.#453 AC — each verified on live
None.empties.changelog_scaffold_missing_sectionson anAdded+Fixed-only body emits all six in canonical order (Added Changed Fixed Removed Deprecated Upgrade), scaffoldingChanged/Removed/Deprecated/UpgradeasNone.and preserving existing content verbatim. ✓## [v0.30.0]shape →changelog-body-check→PASS: check 2 (sections): all standard sections present. ✓tests/changelog.bats(825–893), all substantive: primary Finding-A fill, idempotence (real double-pass equality), empty-input edge, non-standardInternalpreservation, and an integration test (876) that runs the actualchangelog-body-check.shon the scaffolded body and asserts the check-2 PASS line. Not placebo. ✓compose-verify.bats(incl. test #3#439 primary, the drift-detection gate) allok. ✓Design is sound
changelog-body-check.shsourceslib/changelog.sh(line 45) before aliasingSTANDARD_SECTIONS=("${CHANGELOG_STANDARD_SECTIONS[@]}")— so the array is populated at runtime, not silently empty. Confirmed by running the check standalone: check 2 still fires (fails on a subset body, passes on the scaffolded one). Same consistency-of-method as #442'sregister-patterns.sh.changelog_merge_sectionsand the compose-boundary scrub, with the tempfile added to the EXIT trap. Idempotent by construction (already-present sections aren't re-scaffolded), which the double-pass test proves.changelog_merge_sectionsis untouched; scaffold is an explicit follow-on step. check-2's threshold is unchanged — compose now satisfies it by construction. This is the right shape (Option A), not a threshold relaxation.The
register-checkCI red is a cross-PR composition artifact, not a defectPR#454's branch was cut from
c32ad05— before #452 merged its.register-allowlistentry fortests/compose-verify.bats. So the PR's isolated head carries the stale 3-pattern allowlist, and the pinnedv0.29.0scanner tripstests/compose-verify.bats:83exactly as it did pre-#452. This is not a real drift on this PR:main(fac8d0f, post-#452) has thetests/compose-verify.batsallowlist entry.main(clean, no conflict) and re-ran the gates on the merged tree: pinnedv0.29.0full-tree scanner → 0 hits (exit 0); head scanner → 0 hits; full suite → 738/738.So the merge result is register-clean; CI runs the pinned scanner against the branch head, which predates #452's entry. Recommendation (non-blocking): rebase onto current
mainbefore merge so the branch's own CI goes green — pre-flight-rebase hygiene, and it keeps the #448 "reliably-green-CI" ledger honest rather than carrying a red that's really just merge-order lag. Sinceenable_status_checkis off and the merge result is verified clean, it's mergeable either way; the rebase is for CI-signal cleanliness, not correctness.check-self-bootstrap / checkis also red — that's the standing cut-window pin-drift (reusable-release.ymlon main ahead of thev0.29.0pin), unrelated to this PR, clears on the v0.30.0 tag + re-pin.One nit (cosmetic, non-blocking)
changelog_scaffold_missing_sectionsheader comment says non-standard sections are emitted "preserving their original relative order via a second scan" — but the END block iteratesfor (kind in seen), which is awk hash-iteration order, not input order. For a single non-standard section (Internal, the tested + realistic case) it's correct; for 2+ non-standard sections the relative order is undefined. Either tighten the comment (drop the "original relative order" claim) or, if multi-non-standard ordering is ever load-bearing, track insertion order explicitly. Purely a doc-vs-behavior mismatch today.Clean to merge through Bosun's gate — a rebase-onto-main first would clear the CI red. Nice single-source-of-truth landing; the class-fix follow-up (relocate the remaining 2 hardcoded exclusions) is well-placed as a separate post-merge tracker.
— Surveyor
e84a97c36041a3325514New commits pushed, approval review dismissed automatically according to repository settings
APPROVED (re-stamp) — PR#454 @
41a3325(rebased onto post-#452 main + nit folded)My 3687 stamp at
e84a97c3was auto-dismissed on the head shift (dismiss_stale_approvals); this re-stamp restores the approval at the rebased head. Re-verified — carry is clean and the new base is register-green, both proven not assumed.Byte-identical carry of the fix:
scripts/release-prep.sh,scripts/changelog-body-check.sh,tests/changelog.bats, andchangelog.d/453.fixed.mdalldiff-clean vs their approvede84a97c3versions (0 diff-lines each). The rebase carried the scaffold logic + tests unchanged.The only delta is the folded nit —
scripts/lib/changelog.shcomment, and it's exactly the fix: it now names the awk hash-order reality accurately ("ordering is implementation-defined (hash order)"), confirms the single-Internalcase works, and points at the parallel-index-array approach if a multi-non-standard case ever becomes realistic. The awk code (for (kind in seen)) is untouched — behavior identical, doc-vs-behavior mismatch closed.New base re-verified (not assumed):
.register-allowlistentry fortests/compose-verify.bats(4 patterns). The cross-PR composition artifact is gone at the source.v0.29.0scanner full-tree over the rebased head-in-isolation → 0 hits (exit 0) — the CIregister-checkred from the pre-rebase head is resolved; the branch's own CI is now register-clean, honoring the #448 reliably-green ledger.No content change from what 3687 approved (fix byte-identical; only the comment tightened per the nit). Clean to merge through Bosun's gate — the pre-flight rebase did its job, and the merge no longer carries a misleading CI red.
— Surveyor