From f80913fbe3aa3cac20cbc70507743818d069d8dd Mon Sep 17 00:00:00 2001 From: Stuart Meeks Date: Sat, 30 May 2026 07:46:33 +0000 Subject: [PATCH] Add Nerdbank.GitVersioning for git-derived version stamping version.json (0.1.0-alpha.{height}) becomes the single source of truth for the version. NBGV stamps every assembly at build time from version.json + git height + commit hash, so the About page shows a real version for dev and CI builds instead of the 1.0.0 compile-time fallback. release.yml now derives the published version from `nbgv get-version` (asserting a public release per publicReleaseRefSpec) instead of parsing the tag string, and drops the redundant -p:Version on publish. versionHeightOffset starts the alpha counter past the previously hand-tagged v0.1.0-alpha.1. CONTRIBUTING documents the new `nbgv tag` release flow. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/release.yml | 29 +++++++++++++++++++++-------- CHANGELOG.md | 6 ++++++ CONTRIBUTING.md | 32 +++++++++++++++++++++++++------- Directory.Build.props | 7 +++++++ Directory.Packages.props | 5 +++++ version.json | 8 ++++++++ 6 files changed, 72 insertions(+), 15 deletions(-) create mode 100644 version.json diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b162397..3745598 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -38,19 +38,29 @@ jobs: **/packages.lock.json **/*.csproj - - name: Derive version + channel from tag + - name: Install Nerdbank.GitVersioning CLI + run: dotnet tool install --global nbgv --version 3.9.50 + + - name: Derive version + channel from NBGV id: meta shell: pwsh run: | - $tag = "${{ github.ref_name }}" - $version = $tag.TrimStart('v') + # NBGV is the single source of truth — version.json + git height. + # On a tagged (public-release) build the SemVer2 string is clean + # (no commit-id suffix), e.g. 0.1.0-alpha.7 or 0.1.0 for a stable cut. + $json = nbgv get-version --format json | ConvertFrom-Json + if (-not $json.PublicRelease) { + Write-Error "NBGV did not treat ref '$($json.BuildingRef)' as a public release. The release tag must match publicReleaseRefSpec in version.json; create it with 'nbgv tag'." + exit 1 + } + $version = $json.SemVer2 + $prerelease = $json.PrereleaseVersionNoLeadingHyphen # 'alpha.7' or '' # Emit lowercase 'true'/'false' explicitly — PowerShell's boolean # string-interpolation produces 'True'/'False' (capitalised), which # softprops/action-gh-release@v2 silently treats as falsy. - if ($version.Contains('-')) { + if ($prerelease) { $isPrerelease = 'true' - $channel = ($version -split '-', 2)[1] -replace '\..*$', '' - if ([string]::IsNullOrWhiteSpace($channel)) { $channel = 'beta' } + $channel = ($prerelease -split '\.')[0] # 'alpha' } else { $isPrerelease = 'false' $channel = 'stable' @@ -58,7 +68,7 @@ jobs: "version=$version" >> $env:GITHUB_OUTPUT "isPrerelease=$isPrerelease" >> $env:GITHUB_OUTPUT "channel=$channel" >> $env:GITHUB_OUTPUT - Write-Host "Tag : $tag" + Write-Host "Tag : ${{ github.ref_name }}" Write-Host "Version : $version" Write-Host "Pre-release : $isPrerelease" Write-Host "Channel : $channel" @@ -70,7 +80,10 @@ jobs: run: dotnet test tests/Snipdeck.Core.Tests/Snipdeck.Core.Tests.csproj --configuration Release --no-restore - name: Publish Snipdeck.App (win-x64) - run: dotnet publish src/Snipdeck.App/Snipdeck.App.csproj --configuration Release --runtime win-x64 --self-contained true --output publish -p:Version=${{ steps.meta.outputs.version }} + # No -p:Version here — Nerdbank.GitVersioning stamps the assemblies at + # build time from version.json + git height (the same number the meta + # step reads), so an explicit Version would be redundant and ignored. + run: dotnet publish src/Snipdeck.App/Snipdeck.App.csproj --configuration Release --runtime win-x64 --self-contained true --output publish - name: Install Velopack CLI run: dotnet tool install -g vpk diff --git a/CHANGELOG.md b/CHANGELOG.md index 091d3b8..2c960a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added +- **Git-derived version numbers (Nerdbank.GitVersioning).** Every build now + stamps a real version (`0.1.0-alpha.+`) into all + assemblies from a single `version.json`, so the About page shows a meaningful + version for dev and CI builds instead of the `1.0.0` compile-time fallback. + Releases derive their version from NBGV rather than the tag string — see + CONTRIBUTING.md for the `nbgv tag` release flow. - **Trash.** A "Trash" entry in the pane footer lists soft-deleted snips from across every CLI. Each can be **Restored** (returned to its CLI) or **Deleted permanently** (after confirmation). Previously, deleting a snip moved it to diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6508d99..60068fb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -107,15 +107,33 @@ project boundary. ## Releases -Releases are driven by git tags: +The version number is owned by [Nerdbank.GitVersioning](https://github.com/dotnet/Nerdbank.GitVersioning) +(NBGV), not by the tag you type. `version.json` at the repo root holds the base +(`0.1.0-alpha.{height}`); NBGV derives the full version from it plus the git +commit height, stamps every assembly, and the workflow reads it back at release +time. So you don't hand-pick the `-alpha.N` counter — it tracks git height. -- `v1.2.3` — stable release. -- `v1.2.3-rc.1`, `v1.2.3-beta.4`, etc. — pre-release. The hyphen in the tag - marks the GitHub release as a pre-release and feeds Velopack's channel name. +Releases are still driven by git tags, but **create the tag with NBGV so its +name matches the computed version** (install once with +`dotnet tool install --global nbgv`): -Pushing a matching tag triggers `.github/workflows/release.yml`, which builds -`Snipdeck.App`, packs it with Velopack, and attaches the artefacts to a new -GitHub Release. Don't push tags from feature branches — release from `master`. +``` +git checkout master && git pull +nbgv tag # mints e.g. v0.1.0-alpha.7 for the current commit +git push origin v0.1.0-alpha.7 +``` + +Pushing a matching tag triggers `.github/workflows/release.yml`, which derives +the version from `nbgv get-version` (asserting it's a public release per +`publicReleaseRefSpec`), builds `Snipdeck.App`, packs it with Velopack, and +attaches the artefacts to a new GitHub Release. The hyphen in the version +(`-alpha`, `-beta`, …) marks the GitHub release as a pre-release and feeds +Velopack's channel name. Don't tag from feature branches — release from +`master`. + +To cut a **stable** release (or move to a new line), edit `version.json` first +— e.g. `0.1.0-alpha.{height}` → `0.1.0` for the first stable, or bump to +`0.2.0-alpha.{height}` — commit that on `master`, then `nbgv tag` and push. ## Asking for direction diff --git a/Directory.Build.props b/Directory.Build.props index 13c208b..a8a6205 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -15,4 +15,11 @@ true + + + + + diff --git a/Directory.Packages.props b/Directory.Packages.props index e61fc2a..1f149da 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -5,6 +5,11 @@ true + + + + + diff --git a/version.json b/version.json new file mode 100644 index 0000000..c65cb19 --- /dev/null +++ b/version.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/main/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1.0-alpha.{height}", + "versionHeightOffset": 1, + "publicReleaseRefSpec": [ + "^refs/tags/v\\d+\\.\\d+\\.\\d+" + ] +}