actions/changelog-assembled — the release PR's section must be exactly the fragments it consumed #124
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#124
Loading…
Reference in a new issue
No description provided.
Delete branch "build/116-changelog-assembled"
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 #116.
actions/changelog-assembled— the third git-aware guard onchangelog-monotonic's reasoning: "the section matches the fragments it consumed" is a property of a diff, not a tree, because the fragments are gone from HEAD by construction. The guard readschangelog.d/as of the merge base, replaysbin/changelog-assemble --checkover that exact set, and compares byte-for-byte againstchangelog_sectionon HEAD. It applies only to the ceremony PR (fragment mode at the base, bare version on HEAD, section not yet stamped at the base); every other tree is a green NOTICE, never a silent skip; an unresolvable base under the fail-closed switch CI sets is a red, matching monotonic's stance and itsfetch-depth: 0requirement.Acceptance criteria
-devPR → green NOTICE, whatever it does tochangelog.d/.changelog.d/at the merge base) → green NOTICE, always.Worklog
actions/changelog-assembled/changelog-assembled.sh— applicability gates (vacuous, legacy,-dev, already-stamped-at-base), the merge-base replay, the three refusals (diff, surviving fragment, absent section), fail-closed strictactions/changelog-assembled/action.yml— inputsbase-ref,changelog,fragments-dir,version-source,strict, mirroring the sibling guardstest/changelog-assembled.test.sh— constructed git repos: the green rows, the red rows, the trio interaction row, env wiring (34 checks).github/workflows/ci.yml— self-guards runs the new action## Unreleased, above the entry below it🔎 reviewing head
185fc39b96🔎 reviewing head
185fc39b96Approve
Reviewed head
185fc39b964118c35c72e2cc69c44d8730acfc45against #116's acceptance criteria and the repo's guard conventions.Spec / AC
Every criterion in #116 has a constructed-repo row that exercises the intended outcome:
faithful-flat,faithful-groupeddropped(Nine landed+ survivor path)vanishededited(+++,allegedly, redo-with-tool remedy)reorderedsurvivor-devPR → NOTICEordinary-add/none/delchangelog.d/at base) → NOTICElegacyno-base,plainold-date(stamp2020-01-01)The trio interaction row is present and is the issue's whole argument: on the dropped-entry tree armed and monotonic stay green; only assembled goes red.
Out of scope here and correctly left to #117:
docs/CONSUMERS.md+ README guard list.Implementation
changelog-armed(property of a diff, not a tree) — matches the issue and monotonic's reasoning.-dev, already-stamped-at-base), not silent skips; vacuous (merge base IS HEAD) is named.STRICTmirrors monotonic (action default"1", script local default"0"); unresolvable base namesfetch-depth: 0.git ls-tree/git showat the merge base; compares assembler--checkbody againstchangelog_sectionon HEAD (date never enters). Survivors, absent section, assemble refusal, and byte mismatch are separate refusals with actionable messages.action.ymlinputs match the sibling guards' names (base-ref,changelog,strict) plus the ones this check needs (fragments-dir,version-source).self-guardsruns the action under the existingfetch-depth: 0checkout.## Unreleased, above the prior entry (monotonic-safe insert).Verified
bash test/changelog-assembled.test.sh— 34 passed, 0 failedbash test/run.sh— 17/17 files greenshellcheck -x actions/changelog-assembled/changelog-assembled.sh— cleantest,self-guards, action/release exercises, labels)No blocking issues. Non-blocking: none worth holding the round for.
The implementation satisfies #116 at
185fc39b964118c35c72e2cc69c44d8730acfc45. It reconstructs the merge-base fragment set, replays the shared assembler, compares the extracted HEAD section body byte-for-byte, reports unified differences, rejects surviving fragments and missing sections, and preserves the specified NOTICE/fail-closed applicability behavior. The action wiring uses the required inputs and CI runs it beside the existing changelog guards with full history; the behavior change also has an Unreleased entry.Verified locally:
bash test/run.sh— 17/17 test files passed, including all 34changelog-assembledchecks and the three-guard interaction cases.bash .github/scripts/shellcheck-all.sh— 37 tracked scripts clean.bash .github/scripts/actionlint-all.sh— 6 workflow/action files clean.git diff --check 6ec9aa24fac2d93324b02e8a7a5a54c6e2612265...HEAD— clean.GitHub's current check runs for this head are complete and green (with the expected conditionally skipped release jobs). No blocking findings.
🔎 reviewing head
185fc39b96Review: PR #124 — actions/changelog-assembled (head
185fc39)Verdict: APPROVE
Reviewed against
Closes #116in a detached worktree at185fc39b964118c35c72e2cc69c44d8730acfc45(merge base6ec9aa2).Acceptance criteria (issue #116), one by one
All ten are exercised by rows in
test/changelog-assembled.test.sh, which I ran: 34/34 pass.faithful flatandfaithful groupedrows pass.the dropped-entry diff names the missing entrypasses; the survivor row also listschangelog.d/9.mdby path.a deleted fragment whose entry never landed failspasses.+++, the edited word, and the "never to hand-edit" guidance — pass.re-ordered entries failpasses (the suite hand-builds the section with 9 before 12).STILL PRESENTrows pass, both when the entry is missing and when it is present.-devPR → green NOTICE whatever it does tochangelog.d/: three rows (add / no-op / delete) pass.changelog.d/at the merge base) → green NOTICE: passes, on a release tree.fetch-depth: 0as the fix.old-daterow stamps2020-01-01and stays green; the mechanism is sound —--checkprints the body only andchangelog_sectionextracts below the heading, so no heading (or date) ever enters the diff.The issue's headline interaction row is in the suite and passes: on the dropped-entry tree,
changelog-armedandchangelog-monotonicstay green and this guard is the only red.Issue tasks
changelog-assembled.sh,action.yml, the test file, and theci.ymlstep (withfetch-depth: 0already present) are all present. Theaction.ymlinputs (base-ref,changelog,fragments-dir,version-source,strict) mirror the sibling guards' names and defaults exactly — I diffed them againstchangelog-monotonic/action.ymlby hand, including the strict default "1" in the action vs "0" in the script.What I ran
bash test/changelog-assembled.test.sh— 34/34 pass.bash test/run.sh— the new suite is green; 7 pre-existing files fail identically at the merge base (verified by re-running the same suites onmainat6ec9aa2: version 3, facts 2, drill-recorded 2, changelog-armed 2, issueflow-reconcile 11, ruling 43 failures). All are environmental on this box (nonode/npmfor the package-json cases; gh-mock-dependent reconcile suites), not caused by this PR..github/scripts/shellcheck-all.sh(37 tracked scripts) and.github/scripts/actionlint-all.sh(6 workflows) — both clean. (actionlint againstaction.ymldirectly misfires, which is why the sweep deliberately lints workflows only.)-devversion, HEAD with the real assembler's write-mode edit): green,exit=0. I also confirmed the trailing blank line between the stamped body and the next heading does not false-positive — command substitution strips trailing newlines on both sides of the diff symmetrically.Adversarial probes beyond the suite
notes.txtinchangelog.d/at the merge base: the replay extracts it (strays included) and the run goes red with the assembler's own refusal — exactly what a real ceremony over that tree would have done. Fail-closed in the right direction.rig-66.md) consumed by a faithful ceremony: green.git showunderset -e, or a byte diff), never to a false green. Not worth changing.Conventions
set -euo pipefailin the executable,set -uin the test, mawk-compatible awk (ran under mawk 1.3.4), whole-version$2 == vermatching throughout, one CHANGELOG.md line under## Unreleased, and the header comment carries the why (#116, #112, #114) including why this cannot live inchangelog-armed. The guard is its own file with its own driving test, per the repo's one-piece-of-logic-per-file rule.Non-blocking nit: the success line and the refusals are all well-worded, but the "already stamped at the merge base" NOTICE fires before any fragment work, so a branch sitting on an un-rearmed release with genuinely new fragment changes also gets the NOTICE — correct per the spec (it is not the ceremony), just worth knowing the NOTICE is doing double duty there. No action needed.