Skip to content

ci: every PR records its changelog entry under [Unreleased], and CI checks it - #197

Merged
raspbeguy merged 1 commit into
mainfrom
feat/changelog-check
Oct 10, 2026
Merged

raspbeguy merged 1 commit into
mainfrom
feat/changelog-check

Conversation

@raspbeguy

@raspbeguy raspbeguy commented Oct 10, 2026 •

Copy link
Copy Markdown
Member

The changelog is now written in each PR and checked by CI, the way Grafana Mimir does it. Until now, entries were written at release time from memory: nine PRs merged between 3.0.0 and this one, and none of them added an entry.

The rule

  • The entry: every PR adds an entry under ## [Unreleased] in CHANGELOG.md, in the Keep a Changelog heading that fits, ending with its number, for example (#193). Internal stays for release and build machinery, as before.
  • The label: a PR that changes nothing outside the repo (docs, tests, CI that builds no artifact, refactors, release PRs) takes the new changelog-not-needed label instead.
  • The check: .github/workflows/changelog.yml runs scripts/changelog-has-entry.sh and fails the PR when neither is true. It is its own workflow, so adding or removing the label re-runs only this short check, not the integration suite. The parentheses in (#N) keep #19 from matching an entry for #193.
  • The release step: scripts/changelog-missing.sh <previous-tag> lists merged PRs that have neither an entry nor the label, and it must print nothing before a tag. The release then renames ## [Unreleased] to the version.
  • The PR number: scripts/next-pr-number.sh predicts it, so the entry can go in before the PR exists.

The rules are in docs/release-process.md, section Changelog, which replaces the old "Auto-CHANGELOG" section. CONTRIBUTING.md, the PR rules in CLAUDE.md, and the CI shape in docs/testing.md point to it.

Why the Mimir model

Grafana Labs uses four models, checked against their repositories on 2026-10-10:

Model Repos Who writes the entry Enforcement
Hand-written in each PR, under an unreleased section Mimir the PR author CI fails a PR whose number is not in CHANGELOG.md, unless it has changelog-not-needed
Generated from conventional-commit PR titles Loki, Alloy (release-please), terraform-provider-grafana (git-cliff) nobody: the title is the entry a lint on the PR title
PR titles with an opt-in label, collected at release grafana/grafana the release workflow none since May 2026
One hand-written notes file per release k6 the maintainers none

Generation from titles is the most common model across the org. It does not fit uapi, because docs/versioning.md requires some entries to carry more than a title can: a carve-out entry must say which carve-out it uses and how loudly the change fails. Mimir keeps the prose and adds the enforcement. Mimir added that check in June 2025, while grafana/grafana dropped its own in May 2026. Keep a Changelog headings stay as they are, since the file, scripts/release-notes.sh and the semver mapping already use them.

Backfill

## [Unreleased] now holds entries for #186, #189, #190, #193, #194, #195 and #196. #187 and #188 changed only docs, so they now carry changelog-not-needed. scripts/changelog-missing.sh v3.0.0 printed all nine before the backfill and prints nothing after it. This PR carries the label too: it changes no artifact.

Does this change the wire surface?

No. Nothing in the package changes. The changelog text changes, and it becomes the body of the next GitHub Release.

Was it verified against a real device, or only by CI?

Neither applies to the router, because nothing on it changes. The scripts ran against this repository and its real PR history: changelog-has-entry.sh found each backfilled entry, rejected #19 and #187, and changelog-missing.sh v3.0.0 behaved as stated above. The workflow itself was tested on this PR:

  • Opened without the label: the changelog run failed with CHANGELOG.md has no entry ending in (#197) under ## [Unreleased].
  • After the label was added: the next run was skipped, which GitHub counts as passing.

Was LuCI checked?

Not applicable: this is a repository process, not a router behavior.

Branch protection

main has no branch protection, so GitHub does not require this check, or any other. Merging only on green is what enforces it today. A ruleset that requires changelog / entry and the CI jobs would make the rule hold without that discipline.

🤖 Generated with Claude Code

…hecks it

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@raspbeguy raspbeguy added the changelog-not-needed Nothing outside the repo changes, so no CHANGELOG.md entry is needed label Oct 10, 2026
@raspbeguy
raspbeguy merged commit 4282291 into main Oct 10, 2026
7 of 8 checks passed
@raspbeguy
raspbeguy deleted the feat/changelog-check branch October 10, 2026 20:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog-not-needed Nothing outside the repo changes, so no CHANGELOG.md entry is needed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant