Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 39 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,22 @@ jobs:
- name: Build
run: make

# Release notes come straight from CHANGELOG.md: the section for the
# version just cut above (from its "## vX.Y.Z ..." heading up to the
# next one).
# Release notes come from CHANGELOG.md: the section for the version
# just cut above (from its "## vX.Y.Z ..." heading up to the next
# one). A short section (a quick fix, a handful of entries) is used
# in full, same as always. A long one (a big batch of work, like
# this repo's own v2.4.0) is abridged to just its "### " entry
# headings — each one is already written as a one-line summary by
# this file's own convention — plus a link to the matching
# CHANGELOG.md section for the full detail, rather than dumping
# hundreds of lines into the Release page. Either way, a link back
# to CHANGELOG.md is always included.
#
# The link's #fragment reproduces GitHub's own heading-anchor slug
# algorithm (lowercase; drop every character that isn't a-z, 0-9,
# space, underscore, or hyphen — this is what removes the periods
# inside a version number; then turn spaces into hyphens) — verified
# against this repo's actual rendered CHANGELOG.md anchors.
- name: Extract changelog section for this version
id: changelog
env:
Expand All @@ -162,7 +175,29 @@ jobs:
echo "::error::No CHANGELOG.md section found for ${RELEASE_TAG} right after cutting it — this should not happen."
exit 1
fi
printf '%s\n' "$BODY" > /tmp/release_notes.md

HEADING_LINE=$(printf '%s\n' "$BODY" | head -1)
HEADING_TEXT=$(printf '%s\n' "$HEADING_LINE" | sed -E 's/^##[[:space:]]*//')
SLUG=$(printf '%s' "$HEADING_TEXT" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9 _-]//g' | tr ' ' '-')
CHANGELOG_LINK="https://github.com/${GITHUB_REPOSITORY}/blob/main/CHANGELOG.md#${SLUG}"

LINE_COUNT=$(printf '%s\n' "$BODY" | wc -l)
HIGHLIGHTS=$(printf '%s\n' "$BODY" | grep '^### ' | sed -E 's/^###[[:space:]]*/- /')

{
if [ "$LINE_COUNT" -gt 40 ] && [ -n "$HIGHLIGHTS" ]; then
printf '%s\n' "$HEADING_LINE"
echo
printf '%s\n' "$HIGHLIGHTS"
echo
echo "**Full changelog:** see [CHANGELOG.md]($CHANGELOG_LINK) for the complete details."
else
printf '%s\n' "$BODY"
echo
echo "**Full changelog:** [CHANGELOG.md]($CHANGELOG_LINK)"
fi
} > /tmp/release_notes.md

echo "notes_file=/tmp/release_notes.md" >> "$GITHUB_OUTPUT"

- name: Create GitHub Release
Expand Down
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,20 @@ accurate at all times instead of being reconstructed from memory later.

## Unreleased

### Changed: release notes stay short for a big changelog entry
`v2.4.0`'s own GitHub Release ended up as a ~200-line wall of text, since
`.github/workflows/release.yml` always dumped the full `## Unreleased`
section verbatim into the Release body. Now: a short section (a quick
fix, a handful of entries — 40 lines or fewer) still gets used in full,
same as before; a long one is abridged to just its `### ` entry headings
(each already written as a one-line summary by this file's own
convention) as a bullet list. Either way, the Release body now always
ends with a link back to this file's matching dated section for the full
detail — computed to match GitHub's actual heading-anchor slug algorithm
(verified against this repo's own real rendered anchors, e.g. `v2.4.0
(2026-08-19)` → `#v240-2026-08-19` — GitHub drops the periods from the
version number, it doesn't turn them into hyphens).

## v2.4.0 (2026-08-19)

### Fix: release workflow failing on every run, unrelated to the PAT
Expand Down
Loading