diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 18ff561..ee660e0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -8,9 +8,12 @@ # form can't pre-fill a value computed from repo state) and is only # validated to be greater than the current VERSION_STRING. The CHANGELOG # heading is just "## vX.Y.Z (date)" — no separate title to type in; the -# Unreleased section's own content (used verbatim as the GitHub Release -# body too) already says what the release is about. The workflow refuses -# to overwrite an existing release/tag. +# Unreleased section's own content already says what the release is about. +# The GitHub Release body is never that content verbatim, though — see the +# "Extract changelog section for this version" step below for what +# actually gets published, and CLAUDE.md's "Changelog policy" for the +# entry convention it depends on. The workflow refuses to overwrite an +# existing release/tag. name: Release on: @@ -144,23 +147,25 @@ jobs: - name: Build run: make - # 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. + # Release notes are always just the significant-change highlights for + # this version, never the full changelog section. This project's + # CHANGELOG.md convention (see CLAUDE.md's "Changelog policy") is + # that every significant change is its own "### : " heading, with any elaboration living in the paragraph/ + # bullets underneath — so extraction is a straight pull of those + # heading lines, with no length-based judgment call, ever. A section + # written with no "### " headings at all falls back to publishing the + # whole section as-is instead — a structural fallback for a section + # with nothing to extract, not a size cutoff. # - # 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 + # Either way a link back to this file's matching section is always + # appended. 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, not replaces them; + # then turn spaces into hyphens) — verified against this repo's + # actual rendered CHANGELOG.md anchors. + - name: Extract changelog highlights id: changelog env: RELEASE_TAG: ${{ steps.version.outputs.tag }} @@ -181,21 +186,16 @@ jobs: 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 + if [ -n "$HIGHLIGHTS" ]; then 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 + echo + echo "See [CHANGELOG.md]($CHANGELOG_LINK) for the full write-up." } > /tmp/release_notes.md echo "notes_file=/tmp/release_notes.md" >> "$GITHUB_OUTPUT" diff --git a/CHANGELOG.md b/CHANGELOG.md index dbe90c2..cd90b2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,8 +6,10 @@ release is a manual, deliberate step: trigger the `Release` GitHub Actions workflow (`.github/workflows/release.yml`) with just a version number — it renames this file's `## Unreleased` section to `## vX.Y.Z (date)`, bumps `VERSION_STRING` to match, builds, and publishes the result as a -GitHub Release using that section verbatim as the release notes. Keep -the `## vX.Y.Z` heading format exact. +GitHub Release using highlights extracted from that section (see +`CLAUDE.md`'s "Changelog policy" for the entry convention this depends +on — always just this section's `### ` headings plus a link back here, +never the full write-up). Keep the `## vX.Y.Z` heading format exact. **Policy:** every change gets a `CHANGELOG.md` entry under a `## Unreleased` section at the top of this file when it's made (create the section if it @@ -16,19 +18,21 @@ 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). +### Changed: release notes always show only the changelog's headings, never the full section +`.github/workflows/release.yml`'s "Extract changelog section for this +version" step used to hand the whole cut section to +`softprops/action-gh-release` verbatim for a short entry (40 lines or +fewer) and only fell back to a headings-only highlight list past that +size. It now always uses just the `### ` headings (each already a +one-line summary by this file's convention) as the Release body, with no +line-count judgment call — a version written with no headings at all +falls back to the full section instead, a structural fallback rather +than a size one. Either way a link back to this file's matching dated +section is always appended. Same change applied to CoverDex's and +ThePatientGamerHelper's `release.yml`, and each project's `CLAUDE.md` +now documents the bullet/heading convention its own release notes depend +on, so the highlights are always ready in this file rather than computed +by trimming or reflowing prose at release time. ## v2.4.0 (2026-08-19) diff --git a/CLAUDE.md b/CLAUDE.md index 646f626..98d3c41 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -190,9 +190,8 @@ Actions tab when the user actually asks to cut a release. It validates the input, renames `CHANGELOG.md`'s `## Unreleased` section to `## vX.Y.Z (date)`, bumps `VERSION_STRING` in `source/types.h` to match, commits and pushes that bump to `main`, builds, and publishes the -`.3dsx`/`.smdh` as a GitHub Release using that section verbatim as the -release notes — there's no separate title to type in; the Unreleased -section's own content is the release notes. +`.3dsx`/`.smdh` as a GitHub Release using highlights extracted from that +section (see "Changelog policy" below). ## Changelog policy @@ -202,6 +201,19 @@ not deferred until a release is cut. Don't rename it to a `## vX.Y.Z` heading or bump `VERSION_STRING` yourself — that rename/bump is what the `Release` workflow above does, on request, as one atomic step. +**Entry convention:** every significant change is its own `### : +` heading (`Fix:`/`Added:`/`Changed:`/`Removed:` are +this file's established types) — write the heading itself as a +complete, skimmable summary, with any further detail in a paragraph (and +optional sub-bullets) underneath. This isn't just for readability: +`.github/workflows/release.yml`'s "Extract changelog highlights" step +publishes exactly those `### ` heading lines as the GitHub Release +body — always, for every release, never the full section text and never +gated by a length cutoff — followed by a link back to this file's +matching section for the full write-up. A sloppy or vague heading ships +straight to the Release page as-is, so write it as if it were the only +sentence a reader sees. + ## Code conventions - No comments explaining *what* code does — only the non-obvious *why*