fix(workflow): insert ### Changed in Keep-a-Changelog order on auto-CHANGELOG#63
Conversation
The auto-CHANGELOG composer's inline Python previously inserted a newly-created ### Changed block at unreleased_idx + 1, which placed it above any existing ### Added (or other earlier-sorting subsection) inside ## Unreleased. Per Keep a Changelog v1.1.0 the canonical subsection order is: Added → Changed → Deprecated → Removed → Fixed → Security The bug manifests when ## Unreleased already contains a non-Changed subsection and the next Dependabot PR creates a fresh ### Changed. Dormant on this repo right now because ## Unreleased has both subsections; would manifest after the next release ships and a feature PR adds ### Added to the fresh Unreleased section before any Dependabot bump. Fix: in the else-branch (the "create ### Changed" path), walk forward from ## Unreleased looking for the first ###-prefixed subsection that should sort AFTER ### Changed (Deprecated, Removed, Fixed, or Security), OR the next ## release heading. Insert immediately before whichever comes first. Default insertion point is the end of the Unreleased section. Existing ### Changed-found path is unchanged. Smoke-tested locally against five CHANGELOG arrangements: - Empty Unreleased (no subsections) - ### Added only (the dormant-bug case) - ### Changed already exists (existing path) - ### Added AND ### Fixed (no Changed) - ### Fixed only All five produce correctly KaC-ordered output. Test harness output preserved in the PR body. Surfaced by claude-qa during review of the cascade in cmeans/pypi-winnow-downloads (issue #26 there). The pypi-winnow-downloads cascade waits for this fix per the playbook's verification gate (one repo first, validate, then cascade).
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
cmeans
left a comment
There was a problem hiding this comment.
QA Round 1 — PR #63
This is a model example of cross-repo review catching what same-repo review missed. The bug existed in #58's workflow shipped on this repo but was dormant — caught during cascade review on cmeans/pypi-winnow-downloads#26 because that repo has a CHANGELOG arrangement (### Added only at the moment) that would trigger it. Good.
Verification on e70ad58
| Check | Result |
|---|---|
python3 yaml.safe_load(...) |
parses |
uv run pytest |
499 passed, 94 deselected, 96.04% coverage |
| Required CI rollup | all green (lint, typecheck, test 3.11/3.12/3.13, version-sync, validate-server-json, vdsm) |
| CHANGELOG entry placement | under ### Fixed ✓ correctly categorized |
Cross-reference to cmeans/pypi-winnow-downloads#26 |
present in CHANGELOG entry and PR body ✓ |
Existing-### Changed-found path |
unchanged (only the create-new-Changed branch was modified) ✓ |
Independent smoke test (extending Dev's five cases)
Ran the new algorithm locally against six CHANGELOG arrangements:
| Case | Input shape (Unreleased section) | Resulting ### Changed placement |
KaC-correct? |
|---|---|---|---|
| A | Empty Unreleased | At end of Unreleased | ✅ |
| B | ### Added only (the bug case) |
Added → Changed |
✅ |
| D | ### Added + ### Fixed |
Added → Changed → Fixed |
✅ |
| E | ### Fixed only |
Changed → Fixed |
✅ |
| G | ### Deprecated only (not in Dev's table) |
Changed → Deprecated |
✅ |
| H | ### Added + ### Deprecated (not in Dev's table) |
Added → Changed → Deprecated |
✅ |
All six produce KaC-correct ordering. The two extras (G and H) extend coverage to the Deprecated subsection that Dev's table didn't exercise.
Observations on the algorithm
The after_changed set {"### Deprecated", "### Removed", "### Fixed", "### Security"} is correct per KaC v1.1.0. The default fallthrough (insert_at = end_idx) places new ### Changed at the end of Unreleased when no later-sorting subsection exists, which produces the right result for cases A and B (the trailing position is after ### Added, before next ## heading).
Non-canonical subsection names (e.g., ### Improved) would be treated as before-Changed by virtue of not being in after_changed. This is acceptable because the project rule (per feedback_changelog_categories.md / CLAUDE.md) prohibits non-canonical KaC categories, so this case shouldn't occur in well-formed CHANGELOGs.
Verdict
Ready for QA Signoff. No findings. QA Approved remains the maintainer's call.
Maintainer reminder (already in test plan, post-merge): update awareness dependabot-pr-hygiene-playbook entry (c523d239) to record the fix.
QA audit — round 1Branch / SHA: `fix/dependabot-changelog-kac-ordering` @ `e70ad58` Independent smoke test results — extracted the new algorithm from the workflow and ran six KaC arrangements: ``` All six produce KaC-correct order. G and H extend coverage past Dev's table. Local stack: Outcome: Ready for QA Signoff. No findings. `QA Approved` remains the maintainer's call. |
Summary
Closes a dormant subsection-ordering bug in
.github/workflows/dependabot-changelog.ymlsurfaced by claude-qa during review of the cascade PR incmeans/pypi-winnow-downloads(issue #26 there).The auto-CHANGELOG composer's inline Python previously inserted a newly-created
### Changedblock atunreleased_idx + 1, which placed it ABOVE any existing### Added(or other earlier-sorting subsection) inside## Unreleased.Per Keep a Changelog v1.1.0 the canonical subsection order is: Added → Changed → Deprecated → Removed → Fixed → Security.
Bug manifests when
## Unreleasedalready contains a non-Changed subsection and the next Dependabot PR creates a fresh### Changed. Currently dormant on this repo because## Unreleasedhappens to have both### Addedand### Changed. Will manifest after the next release ships and a feature PR adds### Addedto the fresh Unreleased section before any Dependabot bump.Fix
In the else-branch (the "create
### Changed" path), walk forward from## Unreleasedlooking for the first###-prefixed subsection that should sort AFTER### Changed(Deprecated, Removed, Fixed, or Security), OR the next##release heading. Insert immediately before whichever comes first. Default insertion point is the end of the Unreleased section.The existing-
### Changed-found path is unchanged.Smoke test
Algorithm verified locally against five CHANGELOG arrangements:
### Changedplacement### Changedcreated at end of Unreleased### Addedonly (the dormant-bug case)### Added, before next release### Changedalready exists### AddedAND### Fixed, no Changed### Addedand### Fixed### Fixedonly, no Changed### FixedOutput for case B (the actual bug):
Verification gate
This is a fix to existing inline-Python parsing logic, not new infrastructure. Smoke-tested algorithmically against all five KaC arrangements. The bug is dormant on
main's currentCHANGELOG.mdso the natural-data verification path is "next release + feature PR adds### Addedfirst + Dependabot bump after" — which won't happen for some time. Algorithm correctness via the smoke test is the working verification.Cascade
Per the
dependabot-pr-hygiene-playbook(awarenessc523d239) verification gate, the cascade tocmeans/pypi-winnow-downloadswaits for this fix to land here first. After merge, the cascade PR there picks up the same change.Test plan
python -c "import yaml; yaml.safe_load(open('.github/workflows/dependabot-changelog.yml'))"— YAML parses### Changed-found path is unchanged (case C)## Unreleased→### Fixedreferences this PRcmeans/pypi-winnow-downloads#26referenced in commit body and CHANGELOGdependabot-pr-hygiene-playbook(c523d239) to record the fix and remove the dormant-bug warning if any