Versioning Strategy
This document describes the versioning strategy for the BrightSword monorepo.
Overview
The BrightSword monorepo ships all packages as a unified suite at a single shared version. All 5 packages are always released together at the same version number:
- BrightSword.SwissKnife — Utilities and extensions
- BrightSword.Crucible — MSTest utilities
- BrightSword.Feber — Expression-based delegate generation
- BrightSword.Squid — Runtime type emission
- BrightSword.Packages — Metapackage bundling all libraries
Current version: 2.0.0
Semantic Versioning
All packages follow Semantic Versioning 2.0.0:
MAJOR.MINOR.PATCH
Version Components
- MAJOR — Incremented for incompatible API changes in any package
- MINOR — Incremented for new backwards-compatible functionality in any package
- PATCH — Incremented for backwards-compatible bug fixes in any package
Examples
2.0.0 -> 2.0.1 (Patch: Bug fix in any package)
2.0.1 -> 2.1.0 (Minor: New feature in any package)
2.1.0 -> 3.0.0 (Major: Breaking change in any package)
Version Storage
Root version.props
All packages share a single VersionPrefix defined in the root version.props:
<!-- version.props (repo root) -->
<Project>
<PropertyGroup>
<VersionPrefix>2.0.0</VersionPrefix>
</PropertyGroup>
</Project>
There are no per-project version.props files. Every package inherits its version from this single root file via Directory.Build.props.
Preview Suffix
A -preview suffix is automatically added for non-tag builds:
<!-- Directory.Build.props -->
<VersionSuffix Condition="'$(GITHUB_REF_TYPE)' != 'tag'">preview</VersionSuffix>
This means:
- Tag builds (releases):
2.0.0 - Branch/PR builds:
2.0.0-preview
Version Management
Automated Version Increment (Recommended)
Use the MSBuild IncrementVersion target to bump the unified version:
# Increment patch (2.0.0 -> 2.0.1)
dotnet msbuild Build.proj /t:IncrementVersion /p:Level=Patch
# Increment minor (2.0.0 -> 2.1.0)
dotnet msbuild Build.proj /t:IncrementVersion /p:Level=Minor
# Increment major (2.0.0 -> 3.0.0)
dotnet msbuild Build.proj /t:IncrementVersion /p:Level=Major
# Increment and commit locally (be careful):
dotnet msbuild Build.proj /t:IncrementVersion /p:Level=Patch /p:Commit=true
This edits the single VersionPrefix in root version.props, which applies to all 5 packages.
PowerShell Script
The scripts/increment-version.ps1 script provides an alternative interface:
./scripts/increment-version.ps1
Manual Version Updates
Edit the root version.props directly:
code version.props
# Change <VersionPrefix>2.0.0</VersionPrefix> to <VersionPrefix>2.0.1</VersionPrefix>
Dependency Management
Package Dependencies
Packages in the monorepo depend on each other via project references:
BrightSword.Crucible
(Independent - only depends on MSTest)
BrightSword.Feber
depends on BrightSword.SwissKnife
BrightSword.Squid
depends on BrightSword.Feber
depends on BrightSword.SwissKnife
BrightSword.Packages (metapackage)
depends on all 4 libraries
Build Order
The dependency graph determines the build and publish order, but not version management (since all packages share the same version):
- SwissKnife (base - no dependencies)
- Crucible (independent - only depends on MSTest)
- Feber (depends on SwissKnife)
- Squid (depends on Feber and SwissKnife)
- Packages (metapackage - depends on all)
Version Pinning
Project references use built assemblies directly. When packed, the NuGet dependency version matches the unified suite version:
<!-- Generated in .nupkg -->
<dependency id="BrightSword.SwissKnife" version="2.0.0" />
Release Process
1. Prepare Release
# Create release branch
git checkout -b release/v2.0.1
# Increment version
dotnet msbuild Build.proj /t:IncrementVersion /p:Level=Patch
# Commit version change
git add version.props
git commit -m "chore: bump version to 2.0.1"
# Push and create PR
git push origin release/v2.0.1
2. Merge to Main
After PR approval, merge to main.
3. Create Release Tag
# Tag the release
git tag v2.0.1
# Push tag to trigger automated publish
git push origin v2.0.1
4. Automated Publishing
When a v* tag is pushed, the publish-packages.yml workflow:
- Detects the tag
- Builds all packages
- Runs all tests
- Packs all 5 NuGet packages
- Publishes to NuGet.org in dependency order
- Creates GitHub Release
Version Naming Conventions
Git Tags
Tags follow a simple unified pattern:
v{version}
Examples:
v2.0.0v2.0.1v2.1.0
NuGet Packages
All packages share the same version:
BrightSword.SwissKnife.2.0.1.nupkg
BrightSword.Crucible.2.0.1.nupkg
BrightSword.Feber.2.0.1.nupkg
BrightSword.Squid.2.0.1.nupkg
BrightSword.Packages.2.0.1.nupkg
Git Branches
Branch names should be descriptive:
feature/add-new-functionality
fix/resolve-bug-123
release/v2.0.1
hotfix/critical-security-fix
Breaking Changes
Guidelines
Breaking changes in any package require a MAJOR version increment for the entire suite.
Breaking changes include:
- Removing public APIs
- Changing method signatures
- Changing return types
- Renaming public types or members
- Changing behavior that consumers depend on
Communication
For breaking changes:
- Document in PR: Clearly mark as breaking change
- Update CHANGELOG: List all breaking changes
- Migration Guide: Provide guidance for upgrading
- Announcement: Post in Discussions before release
Example
## Breaking Changes in 3.0.0
### Removed Obsolete Methods
The following methods marked obsolete in 2.x have been removed:
- `StringExtensions.OldMethod()` - Use `NewMethod()` instead
### Changed Method Signatures
`ProcessData` now requires a cancellation token:
`csharp
// Old (2.x)
public void ProcessData(string data)
// New (3.0)
public Task ProcessData(string data, CancellationToken cancellationToken)
`
### Migration Guide
1. Replace calls to `OldMethod()` with `NewMethod()`
2. Add `CancellationToken.None` to `ProcessData()` calls
3. Consider making your calls async
Preview Releases
Automatic Previews
Non-tag builds automatically receive a -preview suffix:
2.0.1-preview
This is controlled by VersionSuffix in Directory.Build.props. Pushing to any branch or creating a PR produces preview packages.
Manual Previews
For numbered preview releases, edit version.props:
<VersionPrefix>2.1.0</VersionPrefix>
<!-- and in Directory.Build.props set: -->
<VersionSuffix>preview.1</VersionSuffix>
Publishing Previews
Previews are published to:
- GitHub Packages (automatic for all branches)
- NuGet.org (manual, for official previews)
Version Query
Current Version
View the current unified version:
# Check root version.props
Get-Content version.props | Select-String "VersionPrefix"
# Check NuGet.org
dotnet package search BrightSword --exact-match
Version History
See version history:
- GitHub Releases: https://github.com/johnazariah/brightsword/releases
- NuGet.org: Package page version history
- Git tags:
git tag -l "v*"
Best Practices
When to Increment
- After each release: Increment to next development version
- Before release: Set final release version
- For hotfixes: Increment patch version
Commit Messages
Include version in commit messages:
chore: bump version to 2.0.1
fix: critical bug - bump to 2.0.2
feat: new feature - bump to 2.1.0
Testing
Before incrementing MAJOR version:
- Run all 508 tests
- Check for breaking changes across all packages
- Update documentation
- Create migration guide
Documentation
Update documentation with version-specific information:
- When features were added
- When features were deprecated
- When features were removed
- Minimum version requirements