Claude
Skills
Sign in
Back

dotnet-release-management

Included with Lifetime
$97 forever

Managing .NET release lifecycle. NBGV versioning, SemVer, changelogs, pre-release, branching.

General

What this skill does


# dotnet-release-management

Release lifecycle management for .NET projects: Nerdbank.GitVersioning (NBGV) setup with `version.json` configuration, version height calculation, and public release vs pre-release modes; SemVer 2.0 strategy for .NET libraries (when to bump major/minor/patch, API compatibility considerations) and applications (build metadata, deployment versioning); changelog generation (Keep a Changelog format, auto-generation with git-cliff and conventional commits); pre-release version workflows (alpha, beta, rc, stable progression); and release branching patterns (release branches, hotfix branches, trunk-based releases with tags).

**Version assumptions:** .NET 8.0+ baseline. `Nerdbank.GitVersioning` 3.6+ (current stable). SemVer 2.0 specification.

**Scope boundary:** This skill owns the release lifecycle strategy -- versioning, changelogs, pre-release workflows, and branching patterns. Plugin-specific release workflows (dotnet-artisan versioning and publishing) are documented in repo-level CONTRIBUTING.md. CI/CD publish workflows (NuGet push, container push, deployment) are owned by [skill:dotnet-gha-publish] and [skill:dotnet-ado-publish]. GitHub Release creation and asset management are owned by [skill:dotnet-github-releases]. NuGet package versioning properties (`Version`, `PackageVersion`) are owned by [skill:dotnet-nuget-authoring].

**Out of scope:** Plugin-specific release workflow -- see repo-level CONTRIBUTING.md. CI/CD NuGet push and deployment workflows -- see [skill:dotnet-gha-publish] and [skill:dotnet-ado-publish]. GitHub Release creation and asset attachment -- see [skill:dotnet-github-releases]. NuGet package metadata and signing -- see [skill:dotnet-nuget-authoring]. Project-level configuration (SourceLink, CPM) -- see [skill:dotnet-project-structure].

Cross-references: [skill:dotnet-gha-publish] for CI publish workflows, [skill:dotnet-ado-publish] for ADO publish workflows, [skill:dotnet-nuget-authoring] for NuGet package versioning properties.

---

## NBGV (Nerdbank.GitVersioning)

NBGV calculates deterministic version numbers from git history. The version is derived from a `version.json` file and the git commit height (number of commits since the version was set), producing unique versions for every commit without manual version bumps.

### Installation

```bash
# Install NBGV CLI tool
dotnet tool install --global nbgv

# Initialize NBGV in a repository
nbgv install

# This creates version.json at the repo root
```

### version.json Configuration

```json
{
  "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/main/src/NerdBank.GitVersioning/version.schema.json",
  "version": "1.0",
  "publicReleaseRefSpec": [
    "^refs/heads/main$",
    "^refs/tags/v\\d+\\.\\d+(\\.\\d+)?(-.*)?$"
  ],
  "cloudBuild": {
    "buildNumber": {
      "enabled": true
    },
    "setVersionVariables": true
  }
}
```

### version.json Field Reference

| Field | Purpose | Example |
|-------|---------|---------|
| `version` | Base version (major.minor, optional patch) | `"1.0"`, `"2.3.0"` |
| `publicReleaseRefSpec` | Regex patterns for branches/tags that produce public versions | `["^refs/heads/main$"]` |
| `cloudBuild.buildNumber.enabled` | Set CI build number to calculated version | `true` |
| `cloudBuild.setVersionVariables` | Export version as CI environment variables | `true` |
| `nugetPackageVersion` | Override NuGet package version format | `{"semVer": 2}` |
| `assemblyVersion.precision` | Assembly version component count | `"major"`, `"minor"`, `"build"`, `"revision"` |
| `inherit` | Inherit from parent directory version.json | `true` |

### How Version Height Works

NBGV counts the number of commits since the `version` field was last changed in `version.json`. This count becomes the patch version:

