Specify the changelog and release-notes mechanism #58

Closed
opened 2026-09-10 05:12:33 +00:00 by xavierk · 1 comment
Owner

Parent map: Chart Fenris dashboard clarity

Question

How do per-release Gitea notes carry instructions and bug-fix notes? Decide the CHANGELOG.md format (Keep a Changelog shape), how release.yml assembles the release body from the changelog section at tag time, and the discipline for bug-fix entries. Charting settled: CHANGELOG.md in the repo is the source of truth; the workflow mirrors it into the release body.

Parent map: [Chart Fenris dashboard clarity](https://git.bongbetic.com/xavierk/Fenris/issues/55) ## Question How do per-release Gitea notes carry instructions and bug-fix notes? Decide the CHANGELOG.md format (Keep a Changelog shape), how release.yml assembles the release body from the changelog section at tag time, and the discipline for bug-fix entries. Charting settled: CHANGELOG.md in the repo is the source of truth; the workflow mirrors it into the release body.
xavierk added this to the Wayfinder: Chart Fenris dashboard clarity milestone 2026-09-10 05:12:33 +00:00
xavierk added the wayfinder:grilling label 2026-09-10 05:12:33 +00:00
xavierk added a new dependency 2026-09-10 05:12:46 +00:00
Author
Owner

Resolution

Changelog + release-notes mechanism decided (Q1–Q14, grilling + domain-modeling):

Format (source of truth: CHANGELOG.md, repo root)

  • Keep a Changelog 1.1 shape. Version headings: ## [X.Y.Z] - YYYY-MM-DD (bracketed bare semver, strict ISO date). ## [Unreleased] section always present at top, even empty.
  • Categories: ### Added, ### Changed, ### Fixed only. Security fixes fold into Fixed.
  • Entries: one - bullet, imperative mood, user-facing phrasing; no commit hashes or issue numbers.

Extraction (release.yml, tag time)

  • scripts/extract_changelog.py (checked in, unit-tested): args changelog path + version; slices that version's section verbatim; fails closed (::error::, nonzero exit) when section missing/empty or date malformed. Never reads Unreleased.
  • Guard: workflow fails when pushed tag ≠ v${version from pyproject.toml} (skipped on workflow_dispatch).

Release body

  • Body = version section verbatim + standing footer from packaging/release-footer.md (channel install one-liners, sha256sum -c SHA256SUMS.asc verify, rollback pointer). Footer is standing text; only changelog section varies.
  • Re-run when release exists: PATCH the body (changelog re-sync is a feature). Assets/packages keep current idempotent-skip.

Discipline

  • All entries land in [Unreleased] as part of the fixing change — no notes-later step.
  • One release commit bumps pyproject version + renames [Unreleased] → version heading + restores empty [Unreleased]; tag that commit (tag ↔ pyproject ↔ changelog triple-match, enforced fail-closed).
  • No backfill: per-release notes begin with the release shipping this mechanism; CHANGELOG.md starts with empty [Unreleased].

Disposition: implements existing glossary Release (tag + packages + change notes together — current note-less releases violate it; mechanism closes that). No new glossary terms, no ADR (reversible). Execution is out of map scope; lands in docs/spec/dashboard-clarity.md at assembly (issue #60).

## Resolution Changelog + release-notes mechanism decided (Q1–Q14, grilling + domain-modeling): **Format (source of truth: CHANGELOG.md, repo root)** - Keep a Changelog 1.1 shape. Version headings: `## [X.Y.Z] - YYYY-MM-DD` (bracketed bare semver, strict ISO date). `## [Unreleased]` section always present at top, even empty. - Categories: `### Added`, `### Changed`, `### Fixed` only. Security fixes fold into Fixed. - Entries: one `- ` bullet, imperative mood, user-facing phrasing; no commit hashes or issue numbers. **Extraction (release.yml, tag time)** - `scripts/extract_changelog.py` (checked in, unit-tested): args changelog path + version; slices that version's section verbatim; fails closed (`::error::`, nonzero exit) when section missing/empty or date malformed. Never reads Unreleased. - Guard: workflow fails when pushed tag ≠ `v${version from pyproject.toml}` (skipped on workflow_dispatch). **Release body** - Body = version section verbatim + standing footer from `packaging/release-footer.md` (channel install one-liners, sha256sum -c SHA256SUMS.asc verify, rollback pointer). Footer is standing text; only changelog section varies. - Re-run when release exists: PATCH the body (changelog re-sync is a feature). Assets/packages keep current idempotent-skip. **Discipline** - All entries land in [Unreleased] as part of the fixing change — no notes-later step. - One release commit bumps pyproject version + renames [Unreleased] → version heading + restores empty [Unreleased]; tag that commit (tag ↔ pyproject ↔ changelog triple-match, enforced fail-closed). - No backfill: per-release notes begin with the release shipping this mechanism; CHANGELOG.md starts with empty [Unreleased]. **Disposition**: implements existing glossary **Release** (tag + packages + change notes together — current note-less releases violate it; mechanism closes that). No new glossary terms, no ADR (reversible). Execution is out of map scope; lands in docs/spec/dashboard-clarity.md at assembly (issue #60).
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Reference: xavierk/Fenris#58