5.5 KiB
name, description, argument-hint
| name | description | argument-hint |
|---|---|---|
| new-release | Cut a new release: tag the appropriate commit, generate the changelog, and produce build artifacts. Use when: releasing a new version, tagging a release, publishing NuGet packages, preparing release artifacts. | Branch or commit to release from (default: current main) and the kind of release (stable, prerelease, hotfix) |
New Release
Versioning is GitVersion-driven (GitVersion.yml). Do not hand-pick versions — let GitVersion compute them from branch and tag history.
Versioning
The root GitVersion.yml uses the TrunkBased/preview1 workflow. Its Mainline strategy is what makes stable branches increment per commit rather than holding one version until the next tag.
| Branch | Label | Resulting version |
|---|---|---|
main, release/* |
— | MAJOR.MINOR.PATCH (stable; patch increments on every commit) |
feature/* |
branch name | …-<branch>.N (pre-release; merging bumps minor) |
hotfix/* |
branch name | …-<branch>.N (pre-release; merging bumps patch) |
- Tags use the prefix
v(regex[vV]?also acceptsVor none). - Each
src/*project is versioned independently: only changes under that project's own directory,Directory.Packages.props, orGitVersion.ymlincrement its version (seeGenerateProjectGitVersionConfiginsrc/Directory.Build.props, which renders the rootGitVersion.ymlinto a per-project copy). A change to one library does not bump a sibling's version. - All five packages still share one tag namespace, so a tag rebases every project's
MAJOR.MINORat once. Only the patch/pre-release counters diverge per project. - Increments are suppressed on already-tagged commits, so the tagged commit builds exactly the tagged version.
Changelog
Release notes are generated at pack time and embedded as PackageReleaseNotes. The GenerateChangelogFromGit target writes git log subjects to $(ChangeLogPath), and CreateReleaseNotesFromFile reads that file into the nuspec. Both run before GenerateNuspec, and generation is skipped when the repository root has no .git directory.
The commit range is resolved in this order, first match wins:
$(ChangeLogFromRef)..HEAD— whenChangeLogFromRefis set.<tag>..HEAD— fromgit describe --tags --abbrev=0.<sha>..HEAD— the last first-parent merge whose subject matches$(ChangeLogUpstreamMergePattern).<sha>..HEAD— the last first-parent merge.- No range; the log is capped at
$(ChangeLogCommitLimit)commits.
Commits are filtered with --no-merges and scoped to the project's own directory, plus the directories of its ProjectReferences unless ChangeLogIncludeReferences is false. This mirrors the per-project versioning rule above: a sibling library's commits do not appear in this package's notes.
| Property | Default | Purpose |
|---|---|---|
ChangeLogFromRef |
(empty) | Explicit range start; overrides the fallback chain |
ChangeLogPath |
$(BaseIntermediateOutputPath)changes.log |
Where the log is written and read from |
ChangeLogCommitLimit |
100 |
Cap used only when no range resolves |
ChangeLogUpstreamMergePattern |
from .*/ |
Subject matcher for the upstream-merge fallback |
ChangeLogIncludeReferences |
true |
Include ProjectReference directories in scoping |
GenerateChangelogFromGit |
(unset) | Set to false to skip generation entirely |
Important
Step 2 uses the nearest reachable tag, not the newest. Packing from a commit that already carries a release tag therefore yields only the commits added since it — often a single entry. Pass
ChangeLogFromRefto widen the range:dotnet pack -c Release -p:ChangeLogFromRef=v4.0.0
To ship hand-written notes instead, disable generation and point ChangeLogPath at your own file. Generation must be disabled, otherwise the target overwrites it:
dotnet pack -c Release -p:GenerateChangelogFromGit=false -p:ChangeLogPath=notes.md
Confirm the resolved range in the build output before publishing:
Generated changelog at <path> using range v4.0.0..HEAD.
Procedure
- Sync.
git fetch --all --tags && git status— confirm clean. - Compute.
dotnet build src\<Project>\<Project>.csproj -getProperty:Version— verify the value matches expectations for that specific project (there is no single repo-wide version). - Pack.
dotnet pack -c Release(or use the docker-buildpacktarget). Artifacts land inartifacts/nuget/. Check the logged changelog range and passChangeLogFromRefif it is narrower than the release warrants. - Tag.
git tag -a v<version> -m "Release v<version>" && git push origin v<version>. - Publish packages to the configured feed.
- Create the GitHub release linked to the tag, using the generated changelog as notes.
For hotfixes: branch from the latest stable tag (git switch -c hotfix/<name> v<latest-stable>), follow the procedure, then merge back into main. There is no develop branch to reconcile with — this repo is trunk-based.
Guardrails
- Tags are immutable once pushed; never move or delete them.
- Never skip a
PATCH— ship a fix forward. - Do not edit
GitVersion.ymlor a generatedsrc/*/GitVersion.ymlto force a version. Address the underlying cause (missing tag, branch base, path filter, commit messages). Generated per-project files are gitignored build artifacts, re-derived from the rootGitVersion.ymlon every build — never hand-edit them.