```
version.json: "version": "1.2"

Commit history:
  abc1234  feat: add caching          -> 1.2.3
  def5678  fix: null check            -> 1.2.2
  ghi9012  chore: update deps         -> 1.2.1
  jkl3456  Bump version to 1.2        -> 1.2.0  (version.json changed here)
```

The version height ensures every commit has a unique version without manual intervention.

### Pre-Release vs Public Release

```json
{
  "version": "1.2-beta",
  "publicReleaseRefSpec": [
    "^refs/heads/main$",
    "^refs/tags/v\\d+\\.\\d+(\\.\\d+)?(-.*)?$"
  ]
}
```

| Branch/Ref | Computed Version | Notes |
|-----------|-----------------|-------|
| `main` (public) | `1.2.5-beta` | Public pre-release, height=5 |
| `feature/foo` (non-public) | `1.2.5-beta.gcommithash` | Includes git hash suffix |
| Tag `v1.2.5` (public) | `1.2.5` | Remove `-beta` before tagging |

To release a stable version, remove the pre-release suffix from `version.json` before the release commit:

```json
{
  "version": "1.2"
}
```

### NBGV CLI Commands

```bash
# Show the current calculated version
nbgv get-version

# Show specific version properties
nbgv get-version -v NuGetPackageVersion
nbgv get-version -v SemVer2

# Prepare for a release (creates release branch, bumps version)
nbgv prepare-release

# Set version variables for CI
nbgv cloud
```

### Monorepo NBGV Configuration

For monorepos with independently versioned projects, place `version.json` in each project directory and use `inherit`:

```
repo-root/
  version.json              <- { "version": "1.0" }
  src/
    LibraryA/
      version.json          <- { "version": "2.3", "inherit": true }
    LibraryB/
      version.json          <- { "version": "1.1-beta", "inherit": true }
```

The `inherit` field pulls settings (like `publicReleaseRefSpec` and `cloudBuild`) from the parent `version.json` while overriding the version number.

---

## SemVer Strategy for .NET Libraries

### When to Bump Versions

SemVer 2.0 specifies version format `MAJOR.MINOR.PATCH`:

| Change Type | Version Bump | Examples |
|-------------|-------------|----------|
| Breaking API changes | **Major** | Removing public types/members, changing method signatures, renaming namespaces |
| New features (backward compatible) | **Minor** | Adding public types/members, new extension methods, new overloads |
| Bug fixes (backward compatible) | **Patch** | Fixing incorrect behavior, performance improvements, internal refactors |

### .NET-Specific Breaking Change Considerations

| Change | Breaking? | Notes |
|--------|-----------|-------|
| Remove public type | Yes (Major) | Consumers referencing it will fail to compile |
| Remove public method | Yes (Major) | Direct callers will fail |
| Add required parameter to public method | Yes (Major) | Existing callers do not supply it |
| Add optional parameter to public method | No (Minor) | Binary compatible but source-breaking for callers using named arguments |
| Change return type | Yes (Major) | Binary and source breaking |
| Add new public type | No (Minor) | No existing code affected |
| Add new overload | No (Minor) | Existing calls still resolve |
| Change internal implementation | No (Patch) | No public API change |
| Change default value of optional parameter | No (Patch) | Binary compatible (value embedded at call site on recompile) |
| Seal a previously unsealed class | Yes (Major) | Consumers inheriting from it will fail |
| Make a virtual method non-virtual | Yes (Major) | Consumers overriding it will fail |

### API Compatibility Validation

Use `EnablePackageValidation` to catch accidental breaking changes. For full package validation setup, see [skill:dotnet-nuget-authoring].

```xml
<PropertyGroup>
  <EnablePackageValidation>true</EnablePackageValidation>
  <PackageValidationBaselineVersion>1.0.0</PackageValidationBaselineVersion>
</PropertyGroup>
```

---

## SemVer Strategy for Applications

Applications (web apps, desktop apps, services) have different versioning considerations than libraries because they do not have public API consumers.

### Application Versioning Approaches

| Approach | Format | Best For |
|----------|--------|----------|
| SemVer (feature-driven) | `1.

Related in General