Prepare Release
Analyzes git history, categorizes changes, and generates dual-format release notes for releasenotes.props (NuGet) and CHANGELOG.md (GitHub).
Workflow
When preparing a release (invoked via /prepare-release [version] or automatically when context indicates release preparation):
1. Determine Version and Scope
- Parse the version number (ask if not provided)
- Identify type: Major (X.0.0), Minor (X.Y.0), or Patch (X.Y.Z)
- Find previous version tag for comparison
2. Gather Changes
Run git commands to analyze commits since last release:
git logfor commit historygit log --grepfor PR merges- Look for conventional commit patterns:
fix:,feat:,break:,docs:, etc.
3. Filter and Categorize Changes
Exclude from release notes:
- Dependabot / automated dependency bump commits (e.g.,
chore(deps): Bump ...). These are routine maintenance and not user-facing. - CI/tooling-only changes (e.g., updating GitHub Actions workflows, claude workflows) unless they affect the shipped package.
Group remaining changes into categories (in this order):
- Breaking changes (major versions only) - API removals, behavior changes
- Features - New functionality or APIs
- Fixes - Bug fixes and corrections
- Improvements - Performance or usability enhancements
- Docs - Documentation-only changes
- Other - Infrastructure, tooling, CI/CD (only if user-facing or noteworthy)
4. Generate releasenotes.props Entry
Format: * @contributor: description (#PR)
XML escaping: < → <, > → >, & → &
Minor/Major versions:
<PackageReleaseNotes Condition="$(VersionPrefix.StartsWith('X.Y.'))">
Changes since X.Y-1:
Breaking changes:
* @user: description (#123)
Features:
* @user: description (#124)
Fixes:
* @user: description (#125)
</PackageReleaseNotes>
Patch versions:
Append the patch notes directly at the end of the existing parent version's StartsWith('X.Y.') block. Do NOT create a separate conditional block. Add the patch section just before the closing </PackageReleaseNotes> tag of the parent version:
<PackageReleaseNotes Condition="$(VersionPrefix.StartsWith('X.Y.'))">
...existing X.Y.0 release notes...
Updates in X.Y.Z patch:
* @user: fix description (#123)
</PackageReleaseNotes>
For multiple patches, append each one in order at the end of the same block:
...existing X.Y.0 release notes...
Updates in X.Y.1 patch:
* @user: fix description (#123)
Updates in X.Y.2 patch:
* @user: another fix (#456)
</PackageReleaseNotes>
5. Generate CHANGELOG.md Entry
Format: * [@contributor]: description ([#PR])
For pre-releases (beta, rc):
- Add changes under existing "Unreleased changes" section (do NOT create new version header)
- Update the comparison link to point from last stable tag to main branch HEAD
- Rationale: Build number suffix (e.g.,
-beta.{BUILD_NUMBER}) is unknown until CI runs
## [Unreleased changes](https://github.com/natemcmaster/CommandLineUtils/compare/vX.Y.Z...main)
### Breaking changes
* [@user]: description ([#123])
### Features
* [@user]: description ([#124])
### Fixes
* [@user]: description ([#125])
[#123]: https://github.com/natemcmaster/CommandLineUtils/pull/123
[#124]: https://github.com/natemcmaster/CommandLineUtils/pull/124
[#125]: https://github.com/natemcmaster/CommandLineUtils/pull/125
For stable releases:
- Create new version header with exact tag comparison
- Insert AFTER "Unreleased changes" section
## [vX.Y.Z](https://github.com/natemcmaster/CommandLineUtils/compare/vX.Y.Z-1...vX.Y.Z)
### Features
* [@user]: description ([#123])
[#123]: https://github.com/natemcmaster/CommandLineUtils/pull/123
6. Update Directory.Build.props
Update <VersionPrefix> to match release version.
7. Present for Review
Show the user:
- Summary of changes by category
- Proposed
releasenotes.propsaddition - Proposed
CHANGELOG.mdaddition Directory.Build.propsversion update
Ask for confirmation before applying changes.
8. Apply Changes
Once approved, edit the three files.
9. Final Checklist
Remind user to:
- Review generated notes for accuracy
- Run
./build.ps1to verify build - Create git tag:
git tag vX.Y.Z - Push tag:
git push origin vX.Y.Z
Style Guide
Contributor Attribution
Always credit contributors:
* @username: description (#123)
For multiple contributors:
* @user1 and @user2: description (#123 and #456)
Description Format
Good examples:
fix: find dotnet.exe correctly when DOTNET_ROOT is not setfeature: add API for setting default value on options and argumentsdon't mask OperationCanceledException triggered by SIGINT
Avoid:
- Implementation details:
"Refactored ValidationAttribute processing" - Vague:
"Fixed bug","Updated code" - Missing attribution:
"Fixed parser (#123)"
Optional Prefixes
Use when it adds clarity (optional under category headings):
fix:- Bug fixesfeature:- New featurescleanup:- Code cleanupdocs:- Documentationbugfix:- Alternative to "fix:"
PR References
(#123) # single PR
(#389 and #420) # multiple PRs
Omit if direct commit (no PR).
Version-Specific Patterns
Major Versions (X.0.0)
Lead with breaking changes prominently. Consider linking to upgrade guide.
Changes since X-1.Y.Z:
Breaking changes:
* @user: remove deprecated API (#251)
* @user: dropped .NET Standard 1.6 support (#337)
Features:
* [new features]
See https://natemcmaster.github.io/CommandLineUtils/vX.0/upgrade-guide.html
Patch Versions
Append patch notes directly into the existing parent version's StartsWith('X.Y.') block in releasenotes.props. Do NOT create a separate conditional block or use $(PackageReleaseNotes) inheritance. Each patch gets an "Updates in X.Y.Z patch:" section appended at the end of the parent block.
Quality Checklist
- All changes have contributor attribution (@username)
- All changes have PR references when applicable (#123)
- XML special characters escaped (< > &)
- Categories in correct order
- Version condition is exact
- Footer link included and correct (version without dots)
- CHANGELOG.md has markdown link references
- Descriptions are clear and user-focused
Examples
See src/CommandLineUtils/releasenotes.props:
- Version 4.0.0 - Major with breaking changes
- Version 4.0.1 - First patch
- Version 4.0.2 - Second patch
- Version 3.1.0 - Minor with features
Source: natemcmaster/CommandLineUtils — distributed by TomeVault.