Skip to content

Write a release note

Goal: get real prose into the release, not just a list of commit subjects.

A generated release is a list of subject lines, and a subject line is a summary. The thing a reader most needs, this config key moved, edit the file before you upgrade, is usually written in the commit body by the person who knew it. Left alone, nothing looks there.

Short note: a trailer

For one line, add a Release-Note: trailer in the commit message's last paragraph.

feat: add the widget

Release-Note: The widget config key moved to widget.enabled.

Longer note: a fenced block

For anything that needs more than a line, fence it with release-note.

fix: correct the gadget

```release-note
Gadgets built before 0.2 need regenerating.
Run `gadget regen` once after upgrading.
```

Both forms show up in plan:

0.1.0 → 0.2.0 (minor)

Release notes contributed by 2 commits:
  - Gadgets built before 0.2 need regenerating. …
  - The widget config key moved to widget.enabled.

Decided by 2 commits:
  059b50bd minor  feat: add the widget
  412e075f patch  fix: correct the gadget

A commit can carry several notes, and they appear in the order they occur in the message. Blocks always come before trailers, which is a property of git rather than a choice: a trailer only counts when it sits in the last paragraph, so a fenced block after one would stop it being a trailer at all.

An unterminated block is ignored rather than read to the end of the message.

Shape the section

.colophon.yaml on the release branch decides where the notes sit and what the heading says.

release_notes:
  placement: prepend   # or append; prepend is the default
  heading: Upgrading   # empty means "Notes"

Prepend is the default because these are most often upgrade or migration notes, and a warning printed after the feature list is a warning read too late.

Why the commit and not the merge request

Every project in this estate merges fast-forward with squash off, and under those settings a merge request's description is not in the git history at all. Reading one means asking the forge to map each commit back to its merge request: an API call per commit, unavailable on Bitbucket without a human-installed app, broken for cherry-picked commits, and impossible in a repository read without credentials, which is exactly what plan is designed to be.

It would also make the notes depend on whether whoever merged happened to squash. Squashing is a judgement about whether a branch's commits carry historical value. It is not a precondition for having release notes.

Reference

Exact syntax for both forms is in the trailers reference; the manifest fields are in the release manifest reference.