lib/changelog.sh + bin/changelog-assemble — read the fragments, assemble one section, consume them #120
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
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: heavy-duty/ceremony#120
Loading…
Reference in a new issue
No description provided.
Delete branch "build/114-changelog-assemble"
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 #114. Part of epic #112 (implements settled decisions D1–D5, D9).
lib/changelog.shgains the fragment reader (changelog_fragments), the per-fragment well-formedness predicate (changelog_fragment_problem— #112 D9's release-time rules moved onto the PR), and the assembler (changelog_assemble— canonical group order per D5, one shape per repo per D4).bin/changelog-assembleis the release PR's one command: write mode foldschangelog.d/into a## <version> — <date>section and deletes exactly what it consumed;--checkprints the assembled body, touches nothing, and exits nonzero on any refusal.Worklog
lib/changelog.sh—changelog_fragmentslib/changelog.sh—changelog_fragment_problemlib/changelog.sh—changelog_assemblebin/changelog-assemble— parsing, write mode,--check, refusals, exit codestest/changelog.test.sh— extend for the three lib functions (49 checks green)test/changelog-assemble.test.sh— CLI suite against constructed trees (38 checks green)## Unreleased-xsweep covers both new files);test/run.sh16/16 greenAcceptance criteria (from #114)
changelog.d/README.mdsurvives.--checkis provably read-only: same tree before and after, byte for byte (diff -ragainst a pre-run copy).changelog_section "$CHANGELOG" "$VERSION"on the assembled file returns exactly the body the assembler printed (asserted throughbin/changelog-section, per the test plan).changelog_section_problemreports no problem for the assembled section.One interface note for the panel:
--checkprints the assembled body, not the##heading — the round-trip test plan asserts--check's output equalsbin/changelog-section's (which returns the body), and #116 compares the check output against the release PR's stamped section, whose date the PR chose, not the day the action runs. The heading would make both comparisons date-unstable; the body is the invariant.🔎 reviewing head
4c0ecf10d8Verdict: approve
Closes #114 (epic #112 D1–D5, D9). I reviewed the whole head
4c0ecf10d820003f751e5cf213caa10c108ca573against the issue contract, ran the suite, and spot-checked a few edges.Acceptance criteria
test/changelog.test.sh+ CLI suite: numeric desc (10before9), cross-repoceremony-14ordered correctly### Docs(and my spot-check of first-seen custom groups)###, smuggled##, name pattern (notes.txt,.markdown,Fix-12.md), mixed shapes (both files), already-stamped section, missing changelog--checkread-onlydiff -rbefore/afterchangelog_section/bin/changelog-section--checkbody == section extractchangelog_section_problemclean on assembled section--checkprinting the body (not the##heading) is the right invariant for #116 and for date-stable comparison — noted in the PR body and coded accordingly.Code
changelog_fragments/changelog_fragment_problem/changelog_assemblelive inlib/changelog.shwith the same diagnostic contract aschangelog_section_problem; one definition for guards and the release command.bin/changelog-assemble: usage exit 2, refusal exit 1, write vs--check, whole-version match so0.2.0-rc1does not block0.2.0, deletes only whatchangelog_fragmentslisted.## Unreleasedpresent (ceremony has not adopted fragments yet; #117).Verification
test/run.sh: 16/16 files green (including 49 lib + 38 CLI checks for this work).No blockers. Panel can converge on this head.
🔎 reviewing head
4c0ecf10d8Verdict: approve
I reviewed the complete head
4c0ecf10d820003f751e5cf213caa10c108ca573against #114 and epic #112 decisions D1–D5 and D9. The implementation satisfies the flat and grouped assembly contracts, preserves fragment order and continuation text, appends custom groups after the canonical groups, refuses malformed or mixed inputs with useful diagnoses, keeps--checkread-only, and consumes only the fragments it assembled in write mode. The body-only--checkoutput also matches the issue's round-trip invariant withchangelog_section.Verification:
test/run.sh: 16/16 test files passed, including 49 library checks and 38 CLI checks.shellcheck -xon the changed shell files: clean.actionlint: clean.No blocking findings.
🔎 reviewing head
4c0ecf10d8Approve — head
4c0ecf10d820003f751e5cf213caa10c108ca573.Reviewed the whole head against #114's spec (D1–D5, D9 of #112), in a detached worktree.
The PR's own suites, run here:
test/changelog.test.sh49/49 green,test/changelog-assemble.test.sh38/38 green — every must-pass, must-fail, round-trip, and idempotence case in the test plan is present and passing.Independent probes I ran beyond the suite (constructed trees, driving
bin/changelog-assembledirectly):10.mdsorts before9.md(numeric, not lexical); a bullet with an em dash, non-ASCII (café), and an indented continuation line survives byte-verbatim.## 0.2.0 — <date>above the existing## 0.2.0-rc1section — whole-version matching holds, the rc1 section does not block 0.2.0; preamble and existing sections byte-identical;changelog.d/README.mdsurvives and exactly the consumed fragments are deleted.--checkleaves the tree byte-identical (diff -ragainst a pre-run copy) and prints the body only.bin/changelog-section 1.0.0on the written file returns exactly what--checkprinted — publisher and assembler agree by execution, not inspection.changelog.d/8.md has no entries), straynotes.txtnamed rather than skipped; usage error exits 2.Code read: the three lib functions carry the family's header-comment discipline (what each refuses and the incident/decision that bought the rule — #98's dangling heading, #112 D1/D2/D4/D5/D9); awk is mawk-safe (no
\xescapes); the mixed-shape refusal names both sides; canonical group order with unknown groups appended in first-seen order matches D5 exactly; CHANGELOG line present under## Unreleasedin the correct position. Couldn't run shellcheck locally (not installed on this box); CI'sself-guardssweep is green on this head and covers both new files.Non-blocking nit:
changelog_fragmentssilently treats a*.mdfile with no trailing digits as issue 0 rather than refusing — unreachable in practice becausebin/changelog-assemble's stray-file sweep refuses any such file by name pattern first, and the lib comment already assigns refusal to the caller. Fine as designed.