Skip to content

release: cut v0.2.0-beta CHANGELOG section + inject into release body#57

Merged
Musiker15 merged 1 commit into
mainfrom
release/v0.2.0-beta
May 25, 2026
Merged

release: cut v0.2.0-beta CHANGELOG section + inject into release body#57
Musiker15 merged 1 commit into
mainfrom
release/v0.2.0-beta

Conversation

@Musiker15
Copy link
Copy Markdown
Member

Summary

Pre-tag prep for v0.2.0-beta. Two coupled changes:

1. CHANGELOG: [Unreleased][0.2.0-beta] — 2026-05-25

The Unreleased section had grown to 190 lines with multiple duplicate Added/Changed sections (one per PR sweep). Consolidated into a single coherent [0.2.0-beta] release block with the canonical Keep-a-Changelog structure:

  • Added: Milestones (+ Burn-Down), Timeline/Gantt, Card startAt editor, Board presence, Automation v1, docs site, auto-deploy, ADR 0010, new test suites
  • Changed: KanbanCard plumbing, URL cleanup (docs: fix stale repo URLs + refresh README for post-beta state #53), README post-beta refresh, 21 Dependabot bumps, @vitest/coverage-v8 peer-match
  • Removed: Phase-3 plaintext plumbing, @otplib/core
  • Fixed: Flaky totp tests, .env.example inline comments (fix(env): move inline comments off value lines in .env.example #56)
  • Security: otplib 12→13, @simplewebauthn 11→13
  • Tooling: dependabot crypto group restriction, .gitattributes for LF on .sh/.service
  • Deferred: explicit list of what's not in this release with reasons

Also caught up the missing entries for #53#56 (URL cleanup + auto-deploy + domain fix + env-example fix) that landed after the last CHANGELOG sweep.

Link references at the bottom updated: [Unreleased]: …compare/v0.2.0-beta...HEAD + new [0.2.0-beta] entry.

2. release.yml: inject CHANGELOG section into the GitHub Release body

The workflow used to call softprops/action-gh-release with generate_release_notes: true only → a flat "What's Changed" PR list, no narrative. For a 28-PR release that's not enough.

New step "Extract CHANGELOG section for this release" runs before softprops:

awk -v marker="## [${VERSION}]" '
  index($0, marker) == 1 { p=1; next }
  p && index($0, "## [") == 1 { exit }
  p && $0 != "---" { print }
' CHANGELOG.md > release-body.md

Uses index() (substring match), not regex, because awk implementations disagree on whether \[ is literal or a metachar — we hit that locally during testing. Substring match is unambiguous.

Then softprops/action-gh-release is called with both body_path: release-body.md and generate_release_notes: true → the action prepends the hand-curated narrative to the auto-generated PR list. Best of both worlds.

Fail-soft: if the CHANGELOG has no matching section for the tag, a ::warning:: is logged and the release ships with auto-generated notes only.

Verification

# Local extraction matches expectation
$ awk -v marker="## [0.2.0-beta]" '...' CHANGELOG.md | wc -l
53
$ awk -v marker="## [0.2.0-beta]" '...' CHANGELOG.md | grep -c '0.1.0-beta'
1   # only the cross-reference in the body, not the next section header

Next steps after merge

  1. git tag -s v0.2.0-beta -m "v0.2.0-beta" (or unsigned with -a)
  2. git push origin v0.2.0-beta
  3. Tag-push fires release.yml → multi-arch GHCR push + cosign sign + SBOMs + GitHub Release with the curated body + auto PR list

Test plan

  • pnpm typecheck clean
  • pnpm lint clean
  • Local awk extraction returns 53 lines, no neighbour leakage
  • After merge + tag push: the resulting release body shows the CHANGELOG block at the top and the auto-generated PR list below

🤖 Generated with Claude Code

Two changes that ship together because they both prepare the
upcoming v0.2.0-beta tag:

1. **CHANGELOG**: `[Unreleased]` (190 lines, multiple duplicate
   Added/Changed sections) is consolidated and renamed to
   `[0.2.0-beta] — 2026-05-25`. Missing entries for the recent
   #53#56 (URL cleanup, auto-deploy + domain fix + env.example
   inline-comment fix) are added. A fresh `[Unreleased]` placeholder
   sits above. Link references at the bottom updated:
     [Unreleased]: ...compare/v0.2.0-beta...HEAD
     [0.2.0-beta]: ...compare/v0.1.0-beta...v0.2.0-beta

2. **release.yml**: adds an "Extract CHANGELOG section for this
   release" step before softprops/action-gh-release. It uses awk's
   `index()` (not regex) so awk-implementation differences over `\[`
   escaping can't break it, then writes the matching section to
   `release-body.md`. The action's `body_path:` prepends that to
   the auto-generated PR list — best of both: hand-curated
   narrative + complete commit/PR audit trail.

   The step also logs a `::warning::` and falls through to
   auto-only if the CHANGELOG has no matching section, so a future
   tag with no curated notes still produces a release.

Verified locally with `awk -v marker="## [0.2.0-beta]" '...'
CHANGELOG.md` — 53 lines extracted, no leakage from neighbouring
sections.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Musiker15 <info@musiker15.de>
@Musiker15 Musiker15 merged commit 24d7fd5 into main May 25, 2026
8 checks passed
@Musiker15 Musiker15 deleted the release/v0.2.0-beta branch May 25, 2026 17: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