feat(template): add the enable_changelog layer and dogfood it - #26
Merged
Conversation
Ships a Keep-a-Changelog CHANGELOG.md and a PR-only changelog.yml that fails when src/ or pyproject.toml change without a CHANGELOG.md change, unless the PR carries the skip-changelog label. CI-only; no recipe, since a base-ref diff has no local form. Three mechanics are deliberate and tested: `types:` lists all five activity types because it replaces the defaults and a bare pull_request never re-runs on a label change; the label is honoured inside the step rather than a job-level `if:` so the check reports pass, never "skipped"; and github.base_ref reaches the script through env:, which zizmor requires. The generation suite asserts present-when-on, absent-when-off, and runs the rendered script against a scratch clone in the blocking, labelled, and entry-added cases. run_in gains an env kwarg for that.
Same workflow as the template layer, on the maintainer's own pins, with the trigger paths template/ and copier.yml: the CHANGELOG describes generated-project behaviour only, so maintainer CI changes (including Renovate's Action bumps) need no entry. Documents the layer in AGENTS.md and marks Phase 2 of the dogfooding audit as started.
With in_existing_repo the .github/ directory is never rendered, so the AGENTS.md section and the justfile ci comment must not cite a changelog.yml that does not exist. The authoring rule and CHANGELOG.md itself still ship; only the CI references are conditional. The same condition now also guards the comment's scan.yml reference, which had the same dangling problem.
A deleted or whitespace-only CHANGELOG.md satisfied the check, because it only tested that the path appeared in the diff. It now requires at least one non-empty added line. An unresolvable base ref (a shallow checkout) made both git diff calls fail inside the test condition, which bash -e ignores, so the check printed ok and exited 0; the base is now verified first and the step errors. The gate test covers the whitespace touch, the deletion, the bad base, and a change outside the trigger paths (pinning the pathspec). The policy suite pins the maintainer copy's literals, since the generation suite only runs the rendered template's script. The nested-repo test asserts nothing rendered cites the omitted workflow, and the all-toggles renders include the new layer.
…rantees No v0.3.0 tag exists yet; the entry is still under Unreleased. The Release section claimed the check guarantees an entry, but the skip-changelog label bypasses it, so promotion needs a look at labelled PRs. Also records that the changelog workflow is the one exception to folding maintainer CI into test-template.yml, and describes the fail-closed base check.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The release step ("promote the Unreleased entries before tagging") is only as good as the entries people remembered to write, and nothing enforced writing them. This adds the changelog check as a template layer first, then dogfoods it here: the first Phase 2 layer of the dogfooding audit, and the first template change since v0.2.0 (so it becomes v0.3.0).
Changes
enable_changelogtoggle (default true) shipping a Keep-a-ChangelogCHANGELOG.md, a PR-onlychangelog.yml, and a two-line AGENTS.md section. The check fails whensrc/orpyproject.tomlchange without aCHANGELOG.mdchange; theskip-changeloglabel bypasses it. CI-only, no recipe, since a base-ref diff has no local form.types:lists all five activity types (it replaces the defaults, and a barepull_requestnever re-runs on a label change); the label is honoured inside the step, not a job-levelif:, so the check reports pass rather than "skipped"; andgithub.base_refreaches the script throughenv:, which zizmor requires.template/**andcopier.yml(maintainer CI changes need no entry, so Renovate's Action bumps pass untouched), AGENTS.md section, README row, Unreleased entry, audit status update.run_ingains anenvkwarg for the new gate test.Testing
just fmt-check lint typecheck policy— all pass; policy suite 7 passed (was 6).pytest -k 'changelog or existing_repo_layer or all_toggles_on or rendered_workflows_pass_zizmor or agent_contract or ci_workflows'— 7 passed. The gate test runs the rendered script against a scratch clone: blocks asrc/change with no entry, a whitespace-only touch, and a deleted changelog; errors on an unresolvable base; passes with the label, with a real entry, and for a README-only change.uvx zizmor@1.26.1 --persona=regular --offline .github/workflows— no findings.changelog: ok; a scratch commit touching only copier.yml exits 1 with the expected::error::;BASE_REF=nopeexits 1 withcannot resolve.testmatrix (full generation suite),lint,typecheck,scan,zizmor, and the newchangelogjob.Notes for reviewers
skip-changeloglabel already exists on this repo. Downstreams create theirs once, per the generated AGENTS.md.copier updateon the two nested renders in fix-wifi-issues.repository_urlanswer for compare links in the generated changelog. A new required answer for a hyperlink is not worth the update-prompt cost; downstreams add links at their first release.Related
docs/superpowers/plans/2026-07-01-dogfood-gap-audit.md, section 6 group C and Phase 2 item 8.