feat: enforce CHANGELOG.md on release commits - #11
Conversation
- Add changelog-guard to lefthook: requires CHANGELOG.md staged on release/v* branches, blocks it on all other branches - Switch cargo-dist changelog source from git-cliff (CI) to CHANGELOG.md (committed with the release) — no CI git history dependency - Update RELEASING.md to document the new 'just changelog' step
Greptile SummaryThis PR completes the release-tooling overhaul by introducing a
Confidence Score: 4/5Safe to merge; the single open issue is a cosmetic stdout leak in an edge-case path that does not affect correctness. The core logic is sound: the guard correctly enforces the single-commit release workflow and the fallback for second commits works as intended. The only finding is the missing
|
| Filename | Overview |
|---|---|
| .config/lefthook.json | Adds changelog-guard pre-commit hook; logic is correct for the primary release flow with a minor stdout-leak in the tracked-but-unstaged fallback path. |
| dist-workspace.toml | Switches changelog from "git-cliff" (runtime invocation requiring full history) to "CHANGELOG.md" (reads pre-generated file); straightforward and correct. |
| RELEASING.md | Documentation updated to reflect the new just changelog step and removal of git-cliff from CI; accurate and clear. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[git commit] --> B{branch?}
B -- "release/v*" --> C{CHANGELOG.md staged?}
C -- yes --> G[allow commit ✅]
C -- no --> D{CHANGELOG.md tracked\nand unmodified?}
D -- yes --> G
D -- no --> E[❌ error: run just changelog]
B -- "other branch" --> F{CHANGELOG.md staged?}
F -- yes --> H[❌ error: do not commit CHANGELOG.md here]
F -- no --> G
Prompt To Fix All With AI
This is a comment left during a code review.
Path: .config/lefthook.json
Line: 15
Comment:
**`git ls-files` emits filename to stdout**
`git ls-files --error-unmatch CHANGELOG.md 2>/dev/null` only redirects stderr. When `CHANGELOG.md` is tracked, the command prints `CHANGELOG.md` to stdout, which lefthook will surface to the developer. This is harmless but confusing — they'll see a bare `CHANGELOG.md` line printed during the pre-commit hook on a second release-branch commit.
Add `>/dev/null` alongside `2>/dev/null` to suppress it.
```suggestion
"run": "branch=$(git rev-parse --abbrev-ref HEAD); case \"$branch\" in release/v*) if git diff --cached --name-only | grep -q '^CHANGELOG.md$'; then :; elif git ls-files --error-unmatch CHANGELOG.md >/dev/null 2>/dev/null && ! git diff --name-only -- CHANGELOG.md | grep -q '^CHANGELOG.md$'; then :; else echo \"error: CHANGELOG.md must be staged on release branches (run: mise exec -- just changelog)\"; exit 1; fi;; *) if git diff --cached --name-only | grep -q '^CHANGELOG.md$'; then echo \"error: CHANGELOG.md must not be committed on non-release branches\"; exit 1; fi;; esac"
```
How can I resolve this? If you propose a fix, please make it concise.Reviews (2): Last reviewed commit: "fix(changelog-guard): allow follow-up co..." | Re-trigger Greptile
When CHANGELOG.md is already tracked and unmodified, subsequent commits on a release/v* branch no longer require re-staging the file.
Summary
changelog-guardto the lefthookpre-commithook — mirrors the existingversion-guardpattern:release/v*branches: fails ifCHANGELOG.mdis not staged (runjust changelogfirst)CHANGELOG.mdis staged (keeps it offmain)dist-workspace.tomlfromchangelog = "git-cliff"(CI invocation, required full git history) tochangelog = "CHANGELOG.md"(reads the pre-generated file from the release commit — works with shallow clone)RELEASING.mdto document thejust changelogstepSupersedes
Closes #10 — the
fetch-depth: 0workaround is no longer needed.Release flow after this PR
🤖 Generated with Claude Code