Skip to content

Release-notes hardening pass

Motivation

The first release-notes implementation (yesterday) shipped a flat list and relied on inline Python in scripts/dev/bump-version.sh. Self-review found six concrete gaps: no Unreleased preview, no warning when a feat: commit landed without a feature-change note, no Added/Fixed/Breaking grouping, no rename detection, no commit SHA in entries, and no callout for breaking changes. This pass closes all six.

User-facing change

  • New scripts/dev/render_release_notes.py — single source of truth for release-notes rendering. Used by both the bump script and the docs workflow. Groups entries into Breaking changes / Features / Fixes / Other based on the Conventional Commit prefix of the commit that added each note; appends a short SHA linking to the GitHub commit; detects renames via -M --find-renames; emits a mismatch warning into the page (and to stderr) when there are more feat:/fix: commits in the range than new feature-change notes.
  • New Unreleased page at docs/releases/unreleased.md. It shows every feature-change note added since the last vX.Y.Z tag, so reviewers can see what's queued for the next release at any time. It is:
  • regenerated automatically on every push to main by .github/workflows/docs.yml before mkdocs build,
  • refreshed locally by scripts/dev/bump-version.sh so the working tree stays consistent right after a bump,
  • listed in the docs nav between Releases → Overview and v0.1.0.

API / IaC diff summary

  • scripts (new): scripts/dev/render_release_notes.py (~200 lines).
  • scripts (modified): scripts/dev/bump-version.sh — step 10 now shells out to the new renderer for both vX.Y.Z.md and unreleased.md; step 12 adds unreleased.md to the release commit.
  • docs (new): docs/releases/unreleased.md (committed placeholder; regenerated by CI). docs/releases/index.md gained an In progress section linking to it.
  • mkdocs nav: added Unreleased: releases/unreleased.md between Overview and v0.1.0.
  • workflow (modified): .github/workflows/docs.yml now checks out with fetch-depth: 0 so the renderer can scan tags + history, and runs the renderer before mkdocs build. The path filter also re-triggers the build when scripts/dev/render_release_notes.py changes.
  • No backend, frontend, or Bicep changes.

Validation

  • bash -n scripts/dev/bump-version.sh — syntax OK.
  • python3 -m py_compile scripts/dev/render_release_notes.py — syntax OK.
  • scripts/dev/bump-version.sh --dry-run --minor[bump] 0.1.0 -> 0.2.0.
  • python3 scripts/dev/render_release_notes.py --version Unreleased --auto-from-last-tag --to HEAD --out docs/releases/unreleased.md → wrote 349 notes (no v* tag yet, so range = full history).
  • uv run mkdocs build — 0 errors. Rendered page exposes Breaking changes / Features / Fixes / Other H2s; entry links resolve to both the features_change page and the commit on GitHub.