Skip to content

Source release notes from RELEASE-NOTES.md#27

Merged
martin-ottosen merged 1 commit into
mainfrom
feature/release-notes-from-md
May 26, 2026
Merged

Source release notes from RELEASE-NOTES.md#27
martin-ottosen merged 1 commit into
mainfrom
feature/release-notes-from-md

Conversation

@martin-ottosen

Copy link
Copy Markdown
Contributor

What changed

  • .github/workflows/publish.yml — the "Resolve release notes" step now awks the section under ## v<tag> in RELEASE-NOTES.md and writes it to release-notes.md. That same file is used twice downstream: as the GitHub release body (gh release create --notes-file) and as the nupkg's PackageReleaseNotes (via the export PackageReleaseNotes=... before dotnet pack).
  • No matching section → the step exits 1 with a ::error:: annotation pointing at RELEASE-NOTES.md. Build/test/pack never run, the tag is safe to delete + recreate at a fix commit, no half-baked nupkg ever leaves the workflow.
  • The gh api .../releases/generate-notes fallback is gone, and with it the GH_TOKEN env var on this step (no API call left).
  • CLAUDE.md release-section bullet rewritten: RELEASE-NOTES.md is now described as the source of truth, with a pre-tag checklist item ("verify ## v<next-version> is up to date covering everything merged since the previous tag").

Testing

  • Local smoke-test of the awk extraction:
    export GITHUB_REF_NAME=v0.1.0 && awk -v ver="$GITHUB_REF_NAME" '$0 ~ "^## " ver "([[:space:]]|$)" {in_section=1;next} in_section && /^## / {exit} in_section {print}' RELEASE-NOTES.md
    should print the ## v0.1.0 body.
  • Same awk with GITHUB_REF_NAME=v9.9.9 should produce empty output (zero non-whitespace chars).
  • On a fresh tag push for v0.1.0 (the planned first release), the workflow run should report Using curated '## v0.1.0' section from RELEASE-NOTES.md. and the resulting GitHub release body should match RELEASE-NOTES.md's ## v0.1.0 section verbatim.
  • Tag any version with no matching RELEASE-NOTES.md heading → workflow fails at the "Resolve release notes" step with the ::error:: annotation, nothing downstream runs.

Developer notes

  • Why fail-closed rather than fall back to auto-generated: a degraded GitHub release body can be fixed manually after the fact, but PackageReleaseNotes is baked into the nupkg at pack time. The nupkg uploads to the GitHub release and is then immutable as far as the Optimizely feed is concerned — anyone pulling the package after that sees the unfiltered PR-title dump in their IDE. Fail-closed forces the curated body before any artifact escapes.
  • Section delimiter: assumes ## v<MAJOR.MINOR.PATCH> headings with ## (or EOF) as the terminator. Matches the existing RELEASE-NOTES.md layout. If we ever introduce other ## -level headings inside a release section (e.g. ## Migration notes), they'd truncate the body — easy to spot in the workflow log's "Release notes" group and easy to fix by demoting them to ###.
  • Tag-name match is exact (^## v0.1.0([[:space:]]|$)): v0.1.0 won't accidentally match v0.1.0-rc1 or v0.1.10. Prereleases get their own section by design.

The publish workflow now carves out the "## v<tag>" section of
RELEASE-NOTES.md and uses it verbatim for the GitHub release body and
the nupkg's PackageReleaseNotes. No matching section → the step fails
before build, so the nupkg never ships with the unfiltered PR-title
list that GitHub's generate-notes API produces. CLAUDE.md flips its
"RELEASE-NOTES.md isn't read by CI" guidance and adds a pre-tag
checklist item.
@martin-ottosen
martin-ottosen merged commit 67cacf3 into main May 26, 2026
@martin-ottosen
martin-ottosen deleted the feature/release-notes-from-md branch May 26, 2026 19:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant