Skip to content

Support curated release notes for milestone releases - #280

Merged
jfrench9 merged 3 commits into
mainfrom
chore/curated-release-notes
Aug 4, 2026
Merged

Support curated release notes for milestone releases#280
jfrench9 merged 3 commits into
mainfrom
chore/curated-release-notes

Conversation

@jfrench9

@jfrench9 jfrench9 commented Aug 4, 2026

Copy link
Copy Markdown
Member

The tag-release workflow generates its changelog from git diff <last-tag>..HEAD, so dispatching the 1.0.0 major would have produced release notes describing a two-commit delta since v0.4.12 — the wrong framing for a milestone.

The mechanism. If .github/release-notes/v<version>.md exists at the tagged ref, tag-release.yml uses it as the release body and skips the Claude changelog generation, the delta-statistics section, and the generated-with footer (hand-written notes shouldn't carry it). When no file exists, behavior is unchanged: same generated changelog, same stats, same footer, byte-for-byte template. The release body is now composed into a file and passed via body_path, with untrusted changelog content emitted through env/printf per the existing SECURITY (H2) conventions.

The 1.0.0 notes. .github/release-notes/v1.0.0.md is included — the graduation statement covering the product surface and the 130+ release lineage since June 2024, rather than the delta since last Tuesday. Merging this before dispatching create-release.yml with major means the release branch carries the file and the workflow picks it up automatically.

Also documents the convention in CLAUDE.md under Deployment. The version-specific filename means a leftover file can never leak into a later release.

Test plan

uvx yamllint passes (syntax-clean, only pre-existing line-length style warnings). The compose-body script was exercised locally in both modes: curated mode renders the v1.0.0.md content with links but no stats/footer; generated mode reproduces the existing template exactly, and $(...)/backtick content in the changelog stays literal. Pre-commit hook ran the full test:all gate.

A follow-up commit hardens input and credential handling in tag-release.yml: tag matching is tightened, the changelog API credential is passed to curl via a stdin config file, and remaining git-derived and configured values are routed through env — release body and step summary verified unchanged in both curated and generated modes.

- Tighten release-tag matching in the changelog step
- Pass the changelog API credential to curl via a stdin config file
- Route remaining git-derived and configured values through env

Release body and step summary verified unchanged for normal values in
both curated and generated modes.
The curated-notes and hardening changes were written independently per
repository, which left the same logic expressed several different ways.
Normalise the shared parts so the nine copies stay diffable: identical
tag-existence test, identical curl invocation and continuation style,
one wording for the tag-selection and credential comments, and consistent
brace style. Drops an unused VERSION env entry from the analyze step.

No behaviour change; only formatting, comments, and a dead variable.
@jfrench9
jfrench9 merged commit 6e0e77a into main Aug 4, 2026
3 checks passed
@jfrench9
jfrench9 deleted the chore/curated-release-notes branch August 4, 2026 22:18
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