EonaCat.Versioning.Helpers 1.5.0

Prefix Reserved
dotnet add package EonaCat.Versioning.Helpers --version 1.5.0
                    
NuGet\Install-Package EonaCat.Versioning.Helpers -Version 1.5.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="EonaCat.Versioning.Helpers" Version="1.5.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="EonaCat.Versioning.Helpers" Version="1.5.0" />
                    
Directory.Packages.props
<PackageReference Include="EonaCat.Versioning.Helpers" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add EonaCat.Versioning.Helpers --version 1.5.0
                    
#r "nuget: EonaCat.Versioning.Helpers, 1.5.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package EonaCat.Versioning.Helpers@1.5.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=EonaCat.Versioning.Helpers&version=1.5.0
                    
Install as a Cake Addin
#tool nuget:?package=EonaCat.Versioning.Helpers&version=1.5.0
                    
Install as a Cake Tool

EonaCat.Versioning

Automatic GIT or SVN versioning for your .NET assemblies. Injects VCS revision data into AssemblyInfo, NuGet packages, and version files - zero manual version management required.

Features

  • Automatic versioning from Git tags and SVN revision numbers
  • Semantic Versioning (SemVer 2.0.0) with full parsing, comparison, bumping, and range matching
  • Calendar Versioning (CalVer) support (YYYY.MM.DD, YYYY.MM.MICRO, etc.)
  • Conventional Commits analysis for automatic version bump detection
  • Changeset-based version management for monorepo workflows
  • Git SHA versioning for continuous deployment pipelines
  • Build number auto-increment via persistent counter file
  • Rich format placeholders - 50+ tokens including OS, architecture, environment variables, timestamps, and more
  • MSBuild integration - works with dotnet build, msbuild, and CI/CD pipelines
  • Fail-on-dirty support to prevent releases from modified repositories
  • Version file output - write the resolved version to a custom file path
  • Quiet mode to suppress informational messages during builds

Debug/Console Information

Build your project using:

dotnet build
dotnet build -v d

or with MSBuild directly:

msbuild YourProject.csproj /v:d

or to log to a file:

msbuild YourProject.csproj -fl -flp:logfile=YourProjectOutput.log;verbosity=diagnostic

Note: dotnet build works on all platforms (Windows, Linux, macOS). The standalone msbuild command requires Visual Studio on Windows or Mono on Linux/macOS.

Installation

Just install the NuGet package EonaCat.Versioning to your .NET Framework 4.8 or .NET Standard 2.1 / .NET 6.0 or higher project.

Cross-platform: EonaCat.Versioning works on Windows, Linux, and macOS. On non-Windows platforms, the package targets .NET Standard 2.1. All VCS operations, file handling, and version resolution are fully cross-platform.

If you’re creating a NuGet package of your project, make sure to declare this package reference as private in your .csproj so that your final package does not depend on EonaCat.Versioning.

<ItemGroup>
  <PackageReference Include="EonaCat.Versioning" Version="..." PrivateAssets="all" />
</ItemGroup>

Default behaviour for Git

If not configured, tags following semantic versioning:

{semtagver}+{chash:10}.{c:ymd}

Examples:

  • 0.0.1+8dda362328.20240207
  • 1.0.0+8dda362328.20240207

Default behaviour for Subversion

If not configured otherwise, the revision number is used as the patch number. You should change that before you make a release. Its format is defined as:

0.0.{revnum}

Examples:

  • 0.0.1 (Default version if not or incorrectly specified)
  • 0.0.20
  • 0.0.200

Configuration

MSBuild properties

Configuration of the version scheme is done through MSBuild properties defined in the project file to which the NuGet package was added. If you have multiple projects in your solution, you’d basically have to repeat these steps for each project, or you could factor them out into a separate .props file and import that into each project or you can use Directory.Build.props. This also applies to classic-style projects, even though editing the project file is a bit more involved.

Automatic build number incrementation: <EVBuildNumberFile>$(MSBuildProjectDirectory)\build.number</EVBuildNumberFile>

Revision Format example (which has version 1.0.0): <EVRevisionFormat>1.0.0+{chash:10}.{c:ymd}</EVRevisionFormat>

Revision Format example with build number: <EVRevisionFormat>1.0.0+{chash:10}.{c:ymd}.B{build}</EVRevisionFormat>

Revision Format example with SemVer components: <EVRevisionFormat>{major}.{minor}.{patch}-{branch}+{chash:10}.{c:ymd}</EVRevisionFormat>

Project csproj Example:

<PropertyGroup>
	<EVRevisionFormat>{semtagver}+{chash:10}.{c:ymd}</EVRevisionFormat>
	<EVDefault>true</EVDefault>
	<EVInfo>true</EVInfo>
	<EVTagMatch>v[0-9]*</EVTagMatch>
	<EVRemoveTagV>true</EVRemoveTagV>
	<EVVcs>git</EVVcs>
	<EVCheckAllAttributes>true</EVCheckAllAttributes>
	<EVShowRevision>true</EVShowRevision>
	<EVBuildNumberFile>$(MSBuildProjectDirectory)\build.number</EVBuildNumberFile>
</PropertyGroup>

Default version example: <EVDefaultVersion>1.0.0</EVDefaultVersion>

The following MSBuild properties are supported:

EVRevisionFormat:

The revision format template. This is automatically detected from the AssemblyInfo file in your project, if it exists. It can be overridden for .NET Core/Standard projects.

EVDefault: boolean, default: true.

Specifies whether default version attributes are resolved to the determined version. This affects Version (AssemblyVersionAttribute). The Version identifies the assembly and must be dotted-numeric (max. 65535).

EVInfo: boolean, default: true.

Specifies whether the infor version attribute is resolved to the determined version. This affects InformationalVersion (AssemblyInfoVersionAttribute). It is a free descriptive text that may contain version names like "beta" or a VCS commit hash.

DefaultVersion:

Determines if we need to set a default version instead of the 0.0.0.1

EVTagMatch: glob pattern, default: v[0-9]*

The pattern of tag names to match when looking for version tags. These tag names usually look like "v0.1" or "v1.0.0". Other tags should be ignored for this use. This should usually not be changed.

EVRemoveTagV: boolean, default: true.

Specifies whether the "v" prefix of a matching version tag should be removed to determine its version. This should usually not be disabled.

EVVcs: string, default: "git".

Specifies the name of the VCS that is expected to be found in the project directory. Can be "git" or "svn" (IVcsProvider.Name).

EVShowRevision: boolean, default: false.

Specifies whether the determined revision ID is printed during the build with higher importance than normal, so it can be seen more easily. When patching the AssemblyInfo file, it is also displayed to the console.

EVProjectDirectory: string, default: $(MSBuildProjectDirectory).

Sets the directory where EV starts searching for the VCS files. This is helpful if EV is added to a project that is a submodule of another repository and should observe the parent repository.

EVReplaceMetadata: boolean, default: true.

Indicates whether the AssemblyMetadata attribute is processed

ChangedRepoErrorPattern: string, default: ".Release."

Determines the value of the build configuration RegEx pattern that triggers an error on match if the repository is modified

CheckAllAttributes: boolean, default: true.

Determines if we need to check all the custom attributes from the AssemblyInfo

EVBuildNumberFile: string, default: empty.

Path to a file that stores the build number counter. When set, the build number is read from this file, incremented by 1 on each build, and written back. The file is created automatically if it doesn't exist. Use the {build} placeholder in your revision format to include the build number.

Example:

<PropertyGroup>
  <EVBuildNumberFile>$(MSBuildProjectDirectory)\build.number</EVBuildNumberFile>
  <EVRevisionFormat>1.0.0+{chash:10}.{c:ymd}.B{build}</EVRevisionFormat>
</PropertyGroup>

EVFailOnDirty: boolean, default: false.

When enabled, the build will fail with an error if the repository has uncommitted changes. Useful for release builds to ensure only clean commits are versioned.

Example:

<PropertyGroup>
  <EVFailOnDirty>true</EVFailOnDirty>
</PropertyGroup>

EVVersionFile: string, default: empty.

Path to a file where the resolved version string will be written after each build. Useful for CI/CD pipelines that need to read the version from a file (e.g. for Docker tagging, deployment scripts, etc.).

Example:

<PropertyGroup>
  <EVVersionFile>$(MSBuildProjectDirectory)\version.txt</EVVersionFile>
</PropertyGroup>

EVQuiet: boolean, default: false.

When enabled, suppresses informational version messages during the build. Only warnings and errors will be shown.

Example:

<PropertyGroup>
  <EVQuiet>true</EVQuiet>
</PropertyGroup>

Revision format

You can customise the format of the resulting version with a revision format string that defines how information about the commit or revision is formatted into the final revision ID. It is a plain string that contains placeholders in {curly braces}.

The following data field placeholders are supported:

{chash}: Full commit hash.

{CHASH}: Full commit hash, in upper case.

{chash:<length>}: Commit hash truncated to the specified length. (Also for upper case)

{revnum}: Revision number.

{revnum-<offset>}: Revision number minus the offset. (Also available with +)

{!}: The "!" character if the working directory is modified, otherwise empty.

{!:<string>}: The specified string if the working directory is modified, otherwise empty.

{cname}, {cmail}: Committer’s name or e-mail address.

{aname}, {amail}: Author’s name or e-mail address.

{mname}: Build machine name (computer name).

{user}: Current OS username.

{os}: Operating system description (e.g. "Microsoft Windows 10.0.22631").

{arch}: Process architecture in lowercase (e.g. "x64", "arm64").

{rid}: Runtime identifier (e.g. "win-x64", "linux-arm64").

{tick}: Current UTC time as .NET ticks (useful for truly unique build identifiers).

{epoch}: Current UTC time as Unix epoch seconds.

{guid}: A newly generated GUID in standard "D" format (e.g. "550e8400-e29b-41d4-a716-446655440000").

{guid:<format>}: A newly generated GUID formatted with the given specifier ("N", "D", "B", or "P").

{build}: Build number counter (auto-incremented when EVBuildNumberFile is set).

{build:<length>}: Build number zero-padded to the specified length (e.g. {build:4}0042).

{major}: Major version component extracted from the tag (e.g. 1 from tag v1.2.3).

{minor}: Minor version component extracted from the tag.

{patch}: Patch version component extracted from the tag.

{prerelease}: Pre-release label from the tag (e.g. beta.1 from v1.0.0-beta.1).

{buildmeta}: Build metadata from the tag (the part after + in SemVer).

{dirty}: Outputs "dirty" if the working directory is modified, otherwise empty.

{dirty:<string>}: Outputs the specified string if the working directory is modified, otherwise empty.

{env:<NAME>}: Value of the environment variable <NAME> (useful for CI variables like BUILD_ID, GITHUB_RUN_NUMBER, etc.).

{utcnow:<format>}: Current UTC time formatted with a .NET date/time format string (e.g. {utcnow:yyyyMMddHHmmss}).

{now:<format>}: Current local time formatted with a .NET date/time format string (e.g. {now:yyyy-MM-dd}).

{branch}: Currently checked-out branch.

{branch:<sep>:<ref>}: Branch name, if not <ref> or empty, separated by <sep>, otherwise empty.

{semtagver}: Semantic version based on the most recent matching tag name. Revisions that are not directly tagged are considered a pre-release after the last tag (the patch value is incremented by 1) and the branch name and number of commits after the tag will be appended.

{semtagver+chash}: Semantic version based on the most recent matching tag name, see {semtagver}. Pre-releases also have the abbreviated commit hash appended after a plus (+) sign as build info. This is part of the default format for Git repositories.

{semtagver+chash:<length>}: Same as {semtagver+chash} but with the commit hash truncated to the specified length instead of the default 7.

{semtagver+CHASH:<length>}: Same as {semtagver+chash:<length>} but with the commit hash in upper case.

{semtagver:<development>}: Same as {semtagver} but with the branch name left out if it is equal to <development>.

{semtagver:<development>:+chash}: Same as {semtagver+chash} but with the branch name left out if it is equal to <development>.

{semtagver:<development>:+chash:<length>}: Same as {semtagver+chash:<length>} but with the branch name left out if it is equal to <development>.

{semtagver:<development>:+CHASH:<length>}: Same as {semtagver+CHASH:<length>} but with the branch name left out if it is equal to <development>.

{tag}: Most recent matching tag name, with additional info.

{tagname}: Most recent matching tag name only.

{tagadd}: Number of commits since the most recent matching tag.

{tagadd:<sep>}: Number of commits since the most recent matching tag, prefixed with <sep>, or empty.

{tz}: Local time zone offset like "+02:00".

{url}: Repository URL.

{copyright}: Abbreviation for the copyright year (commit or build time).

{copyright:<first>-}: Abbreviation for the copyright year range, starting at <first>. The following dash is optional but recommended for clearer understanding.

Revision format examples

Format Example output
1.0.0+{chash:10}.{c:ymd} 1.0.0+8dda362328.20240207
1.0.0+{chash:10}.{c:ymd}.B{build} 1.0.0+8dda362328.20240207.B42
{major}.{minor}.{patch}+{chash:10} 1.2.3+8dda362328
{major}.{minor}.{patch}-{branch}+{build:4} 1.2.3-feature-x+0005
{semtagver}+{dirty:.dirty}.{now:yyyyMMdd} 1.0.1-main.2+dirty.20240210
{major}.{minor}.{patch}+{env:BUILD_ID} 1.0.0+12345
{semtagver}+{user}@{mname} 1.0.0+john@DESKTOP-ABC
{semtagver}+{arch}.{epoch} 1.0.0+x64.1718291234
{major}.{minor}.{patch}+{rid} 1.2.3+win-x64
{semtagver}+{guid:N} 1.0.0+550e8400e29b41d4a716446655440000

Schemes

Schemes convert a commit or build time to a compact string representation. They can be used to assign incrementing versions if no revision number is provided by the VCS. First, select from the build, commit or authoring time with {b:…}, {c:…} or {a:…}. This is followed by the scheme name. There are 4 types of schemes.

The following time schemes are supported:

Readable date/time: Produces a readable date or time string in several formats.

Format Description
ymd Year, month, day, no separator.
ymd- Year, month, day, separated by "-".
ymd. Year, month, day, separated by ".".
hms Hour, minute, second, no separator.
hms- Hour, minute, second, separated by "-".
hms: Hour, minute, second, separated by ":".
hms. Hour, minute, second, separated by ".".
hm Hour, minute, no separator.
hm- Hour, minute, separated by "-".
hm: Hour, minute, separated by ":".
hm. Hour, minute, separated by ".".
h Hour only.

Prefix with "u" for UTC instead of local time zone.

Dotted-decimal: Generates regular dotted version numbers with two segments. The first describes the days since the base year, the second the number of intervals since midnight (UTC). This scheme consists of multiple colon-separated values: interval length, base year.

The interval length is a number followed by "s" for seconds, "m" for minutes, "h" for hours, or "d" for days. Practical intervals are "15m" (2 digits), "2m" (3 digits).

A shortcut to the 15-minute interval is {dmin:<year>}.

Base-encoding: Converts a linear value to a higher number base to create more compact digit/letter combinations. These schemes consist of multiple colon-separated values: number base, interval length, base year, minimum output length.

Number base can be from 2 to 36. The digits 0–9 and then letters a–z are used. The higher the base, the higher the chance that profane words appear in a revision ID. Base 28 uses an optimised alphabet without vowels and similar characters to avoid errors when hand-writing and undesired words.

The number of passed intervals since the base year is encoded for the result (UTC). The minimum length padding generates fixed-length comparable strings. Set the length to a value that lasts for as long as you plan to use this versioning scheme (30 years recommended). Practical combinations are "16:1m" (6 chars), "28:20m" (4 chars), "36:10m" (4 chars).

All letters are lower case. Use a capital {A:…}, {B:…} or {C:…} for upper case.

Hours: Generates a single number of hours passed since the given base year and month. This scheme begins with "h:" followed by two hyphen-separated values: base year, base month.

For values up to 65535 this lasts over 7 years.

Examples:

Format Description
{b:ymd-} Local build date, like "2024-02-10".
{c:hm.} Local commit time of day, like "23.59".
{c:uhm} UTC commit time of day, like "2359".
{c:15m:2023} Dotted decimal from commit time since 2023, like "365.95".
{dmin:2023} Same as previous (short syntax from version 1.x).
{c:16:1m:2024} Base-16 encoding of minutes from commit time since 2024, like "abcdef".
{b:28:20m:2023:4} Base-28 encoding of 20-minute intervals from build time since 2023.
{bmin:2023:4} Same as previous (short syntax from version 1.x).
{B:28:20m:2023:4} Base-28 encoding (upper case) of 20-minute intervals from build time since 2023".
{b:h:2024-02} Hours encoding of UTC build time since February 2024.

Usage in C# source code

The following sample code from the AssemblyInfo.cs file would be resolved as described.

[assembly: AssemblyVersion("0.0")]
[assembly: AssemblyInfoVersion("1.0.0{chash:10}.{c:ymd}")]

Result:

Version: 1.0.0 InformationalVersion: 1.0.0+05876ca02e+20240210

API PowerShell example (Windows, Linux, macOS with PowerShell):

Add-Type -Path EonaCat.Versioning.dll
[EonaCat.Versioning.Api]::GetVersion()

API Bash example (Linux, macOS):

#!/bin/bash
dotnet script -e 'Console.WriteLine(EonaCat.Versioning.Api.GetVersion())'

API Batch example (Windows):

@echo off
powershell -Command "Add-Type -Path EonaCat.Versioning.dll; [EonaCat.Versioning.Api]::GetVersion()"
exit /b %errorlevel%

VCS providers

Git

The Git CLI must be available on your system:

  • Windows: Install Git for Windows. The binary is auto-detected from the PATH, registry, %ProgramFiles%\Git*, SourceTree, Tower, or SmartGit locations.
  • Linux: Install via your package manager (e.g. sudo apt install git, sudo dnf install git).
  • macOS: Install via Xcode Command Line Tools (xcode-select --install) or Homebrew (brew install git).

On Linux and macOS, the git binary must be available in your PATH.

The revision number is provided by counting revisions with the --first-parent option in the current branch. This is a stable value for the master branch if merges from other branches are done the correct way (always merge temporary/work/feature branches into master, not reverse).

Subversion

The SVN CLI (svn and svnversion) must be available on your system:

  • Windows: Install TortoiseSVN with the "CLI" option, or CollabNet SVN. Auto-detected from the PATH, registry, and %ProgramFiles% locations.
  • Linux: Install via your package manager (e.g. sudo apt install subversion).
  • macOS: Install via Homebrew (brew install subversion).

On Linux and macOS, the svn and svnversion binaries must be available in your PATH.

Semantic Versioning API

EonaCat.Versioning includes a full Semantic Versioning 2.0.0 implementation for parsing, comparing, sorting, bumping and validating version strings.

SemanticVersion class

using EonaCat.Versioning;

// Parse a version string
var version = SemanticVersion.Parse("1.2.3-beta.1+build.42");

// Access components
Console.WriteLine(version.Major);        // 1
Console.WriteLine(version.Minor);        // 2
Console.WriteLine(version.Patch);        // 3
Console.WriteLine(version.PreRelease);   // "beta.1"
Console.WriteLine(version.BuildMetadata);// "build.42"
Console.WriteLine(version.IsPreRelease); // true
Console.WriteLine(version.IsStable);     // false

// Safe parsing
if (SemanticVersion.TryParse("not-a-version", out var v))
{
    // ...
}

// Validation
bool valid = SemanticVersion.IsValid("1.0.0"); // true

// Bump versions
var next = version.BumpMinor();  // 1.3.0
var major = version.BumpMajor(); // 2.0.0
var patch = version.BumpPatch(); // 1.2.4

// Modify labels
var rc = version.WithPreRelease("rc.1");   // 1.2.3-rc.1+build.42
var release = version.ToRelease();          // 1.2.3

// Comparison (follows SemVer 2.0.0 precedence)
bool isNewer = SemanticVersion.Parse("2.0.0") > SemanticVersion.Parse("1.9.9"); // true

// Tag string
Console.WriteLine(version.ToTagString()); // "v1.2.3-beta.1+build.42"

Version Range Matching

using EonaCat.Versioning;

var version = SemanticVersion.Parse("1.5.0");

// Simple comparisons
version.Satisfies(">=1.0.0");  // true
version.Satisfies("<2.0.0");   // true
version.Satisfies("!=1.5.0");  // false

// Caret range (compatible with): ^1.2.0 means >=1.2.0 <2.0.0
version.Satisfies("^1.2.0");   // true

// Tilde range (patch-level): ~1.5.0 means >=1.5.0 <1.6.0
version.Satisfies("~1.5.0");   // true

// VersionRange class for complex ranges
var range = new VersionRange(">=1.0.0 <2.0.0 || >=3.0.0");
range.IsSatisfiedBy(version);  // true

// Filter and find max from a list
var versions = new List<SemanticVersion>
{
    SemanticVersion.Parse("1.0.0"),
    SemanticVersion.Parse("1.5.0"),
    SemanticVersion.Parse("2.0.0"),
};
var filtered = range.Filter(versions);        // [1.0.0, 1.5.0]
var max = range.MaxSatisfying(versions);      // 1.5.0

Version Bumping with Enum

using EonaCat.Versioning;

var current = SemanticVersion.Parse("1.2.3");

// Bump by type
var bumped = current.Bump(VersionBumpType.Minor);  // 1.3.0
bumped = current.Bump(VersionBumpType.Major);       // 2.0.0
bumped = current.Bump(VersionBumpType.Patch, "rc.1"); // 1.2.4-rc.1

Conventional Commits Analysis

Automatically determine the version bump type by analyzing commit messages following the Conventional Commits specification.

using EonaCat.Versioning;

// Single message analysis
ConventionalCommitAnalyzer.AnalyzeMessage("feat: add new feature");       // Minor
ConventionalCommitAnalyzer.AnalyzeMessage("fix: correct typo");           // Patch
ConventionalCommitAnalyzer.AnalyzeMessage("feat!: breaking change");      // Major
ConventionalCommitAnalyzer.AnalyzeMessage("refactor: clean up code");     // Patch

// Check if a message follows the convention
ConventionalCommitAnalyzer.IsConventionalCommit("feat(api): new endpoint"); // true
ConventionalCommitAnalyzer.GetCommitType("feat(api): new endpoint");        // "feat"
ConventionalCommitAnalyzer.GetCommitScope("feat(api): new endpoint");       // "api"

// Analyze multiple messages to get the highest bump
var messages = new[]
{
    "fix: patch change",
    "feat: minor change",
    "docs: update readme"
};
var bump = ConventionalCommitAnalyzer.AnalyzeMessages(messages); // Minor

// Combine with SemanticVersion
var current = SemanticVersion.Parse("1.2.3");
var next = current.Bump(bump); // 1.3.0

Interactive API Extensions

The Api class provides additional methods for querying VCS state:

using EonaCat.Versioning;

var api = new Api(projectDir: @"C:\MyProject");

// Get a SemanticVersion object
SemanticVersion semver = api.GetSemanticVersion();

// Bump with a specific type
SemanticVersion next = api.GetBumpedVersion(VersionBumpType.Minor);

// Query VCS state
string branch    = api.GetBranch();
string hash      = api.GetCommitHash();
bool   dirty     = api.IsDirty();
int    count     = api.GetCommitCount();
int    afterTag  = api.GetCommitsAfterTag();
string tag       = api.GetTag();

// Get all version info as a dictionary
var info = api.GetVersionInfo();
foreach (var kv in info)
{
    Console.WriteLine($"{kv.Key}: {kv.Value}");
}

Helper Extensions

The VersionHelper class in EonaCat.Versioning.Helpers provides additional methods:

using EonaCat.Versioning.Helpers;

// Get individual version components
int major = VersionHelper.GetMajorVersion();
int minor = VersionHelper.GetMinorVersion();
int patch = VersionHelper.GetPatchVersion();

// Get pre-release and build metadata from informational version
string preRelease = VersionHelper.GetPreReleaseLabel();    // e.g. "beta.1"
string buildMeta  = VersionHelper.GetBuildMetadata();      // e.g. "abc123.20240210"
bool   isPreRel   = VersionHelper.IsPreRelease();

// Get a formatted display string
string display = VersionHelper.GetFormattedVersion();      // e.g. "MyApp v1.2.3-beta+abc123"
string product = VersionHelper.GetProductName();

Additional Format Placeholders

The following additional placeholders are available in revision format strings:

{commitcount}: Total number of commits (same as {revnum}, for clarity).

{shortbranch}: The last segment of the branch name after / (e.g. my-feature from feature/my-feature).

{commitsaftertag}: Number of additional commits since the last matching tag (same as {tagadd}, for clarity).

Revision format examples (extended)

Format Example output
{major}.{minor}.{patch}+{commitcount} 1.2.3+42
{semtagver}-{shortbranch}+{chash:8} 1.0.1-my-feature+8dda3623
{major}.{minor}.{patch}+{commitsaftertag}.{dirty} 1.0.0+5.dirty

Versioning Strategies

EonaCat.Versioning supports multiple versioning strategies beyond standard SemVer. Each strategy is available as a standalone class that can be used independently or combined.

semantic-release / Release Please

Automatically determine the next release version and generate changelogs from conventional commit messages, compatible with both semantic-release and Release Please.

using EonaCat.Versioning;

var commits = new[]
{
    "feat(api): add user endpoint",
    "fix: correct null reference in parser",
    "docs: update README",
    "feat!: redesign authentication flow"
};

// Determine next version
var next = ReleaseVersion.GetNextVersion("1.2.3", commits);
// => 2.0.0 (breaking change detected)

// With a pre-release channel (e.g. beta releases)
var beta = ReleaseVersion.GetNextVersion("1.2.3", commits, preReleaseChannel: "beta", preReleaseNumber: 1);
// => 2.0.0-beta.1

// Check if commits warrant a release
bool shouldRelease = ReleaseVersion.ShouldRelease(commits); // true

// Generate a changelog
string changelog = ReleaseVersion.GenerateChangelog(next, commits);
// Produces grouped Markdown: Breaking Changes, Features, Bug Fixes, etc.

// Generate a Release Please-style manifest entry
string manifest = ReleaseVersion.GenerateManifestEntry("MyPackage", next);
// => { "MyPackage": "2.0.0" }

Git SHA Deploys

Use Git commit SHAs as deploy identifiers - ideal for continuous deployment pipelines, container image tagging, and environments where every commit is a deployable artifact.

using EonaCat.Versioning;

// Create from a commit hash
var sha = new GitShaVersion("8dda362328abcdef1234567890abcdef12345678");

// Deploy tags
sha.ToDeployTag();              // "sha-8dda3623"
sha.ToImageTag("myapp");        // "myapp:sha-8dda3623"

// Attach to a semantic version as build metadata
var withBase = GitShaVersion.FromVersion("8dda362328ab", "1.0.0");
withBase.ToSemanticVersion();    // 1.0.0+sha.8dda3623
withBase.ToString();             // "1.0.0+sha.8dda3623"

// Validate a SHA string
GitShaVersion.IsValidSha("8dda362328ab"); // true
GitShaVersion.IsValidSha("not-a-sha");    // false

CalVer + Build Metadata

Calendar Versioning (CalVer) uses date-based version components. EonaCat.Versioning supports CalVer with optional modifiers and build metadata. See calver.org for the specification.

using EonaCat.Versioning;

// Create from current date
var calver = CalendarVersion.Today();           // e.g. 2024.6.15
var monthly = CalendarVersion.Now(micro: 3);    // e.g. 2024.6.3

// Parse a CalVer string
var parsed = CalendarVersion.Parse("2024.6.15-beta+build.42");
Console.WriteLine(parsed.Year);          // 2024
Console.WriteLine(parsed.Month);         // 6
Console.WriteLine(parsed.Micro);         // 15
Console.WriteLine(parsed.Modifier);      // "beta"
Console.WriteLine(parsed.BuildMetadata); // "build.42"

// Add Git SHA as build metadata
var withSha = calver.WithGitSha("8dda362328abcdef");
// => 2024.6.15+8dda362

// Bump micro, add modifier
var next = calver.BumpMicro().WithModifier("rc.1");
// => 2024.6.16-rc.1

// Convert to SemanticVersion (Year.Month.Micro)
SemanticVersion semver = calver.ToSemanticVersion();

// Short year format (YY.MM.DD)
var short = CalendarVersion.Today(shortYear: true); // e.g. 24.6.15

// Comparison
bool newer = CalendarVersion.Parse("2024.7.1") > CalendarVersion.Parse("2024.6.30"); // true

Changesets

Changesets is a versioning approach where version bump intent is declared in Markdown files that can be reviewed in pull requests. Each changeset file specifies which packages are affected and the bump level.

using EonaCat.Versioning;

// Generate a changeset file
string content = Changeset.Generate("MyPackage", ChangesetBumpLevel.Minor, "Added new search feature");
// Produces:
// ---
// "MyPackage": minor
// ---
//
// Added new search feature

// Parse a changeset file
var entries = Changeset.Parse(content);
// entries[0].PackageName  => "MyPackage"
// entries[0].BumpLevel    => ChangesetBumpLevel.Minor
// entries[0].Summary      => "Added new search feature"

// Apply changesets to current versions
var currentVersions = new Dictionary<string, string>
{
    { "MyPackage", "1.2.3" },
    { "MyOtherPackage", "2.0.0" }
};
var allEntries = new List<ChangesetEntry>
{
    new ChangesetEntry("MyPackage", ChangesetBumpLevel.Minor, "Added search"),
    new ChangesetEntry("MyPackage", ChangesetBumpLevel.Patch, "Fixed typo"),
    new ChangesetEntry("MyOtherPackage", ChangesetBumpLevel.Major, "Breaking API change")
};

var newVersions = Changeset.ApplyChangesets(currentVersions, allEntries);
// newVersions["MyPackage"]      => 1.3.0 (highest bump: minor)
// newVersions["MyOtherPackage"] => 3.0.0 (highest bump: major)

// Generate a combined changelog
string changelog = Changeset.GenerateChangelog(newVersions, allEntries);

Compatibility & Distance

using EonaCat.Versioning;

var v1 = SemanticVersion.Parse("1.5.0");
var v2 = SemanticVersion.Parse("1.2.0");
var v3 = SemanticVersion.Parse("2.0.0");

// Check API compatibility (same major, this >= other)
v1.IsCompatibleWith(v2); // true  - 1.5.0 is compatible with 1.2.0
v1.IsCompatibleWith(v3); // false - different major

// Measure distance between versions
var dist = v1.Distance(v3);
// dist.Major = 1, dist.Minor = 5, dist.Patch = 0

// Implicit string conversion
SemanticVersion v = "3.1.4";
Console.WriteLine(v.Major); // 3

Complete MSBuild Property Reference

Input Properties

Property Type Default Description
EVRevisionFormat string {semtagver}+{chash:10}.{c:ymd} The revision format template
EVDefaultVersion string 0.0.1 Fallback version when no tag is found
EVDefault bool true Resolve Version / AssemblyVersionAttribute
EVInfo bool true Resolve InformationalVersion
EVTagMatch glob v[0-9]* Tag name matching pattern
EVRemoveTagV bool true Strip leading "v" from tags
EVVcs string git Expected VCS (git or svn)
EVShowRevision bool false Print resolved version during build
EVProjectDirectory string $(MSBuildProjectDirectory) VCS search start directory
EVReplaceMetadata bool true Process AssemblyMetadata attribute
EVCheckAllAttributes bool true Check all custom AssemblyInfo attributes
EVBuildNumberFile string (empty) Path to build number counter file
EVFailOnDirty bool false Fail build if repository is modified
EVVersionFile string (empty) Write resolved version to this file
EVQuiet bool false Suppress informational build messages
ChangedRepoErrorPattern regex .*Release.* Configuration pattern that triggers error on dirty repo
EVVersionJsonFile string (empty) Write version metadata as JSON to this file
EVRequireTag bool false Fail build if no VCS tag found
EVVersionPrefix string (empty) Prefix prepended to version (e.g. v)
EVVersionSuffix string (empty) Suffix appended to version (e.g. -preview)
EVPreReleaseLabel string (empty) Fixed pre-release label to always append (e.g. alpha)
EVBuildMetadataLabel string (empty) Fixed build metadata to always append (e.g. CI job ID)
EVForceVersion string (empty) Force exact version, bypassing VCS resolution
EVStampAssemblyVersion bool true Whether to stamp AssemblyVersion
EVStampFileVersion bool true Whether to stamp FileVersion
EVStampPackageVersion bool true Whether to stamp PackageVersion
EVStampInformationalVersion bool true Whether to stamp InformationalVersion
EVDisable bool false Kill switch - disable all EonaCat versioning
EVSkipPatch bool false Skip AssemblyInfo patching
EVAutoIncrementPatch bool false Auto-increment patch on each build
EVAutoIncrementMinor bool false Auto-increment minor on each build
EVBuildNumberReset bool false Reset build number to 0 when version changes
EVBuildNumberPadding int 0 Pad build number to this many digits (e.g. 40042)
EVTagPrefix string (empty) Tag prefix to strip (alternative to EVRemoveTagV)
EVDefaultBranch string main Default/main branch name for semtagver logic
EVDirtyMarker string dirty String output when repo is dirty
EVCleanMarker string (empty) String output when repo is clean
EVRequireStable bool false Fail build if resolved version is pre-release
EVRequireSemVer bool false Fail build if version is not valid SemVer 2.0.0
EVMaxVersion string (empty) Maximum allowed version (build fails if exceeded)
EVMinVersion string (empty) Minimum allowed version (build fails if below)
EVForbiddenBranches string (empty) Semicolon-separated branch names where builds are forbidden
EVAllowedChannels string (empty) Semicolon-separated allowed pre-release channels
EVWarnOnPreRelease bool false Warn (don't fail) when version is pre-release
EVWarnOnNonDefaultBranch bool false Warn when not building on default branch
EVFailOnDetachedHead bool false Fail build on detached HEAD
EVMaxCommitsAfterTag int 0 Max commits after tag before build fails (0 = unlimited)
EVVersionYamlFile string (empty) Write version metadata as YAML to this file
EVVersionXmlFile string (empty) Write version metadata as XML to this file
EVVersionEnvFile string (empty) Write version as shell env file (KEY=VALUE)
EVVersionHeaderFile string (empty) Write version as C/C++ header file
EVVersionPropsFile string (empty) Write version as .props file for other projects
EVVersionCsvFile string (empty) Write version metadata as CSV
EVVersionTomlFile string (empty) Write version metadata as TOML
EVVersionIniFile string (empty) Write version metadata as INI
EVVersionSqlFile string (empty) Write version as SQL INSERT script
EVVersionBadgeFile string (empty) Write Markdown badge to this file
EVGitHubActionsOutput bool false Write GitHub Actions ::set-output commands
EVAzureDevOpsOutput bool false Write Azure DevOps ##vso commands
EVTeamCityOutput bool false Write TeamCity service messages
EVGitLabCIOutput bool false Write GitLab CI variable exports
EVSetEnvironmentVariables bool false Set environment variables in current process
EVEnvVariablePrefix string EV_ Prefix for environment variable names
EVDockerImageName string (empty) Docker image name for tag generation
EVDockerRegistry string (empty) Docker registry URL for full image path
EVCopyrightHolder string (empty) Copyright holder name
EVCopyrightStartYear int 0 Copyright start year for year-range generation
EVLogLevel string info Log level: trace, info, warning, error
EVLogFile string (empty) Path to write a build version log
EVTimestampFormat string o .NET format string for build timestamp
EVTimestampTimeZone string (empty) Time zone ID for timestamps (default: UTC)
EVCustomPlaceholders string (empty) Semicolon-separated custom placeholders (key=value)
EVAdditionalFormats string (empty) Semicolon-separated additional format templates to resolve
EVIncludeProjectHash bool false Include project file hash in build metadata
EVIncludeTargetFramework bool false Include target framework in build metadata
EVDeterministic bool false Generate deterministic version (no timestamps/random)
EVVersionCacheFile string (empty) Cache file for last resolved version
EVUseCache bool false Skip version generation if cache is up to date
EVExtraJsonProperties string (empty) Semicolon-separated extra properties for JSON output
EVNuGetCompatible bool false Produce NuGet-compatible version (strip build metadata)
EVCalVerBaseYear int 0 Base year for CalVer versioning
EVCalVerShortYear bool false Use 2-digit year in CalVer
EVAssemblyName string $(AssemblyName) Assembly name override
EVProductName string $(Product) Product name for metadata
EVCompanyName string $(Company) Company name for metadata
EVMajorBumpTypes string (empty) Semicolon-separated commit types that trigger major bump
EVMinorBumpTypes string (empty) Semicolon-separated commit types that trigger minor bump
EVConventionalCommitsEnabled bool false Enable conventional commits analysis
EVMaxCommitsToAnalyze int 0 Max commits to analyze (0 = unlimited)
EVAppendBranchToPreRelease bool false Append branch name to pre-release versions
EVPreReleaseBranchPattern regex (empty) Branch pattern that produces pre-release versions
EVReleaseBranchPattern regex (empty) Branch pattern that produces stable releases
EVSanitizeBranchName bool false Sanitize branch name for SemVer pre-release use
EVBranchNameMaxLength int 0 Max length for branch name in version strings
EVVersionSeparator string . Separator between version components
EVWriteOutputVersion bool false Write .version file to output directory
EVGitHubEnvFile bool false Append version to $GITHUB_ENV file
EVGitHubEnvFilePath string (empty) Custom path for GITHUB_ENV file
EVHashAlgorithm string SHA256 Hash algorithm for checksum generation (SHA256, SHA512, MD5)
EVGenerateChecksum bool false Generate a checksum file alongside the version file
EVChecksumFile string (empty) Path to write checksum file
EVGenerateSbom bool false Generate a Software Bill of Materials file
EVSbomFormat string CycloneDX SBOM format: CycloneDX or SPDX
EVSbomFile string (empty) Path to write SBOM file
EVMonorepoRoot string (empty) Root path of the monorepo
EVProjectScope string (empty) Package/project scope name within a monorepo
EVIndependentVersioning bool false Version each project independently in a monorepo
EVSyncVersions bool false Synchronize all project versions to the same value
EVChangesetDir string (empty) Directory containing changeset markdown files
EVConsumeChangesets bool false Auto-consume changeset files during build
EVAutoTag bool false Automatically create a git tag after version generation
EVAutoTagPrefix string v Prefix for auto-created tags
EVAutoTagMessage string (empty) Message template for auto-created tags
EVChangelogFile string (empty) Path to CHANGELOG.md for auto-generation
EVChangelogFormat string keepachangelog Changelog format: keepachangelog or conventional
EVAutoChangelog bool false Auto-generate changelog from commit messages
EVReleaseNotesFile string (empty) Path to write release notes file
EVAutoReleaseNotes bool false Auto-generate release notes from commits
EVWebhookUrl string (empty) Webhook URL to POST version info after build
EVWebhookOnRelease bool false Send webhook notification on release builds
EVSlackWebhook string (empty) Slack incoming webhook URL for version notifications
EVTeamsWebhook string (empty) Microsoft Teams webhook URL for version notifications
EVNotifyOnMajor bool false Notify on major version bumps only
EVBuildAgent string (empty) CI build agent name
EVBuildUrl string (empty) CI build URL for traceability
EVBuildPipelineId string (empty) CI pipeline identifier
EVBuildJobId string (empty) CI job identifier
EVSourceBranch string (empty) Source branch for pull requests
EVTargetBranch string (empty) Target branch for pull requests
EVPullRequestId string (empty) Pull request number or ID
EVBuildReason string (empty) Build trigger reason (manual, CI, schedule, webhook)
EVAppleBundleVersionBase int 0 Apple CFBundleVersion base number
EVAndroidVersionCodeBase int 0 Base offset for Android versionCode calculation
EVAndroidVersionCodeScheme string semver Android versionCode scheme: semver or timestamp
EVFlutterBuildNumber int 0 Flutter build number for pubspec.yaml
EVUnityVersion bool false Generate Unity-compatible version output
EVElectronVersion bool false Generate Electron-compatible version output
EVJsonIndented bool false Pretty-print JSON output with indentation
EVXmlNamespace string (empty) XML namespace URI for version XML files
EVOutputEncoding string utf-8 Output file encoding: utf-8, utf-8-bom, ascii
EVLineEnding string auto Line ending style: crlf, lf, auto
EVBuildNumberStrategy string increment Build number strategy: increment, timestamp, hash
EVVersionTemplate string (empty) Custom version template for non-standard schemes
EVVersionRegex string (empty) Regex pattern to validate the final resolved version
EVBumpStrategy string semver Bump strategy: semver, calver, auto
EVVersionLock bool false Lock version to current value (no auto-increment)
EVVersionLockFile string (empty) Path to version lock file
EVSnapshotSuffix string -SNAPSHOT Suffix for snapshot versions
EVNightlySuffix string -nightly Suffix for nightly versions
EVDevVersionFormat string (empty) Format for development versions
EVRcNumberStart int 1 Starting number for RC pre-release versions
EVPreReleaseNumberStart int 1 Starting number for pre-release versions
EVGitDepth int 0 Git depth for shallow clones (0 = full)
EVGitFetchTags bool false Fetch tags before version resolution
EVGitRemote string origin Git remote name
EVUseGitDescribe bool false Use git describe for version resolution
EVGitDescribeArgs string (empty) Extra arguments passed to git describe
EVGitSubmoduleVersioning bool false Include submodule version info in metadata
EVRequireChangelog bool false Require a changelog entry for the current version
EVMaxPatchVersion int 0 Maximum allowed patch version (0 = unlimited)
EVMaxMinorVersion int 0 Maximum allowed minor version (0 = unlimited)
EVMaxMajorVersion int 0 Maximum allowed major version (0 = unlimited)
EVAllowDowngrade bool false Allow version downgrades
EVRequireCI bool false Require a CI environment to build
EVAllowLocalBuild bool true Allow local (non-CI) builds
EVBackupVersionFile bool false Backup version files before modification
EVBackupDir string (empty) Directory for version file backups
EVRollbackOnFailure bool false Rollback version changes on build failure
EVCompatibilityMode string strict Compatibility mode: strict or loose
EVNuGetV2Compatible bool false Generate NuGet v2-compatible version strings
EVLegacyVersionFormat bool false Use legacy 4-part version format
EVJenkinsOutput bool false Write Jenkins-compatible env vars to stdout
EVBitbucketOutput bool false Write Bitbucket Pipelines export lines
EVCircleCIOutput bool false Write CircleCI env export lines
EVAppVeyorOutput bool false Write AppVeyor service messages
EVTravisCIOutput bool false Write TravisCI export lines
EVAWSCodeBuildOutput bool false Write AWS CodeBuild env exports
EVCloudBuildOutput bool false Write Google Cloud Build substitutions
EVCSharpVersionFile string (empty) Path to write generated C# version constants file
EVCSharpNamespace string (empty) Namespace for generated C# version file
EVTypeScriptVersionFile string (empty) Path to write generated TypeScript version file
EVPythonVersionFile string (empty) Path to write generated Python version file
EVGoVersionFile string (empty) Path to write generated Go version file
EVRustVersionFile string (empty) Path to write generated Rust version file
EVSwiftVersionFile string (empty) Path to write generated Swift version file
EVKotlinVersionFile string (empty) Path to write generated Kotlin version file
EVJavaVersionFile string (empty) Path to write generated Java version file
EVJavaPackageName string (empty) Java package name for generated version class
EVDartVersionFile string (empty) Path to write generated Dart version file
EVPhpVersionFile string (empty) Path to write generated PHP version file
EVRubyVersionFile string (empty) Path to write generated Ruby version file

Output Properties

After the EVGenerateVersion target runs, the following MSBuild properties are available for use in subsequent targets:

Property Description
EonaCatVersion The full resolved EonaCat version string
BuildTimestamp Build timestamp in ISO 8601 UTC format
EVCommitHash Full commit hash
EVCommitHashShort Short commit hash (first 7 characters)
EVBranchName Current branch name
EVShortBranchName Last segment of branch after /
EVSafeBranchName Branch name sanitized for SemVer use
EVTagName Most recent matching tag
EVCommitsAfterTag Commits since last tag
EVRevisionNumber Total revision/commit number
EVCommitterName Committer's name
EVCommitterEmail Committer's email
EVAuthorName Author's name
EVAuthorEmail Author's email
EVRepositoryUrl Repository URL
EVIsDirty true / false - whether repo has uncommitted changes
EVCommitDate Commit date (ISO 8601)
EVAuthorDate Author date (ISO 8601)
EVMajorVersion Major version component
EVMinorVersion Minor version component
EVPatchVersion Patch version component
EVPreRelease Pre-release label
EVBuildMeta Build metadata
EVBuildNumber Resolved build number
EVIsPreRelease true / false - whether version is pre-release
EVIsTagged true / false - whether a VCS tag was found
EVCommitCount Total commit count
EVBuildDate Build date (yyyy-MM-dd)
EVBuildMachine Build machine hostname
EVOsDescription OS description
EVProcessArch Process architecture (e.g. x64)
EVRuntimeId Runtime identifier (e.g. win-x64)
EVUserName Current OS user name
EVNuGetVersion NuGet-compatible version (no build metadata)
EVAssemblyVersion Assembly version (major.minor.0.0)
EVFileVersion File version (major.minor.patch.0)
EVDockerTag Docker image tag (if EVDockerImageName set)
EVDockerImageTag Full Docker image path with tag
EVVersionOrdinal Sortable integer (major×1000000 + minor×1000 + patch)
EVBuildEpoch Unix epoch seconds at build time
EVBuildTicks .NET ticks at build time
EVVersionTag Version as tag string (v1.2.3)
EVVersionMSBuildXml Version as MSBuild XML element
EVGitHubActionsVersionOutput GitHub Actions set-output command
EVAzureDevOpsBuildNumber Azure DevOps build number command
EVTeamCityBuildNumber TeamCity build number service message
EVCalVerVersion CalVer version (YYYY.MM.DD)
EVAdditionalVersions Resolved additional format strings
EVFullCopyright Full copyright string with holder and year
EVVcsProviderName VCS provider name used
EVShortVersion Short version (major.minor)
EVWindowsVersion Windows 4-part version (major.minor.patch.build)
EVAndroidVersionCode Android versionCode integer
EVBadgeUrl Shields.io badge URL
EVVersionJson Full version metadata as JSON string
EVVersionYaml Full version metadata as YAML string
EVFullVersion Full 4-part version (major.minor.patch.revision)
EVSemVer2Version SemVer 2.0.0 compatible version string
EVNuGetV2Version NuGet v2-compatible version (max 3 parts, no dots in pre-release)
EVPep440Version PEP 440 (Python) compatible version
EVGemVersion Ruby gem-style version
EVMavenVersion Maven-compatible version string
EVDebianVersion Debian package version string
EVRpmVersion RPM package version string
EVAppleShortVersion Apple CFBundleShortVersionString
EVAppleBundleVersion Apple CFBundleVersion
EVFlutterVersion Flutter-compatible version (version+build)
EVHelmVersion Helm chart-compatible version
EVTerraformConstraint Terraform constraint (~> major.minor)
EVChocolateyVersion Chocolatey-compatible version
EVSnapVersion Snap-compatible version
EVFlatpakVersion Flatpak-compatible version
EVWixVersion WiX installer-compatible version (clamped limits)
EVOciTag OCI/container tag-safe version
EVFullDockerImagePath Full Docker image path with registry, name, and tag
EVDockerLatestTag Docker latest tag string
EVDockerMajorTag Docker major version tag (e.g. myapp:1)
EVDockerMinorTag Docker major.minor tag (e.g. myapp:1.2)
EVJenkinsBuildNumber Jenkins-compatible version string
EVBitbucketVersionOutput Bitbucket Pipelines variable export
EVCircleCIVersionOutput CircleCI env export string
EVAppVeyorBuildVersion AppVeyor build number update string
EVTravisCIVersionOutput TravisCI env export string
EVGitLabDotEnvVersion GitLab CI DOTENV artifact line
EVBuildYear Build year (4 digit)
EVBuildMonth Build month (1-12)
EVBuildDay Build day of month (1-31)
EVBuildHour Build hour (0-23)
EVBuildMinute Build minute (0-59)
EVBuildSecond Build second (0-59)
EVBuildDayOfYear Build day of year (1-366)
EVBuildWeekOfYear Build week of year (ISO 8601)
EVBuildQuarter Build quarter (1-4)
EVCommitSubject Commit message subject (first line)
EVCommitBody Commit message body (lines after first)
EVDirtyFileCount Number of files changed in working directory
EVMatchingTagCount Number of tags matching the pattern
EVPreviousTag Previous tag name (second most recent)
EVCommitDepth Commit depth (total ancestors in first-parent chain)
EVHeadRef Current git HEAD reference
EVIsDetachedHead true / false - whether HEAD is detached
EVIsDirectlyTagged true / false - whether current commit is directly tagged
EVIsClean true / false - whether working directory is clean
EVStashCount Number of stashed entries
EVRemoteName Name of the remote (e.g. origin)
EVRemoteUrl Remote URL of the repository
EVRepoSlug GitHub-style repository slug (owner/repo)
EVRepoName Repository name only
EVRepoOwner Repository owner
EVHostingProvider Hosting provider (github, gitlab, bitbucket, azure, unknown)
EVCloneUrlHttps HTTPS clone URL
EVCloneUrlSsh SSH clone URL
EVCommitUrl Web URL to the commit on the hosting provider
EVCompareUrl Web URL to compare view between tag and HEAD
EVFullAssemblyVersion Assembly version (major.minor.build.0)
EVFullFileVersion File version with build (major.minor.patch.build)
EVProductVersion Product version (same as InformationalVersion)
EVPreReleaseChannel Pre-release channel name only (alpha, beta, rc)
EVPreReleaseNumber Pre-release number only (e.g. 1 from beta.1)
EVIsStable true / false - whether version is a stable release
EVIsDevelopment true / false - whether version is in 0.x.x range
EVIsCI true / false - whether build is running in CI
EVCIPlatform Detected CI platform name
EVProjectHash Checksum/hash of the project file
EVVersionHash SHA256 hash of the resolved version string
EVDotNetRuntimeVersion .NET runtime version used during build
EVDotNetSdkVersion .NET SDK version used during build
EVTargetFrameworkOutput Target framework moniker used in the build
EVMSBuildVersion MSBuild version
EVCSharpVersionConstant Generated C# version constant source code
EVCDefineBlock Generated C/C++ #define source code
EVBashExports Generated bash export statements
EVPowerShellVars Generated PowerShell variable assignments
EVPackageJsonVersion package.json compatible version line
EVBadgeMarkdown Markdown badge image string
EVHtmlMetaVersion HTML meta tag with version
EVVersionToml TOML version string
EVVersionIni INI-formatted version string
EVVersionEnv ENV-formatted version string
EVVersionCsv CSV-formatted version record
EVVersionSql SQL INSERT statement for the version
EVVersionXml XML-formatted version record
EVVersionProps Version as MSBuild properties file content
EVBuildBadgeUrl Shields.io URL for a "build passing" badge
EVConventionalBumpType Conventional commit bump type (Major, Minor, Patch, None)
EVVersionOrdinalHex Version ordinal as hex string
EVSortableVersion Sortable zero-padded version (001.002.003)

Using Output Properties

You can reference any output property in subsequent MSBuild targets or in your project file:

<PropertyGroup>
  <EVDockerImageName>myregistry/myapp</EVDockerImageName>
  <EVCopyrightHolder>My Company</EVCopyrightHolder>
  <EVCopyrightStartYear>2020</EVCopyrightStartYear>
  <EVGitHubActionsOutput>true</EVGitHubActionsOutput>
</PropertyGroup>


<Target Name="PrintVersionInfo" AfterTargets="EVGenerateVersion">
  <Message Text="Version: $(EonaCatVersion)" Importance="High" />
  <Message Text="Commit: $(EVCommitHash)" Importance="High" />
  <Message Text="Branch: $(EVBranchName)" Importance="High" />
  <Message Text="Docker: $(EVDockerTag)" Importance="High" />
  <Message Text="NuGet: $(EVNuGetVersion)" Importance="High" />
  <Message Text="Copyright: $(EVFullCopyright)" Importance="High" />
  <Message Text="Is dirty: $(EVIsDirty)" Importance="High" />
  <Message Text="CalVer: $(EVCalVerVersion)" Importance="High" />
</Target>

Example: CI/CD Pipeline Configuration

<PropertyGroup>
  
  <EVGitHubActionsOutput>true</EVGitHubActionsOutput>
  <EVGitHubEnvFile>true</EVGitHubEnvFile>

  
  <EVAzureDevOpsOutput>true</EVAzureDevOpsOutput>

  
  <EVTeamCityOutput>true</EVTeamCityOutput>

  
  <EVSetEnvironmentVariables>true</EVSetEnvironmentVariables>
  <EVEnvVariablePrefix>BUILD_</EVEnvVariablePrefix>
</PropertyGroup>

Example: Version Policy Enforcement

<PropertyGroup>
  
  <EVRequireStable Condition="$(Configuration) == 'Release'">true</EVRequireStable>

  
  <EVMaxCommitsAfterTag>50</EVMaxCommitsAfterTag>

  
  <EVForbiddenBranches>deprecated;archived</EVForbiddenBranches>

  
  <EVWarnOnNonDefaultBranch>true</EVWarnOnNonDefaultBranch>
  <EVDefaultBranch>main</EVDefaultBranch>

  
  <EVMinVersion>1.0.0</EVMinVersion>
  <EVMaxVersion>99.0.0</EVMaxVersion>
</PropertyGroup>

Example: Multi-Format File Output

<PropertyGroup>
  
  <EVVersionFile>$(OutputPath)\version.txt</EVVersionFile>
  <EVVersionJsonFile>$(OutputPath)\version.json</EVVersionJsonFile>
  <EVVersionYamlFile>$(OutputPath)\version.yaml</EVVersionYamlFile>
  <EVVersionXmlFile>$(OutputPath)\version.xml</EVVersionXmlFile>
  <EVVersionEnvFile>$(OutputPath)\version.env</EVVersionEnvFile>
  <EVVersionHeaderFile>$(OutputPath)\version.h</EVVersionHeaderFile>
  <EVVersionPropsFile>$(OutputPath)\version.props</EVVersionPropsFile>
  <EVVersionCsvFile>$(OutputPath)\version.csv</EVVersionCsvFile>
  <EVVersionTomlFile>$(OutputPath)\version.toml</EVVersionTomlFile>
  <EVVersionIniFile>$(OutputPath)\version.ini</EVVersionIniFile>
  <EVVersionSqlFile>$(OutputPath)\version.sql</EVVersionSqlFile>
  <EVVersionBadgeFile>$(OutputPath)\badge.md</EVVersionBadgeFile>
</PropertyGroup>

Example: Docker Tag Generation

<PropertyGroup>
  <EVDockerImageName>myregistry.azurecr.io/myapp</EVDockerImageName>
  <EVDockerRegistry>myregistry.azurecr.io</EVDockerRegistry>
</PropertyGroup>


Example: Version Prefix/Suffix

<PropertyGroup>
  
  <EVPreReleaseLabel>beta</EVPreReleaseLabel>

  
  <EVBuildMetadataLabel>$(BUILD_BUILDID)</EVBuildMetadataLabel>

  
  <EVForceVersion>99.0.0-special</EVForceVersion>
</PropertyGroup>

Example: Selective Stamping

<PropertyGroup>
  
  <EVStampAssemblyVersion>false</EVStampAssemblyVersion>
  <EVStampFileVersion>false</EVStampFileVersion>
  <EVStampPackageVersion>false</EVStampPackageVersion>
  <EVStampInformationalVersion>true</EVStampInformationalVersion>
</PropertyGroup>
<PropertyGroup>
  <EVCopyrightHolder>EonaCat</EVCopyrightHolder>
  <EVCopyrightStartYear>2020</EVCopyrightStartYear>
</PropertyGroup>


## Version Formatting API

### Built-in Format Specifiers

```csharp
using EonaCat.Versioning;

var v = SemanticVersion.Parse("1.2.3-beta.1+build.42");

// Built-in format specifiers
VersionFormatter.Format(v, "S");  // "1.2.3"              (Short)
VersionFormatter.Format(v, "F");  // "1.2.3-beta.1+build.42" (Full)
VersionFormatter.Format(v, "T");  // "v1.2.3-beta.1+build.42" (Tag)
VersionFormatter.Format(v, "M");  // "1.2"                (Major.Minor)
VersionFormatter.Format(v, "N");  // "1002003"            (Numeric)
VersionFormatter.Format(v, "D");  // "v1.2.3"             (Display)
VersionFormatter.Format(v, "C");  // "1002003"            (Compact)
VersionFormatter.Format(v, "H");  // "Version 1.2.3 ..."  (Human-readable)

Cross-Ecosystem Formatting

// JSON output
VersionFormatter.ToJson(v);
// { "major": 1, "minor": 2, "patch": 3, "preRelease": "beta.1", ... }

// XML output
VersionFormatter.ToXml(v);
// <version major="1" minor="2" patch="3" preRelease="beta.1" ... />

// YAML output
VersionFormatter.ToYaml(v);
// version:
//   major: 1
//   minor: 2
//   ...

// TOML output (Cargo.toml style)
VersionFormatter.ToToml(v);  // version = "1.2.3-beta.1+build.42"

// INI file output
VersionFormatter.ToIni(v);
// [Version]
// Major=1
// ...

// SQL INSERT
VersionFormatter.ToSqlInsert(v);
// INSERT INTO Versions (Major, Minor, ...) VALUES (1, 2, ...);

Package Manager Formats

VersionFormatter.ToNuGetVersion(v);     // "1.2.3-beta.1"
VersionFormatter.ToPythonVersion(v);    // "1.2.3b1" (PEP 440)
VersionFormatter.ToGemVersion(v);       // "1.2.3.beta.1"
VersionFormatter.ToMavenVersion(v);     // "1.2.3-BETA.1"
VersionFormatter.ToDebianVersion(v);    // "1.2.3~beta.1"
VersionFormatter.ToRpmVersion(v);       // "0:1.2.3-0.beta.1"
VersionFormatter.ToWindowsVersion(v);   // "1.2.3.0"

CI/CD Platform Formats

// GitHub Actions
VersionFormatter.ToGitHubActionsOutput(v);
// ::set-output name=version::1.2.3-beta.1+build.42
// ::set-output name=version-major::1
// ...

// Azure DevOps
VersionFormatter.ToAzureDevOpsBuildNumber(v);
// ##vso[build.updatebuildnumber]1.2.3-beta.1+build.42

VersionFormatter.ToAzureDevOpsVariable(v);
// ##vso[task.setvariable variable=Version]1.2.3-beta.1+build.42

// TeamCity
VersionFormatter.ToTeamCityBuildNumber(v);
// ##teamcity[buildNumber '1.2.3-beta.1+build.42']

// GitLab CI
VersionFormatter.ToGitLabVariable(v);
// echo "VERSION=1.2.3-beta.1+build.42" >> $GITLAB_ENV

Container & Cloud Formats

// Docker image tags (single and multi-tag)
VersionFormatter.ToDockerTag(v, "myapp");
// "myapp:1.2.3-beta.1"

VersionFormatter.ToDockerTags(SemanticVersion.Parse("1.2.3"), "myapp");
// ["myapp:latest", "myapp:1", "myapp:1.2", "myapp:1.2.3"]

// Helm chart version
VersionFormatter.ToHelmVersion(v);  // "1.2.3-beta.1+build.42"

.NET Assembly Formats

VersionFormatter.ToAssemblyVersion(v);              // "1.2.0.0"
VersionFormatter.ToAssemblyFileVersion(v);           // "1.2.3.0"
VersionFormatter.ToAssemblyInformationalVersion(v);  // "1.2.3-beta.1+build.42"
VersionFormatter.ToMSBuildProperty(v);               // "<Version>1.2.3-beta.1+build.42</Version>"

Code Generation Formats

// C# constant
VersionFormatter.ToCSharpConstant(v);
// public const string Version = "1.2.3-beta.1+build.42";

// C preprocessor defines
VersionFormatter.ToCDefine(v);
// #define VERSION_MAJOR 1
// #define VERSION_MINOR 2
// ...

// Shell exports
VersionFormatter.ToBashExport(v);
// export VERSION_MAJOR=1
// export VERSION_MINOR=2
// ...

VersionFormatter.ToPowerShellVars(v);
// $VersionMajor = 1
// $VersionMinor = 2
// ...

Badge & Display Formats

// Shields.io badge URL
VersionFormatter.ToShieldsBadgeUrl(v);
// https://img.shields.io/badge/version-1.2.3--beta.1+build.42-blue

// Markdown badge
VersionFormatter.ToShieldsBadgeMarkdown(v);
// ![version](https://img.shields.io/badge/version-...)

// package.json
VersionFormatter.ToPackageJsonVersion(v);
// "version": "1.2.3-beta.1+build.42"

Custom Template Formatting

// Custom templates with tokens
VersionFormatter.FormatCustom(v, "App v{major}.{minor}.{patch} ({stable})");
// "App v1.2.3 (unstable)"

VersionFormatter.FormatCustom(v, "Build {major:3}.{minor:3}.{patch:4}");
// "Build 001.002.0003"

// CalVer formatting
var calVer = CalendarVersion.Today();
VersionFormatter.FormatCalVer(calVer, "{YYYY}.{MM}.{DD}");
// "2024.06.15"

Ordinal Conversion

// Convert to/from sortable integer
long ord = VersionFormatter.ToOrdinal(v);     // 1002003000
var back = VersionFormatter.FromOrdinal(ord); // 1.2.3

Version Converter API

The VersionConverter class provides conversions between versioning ecosystems.

Cross-System Conversions

using EonaCat.Versioning;

var v = SemanticVersion.Parse("1.2.3");

// .NET System.Version ↔ SemVer
Version sysVer = VersionConverter.ToSystemVersion(v);          // 1.2.3.0
SemanticVersion back = VersionConverter.FromSystemVersion(sysVer); // 1.2.3

// CalVer ↔ SemVer
CalendarVersion calVer = VersionConverter.SemVerToCalVer(v);   // 2024.6.3
SemanticVersion fromCal = VersionConverter.CalVerToSemVer(calVer);

// Date-based conversions
SemanticVersion fromDate = VersionConverter.DateToSemVer(DateTime.UtcNow);   // 2024.6.15
CalendarVersion fromEpoch = VersionConverter.FromEpoch(1718291234);
SemanticVersion fromDateStr = VersionConverter.FromDateString("2024-06-15");

// Build number → SemVer
SemanticVersion fromBuild = VersionConverter.FromBuildNumber(42); // 0.0.42

// Sortable integer
int sortable = VersionConverter.ToSortableInt(v);            // 1002003
SemanticVersion fromInt = VersionConverter.FromSortableInt(sortable); // 1.2.3

// Four-part .NET version
string fourPart = VersionConverter.ToFourPartVersion("1.2.3"); // "1.2.3.0"
SemanticVersion from4 = VersionConverter.FromFourPartVersion("1.2.3.4"); // 1.2.3

Package Manager Conversions

VersionConverter.ToNuGetVersion(v);      // "1.2.3"
VersionConverter.ToNpmVersion(v);        // "1.2.3"
VersionConverter.ToPep440(v);            // "1.2.3"
VersionConverter.ToRubyGemsVersion(v);   // "1.2.3"
VersionConverter.ToMavenVersion(v);      // "1.2.3"
VersionConverter.ToDebianVersion(v);     // "1.2.3"
VersionConverter.ToRpmVersion(v);        // "0:1.2.3-1"
VersionConverter.ToChocolateyVersion(v); // "1.2.3"
VersionConverter.ToSnapVersion(v);       // "1.2.3"
VersionConverter.ToFlatpakVersion(v);    // "1.2.3"
VersionConverter.ToWixVersion(v);        // "1.2.3" (clamped to WiX limits)
VersionConverter.ToDockerTag(v, "app");  // "app:1.2.3"
VersionConverter.ToOciTag(v);            // "1.2.3" (OCI-safe)

Mobile & Platform Conversions

// Android
int versionCode = VersionConverter.ToAndroidVersionCode(v);     // 10203
SemanticVersion fromCode = VersionConverter.FromAndroidVersionCode(10203); // 1.2.3

// Apple
string bundle = VersionConverter.ToAppleBundleVersion(v, 42);   // "42"
string shortVer = VersionConverter.ToAppleShortVersion(v);       // "1.2.3"

// Windows
VersionConverter.ToWindowsProductVersion(v); // "1.2.3.0"

// CalVer ecosystem
VersionConverter.ToUbuntuVersion(CalendarVersion.Parse("2024.4.1")); // "24.04"
VersionConverter.ToUnityVersion(CalendarVersion.Parse("2024.4.1"));  // "2024.4.1"

Loose String Coercion

// Auto-fix incomplete/loose version strings
var coerced = VersionConverter.CoerceLoose("v1");        // 1.0.0
coerced = VersionConverter.CoerceLoose("1.2");           // 1.2.0
coerced = VersionConverter.CoerceLoose("v1.2.3-beta");   // 1.2.3-beta

// Parse and sort mixed version strings
var sorted = VersionConverter.ParseAndSort(new[] { "2.0.0", "1.0.0", "1.5.0" });
// [1.0.0, 1.5.0, 2.0.0]

// Resolve best version from a range
var best = VersionConverter.Resolve("^1.0.0", sorted); // 1.5.0

Infrastructure Conversions

VersionConverter.ToTerraformConstraint(v);  // "~> 1.2"

// Composer (PHP) ↔ SemVer range
VersionConverter.ComposerToSemVerRange("^1.0||^2.0"); // "^1.0 || ^2.0"
VersionConverter.SemVerRangeToComposer("^1.0 || ^2.0"); // "^1.0||^2.0"

// Homebrew
var fromBrew = VersionConverter.FromHomebrewVersion("1.2.3_1"); // 1.2.3

Version Policy & Governance API

The VersionPolicy class provides policy enforcement, validation, lifecycle management, filtering, and analysis for collections of versions.

Policy Validation

using EonaCat.Versioning;

var v = SemanticVersion.Parse("1.2.3-beta.1");

// Check bump validity
VersionPolicy.IsValidBump(SemanticVersion.Parse("1.0.0"), v);       // true
VersionPolicy.IsConsecutiveBump(SemanticVersion.Parse("1.2.2"), v);  // false (has prerelease)

// Get diff type
VersionPolicy.GetDiffType(SemanticVersion.Parse("1.0.0"), v);  // "Minor"
VersionPolicy.HasBreakingChanges(SemanticVersion.Parse("1.0.0"), v); // false

// Bounds checking
VersionPolicy.IsWithinBounds(v, SemanticVersion.Parse("1.0.0"), SemanticVersion.Parse("2.0.0")); // true

// Full policy validation with rules
var rules = new VersionPolicyRules
{
    RequireStable = true,
    MaxMajor = 5,
    ForbidBuildMetadata = false,
    AllowedChannels = new List<string> { "alpha", "beta", "rc" },
    MinVersion = SemanticVersion.Parse("1.0.0")
};
var violations = VersionPolicy.Validate(v, rules);
// ["Pre-release versions are not allowed by policy."]

Pre-Release Lifecycle

var v = SemanticVersion.Parse("1.2.3-alpha.3");

// Classify pre-release
VersionPolicy.IsAlpha(v);              // true
VersionPolicy.IsBeta(v);               // false
VersionPolicy.IsReleaseCandidate(v);   // false
VersionPolicy.IsDevelopment(v);        // false (major > 0)
VersionPolicy.GetPreReleaseChannel(v); // "alpha"
VersionPolicy.GetPreReleaseNumber(v);  // 3
VersionPolicy.GetLifecycleStage(v);    // "ALPHA"

// Bump pre-release number
var next = VersionPolicy.BumpPreRelease(v); // 1.2.3-alpha.4

// Promote through lifecycle stages
var promoted = VersionPolicy.Promote(v);               // 1.2.3-beta.1
promoted = VersionPolicy.Promote(promoted);             // 1.2.3-rc.1
promoted = VersionPolicy.Promote(promoted);             // 1.2.3 (release!)

// Create special versions
var snapshot = VersionPolicy.CreateSnapshot(v);  // 1.2.3-alpha.3+snapshot.20240615...
var nightly = VersionPolicy.CreateNightly(v);    // 1.2.3-nightly.20240615

Collection Operations

var versions = new List<SemanticVersion>
{
    SemanticVersion.Parse("1.0.0"),
    SemanticVersion.Parse("1.1.0-beta.1"),
    SemanticVersion.Parse("1.1.0"),
    SemanticVersion.Parse("2.0.0-alpha.1"),
    SemanticVersion.Parse("2.0.0"),
    SemanticVersion.Parse("3.0.0-rc.1"),
};

// Find newest/oldest
VersionPolicy.GetNewest(versions);      // 3.0.0-rc.1
VersionPolicy.GetOldest(versions);      // 1.0.0
VersionPolicy.LatestStable(versions);   // 2.0.0

// Sort
var asc = VersionPolicy.SortAscending(versions);
var desc = VersionPolicy.SortDescending(versions);

// Filter
var stable = VersionPolicy.FilterStable(versions);         // [1.0.0, 1.1.0, 2.0.0]
var prerel = VersionPolicy.FilterPreRelease(versions);     // [1.1.0-beta.1, 2.0.0-alpha.1, 3.0.0-rc.1]
var alphas = VersionPolicy.FilterByChannel(versions, "alpha"); // [2.0.0-alpha.1]
var v1line = VersionPolicy.FilterByMajor(versions, 1);     // [1.0.0, 1.1.0-beta.1, 1.1.0]

// Group
var byMajor = VersionPolicy.GroupByMajor(versions);   // {1: [...], 2: [...], 3: [...]}
var byChan = VersionPolicy.GroupByChannel(versions);   // {"stable": [...], "beta": [...], ...}

// Parse from strings (skips invalid)
var parsed = VersionPolicy.ParseMany(new[] { "1.0.0", "invalid", "2.0.0" }); // [1.0.0, 2.0.0]

// Bulk checks
VersionPolicy.AllStable(stable);       // true
VersionPolicy.AnyPreRelease(versions); // true

Analysis & Migration

// Suggest next version
var next = VersionPolicy.SuggestNext(versions, VersionBumpType.Minor); // 3.1.0

// Check compatibility
VersionPolicy.IsSameSeries(
    SemanticVersion.Parse("1.2.0"),
    SemanticVersion.Parse("1.2.5")); // true

VersionPolicy.MajorDistance(
    SemanticVersion.Parse("1.0.0"),
    SemanticVersion.Parse("3.0.0")); // 2

// Migration path
var path = VersionPolicy.GetMigrationPath(
    SemanticVersion.Parse("1.0.0"),
    SemanticVersion.Parse("2.0.0"),
    versions);
// [1.1.0-beta.1, 1.1.0, 2.0.0-alpha.1, 2.0.0]

// Version age
int age = VersionPolicy.GetVersionAge(SemanticVersion.Parse("1.0.0"), versions); // 5

// Diff between versions
string diff = VersionPolicy.Diff(
    SemanticVersion.Parse("1.0.0"),
    SemanticVersion.Parse("2.1.3-beta.1"));
// Major: 1 → 2
// Minor: 0 → 1
// Patch: 0 → 3
// PreRelease: '' → 'beta.1'

// Timeline
string timeline = VersionPolicy.GenerateTimeline(versions);
// 1.0.0 --[Minor]--> 1.1.0-beta.1 --[Patch]--> 1.1.0 --[Major]--> ...

// Statistics
var stats = VersionPolicy.GetStatistics(versions);
// Total=6, Stable=3, PreRelease=3, Newest="3.0.0-rc.1", ...

// String coercion for loose inputs
var coerced = VersionPolicy.Coerce("v1.2");  // 1.2.0

// Naming convention matching
VersionPolicy.MatchesNamingConvention("v1.2.3", "v{major}.{minor}.{patch}"); // true

Version File Manager API

The VersionFileManager class provides read/write support for version files in formats across all major ecosystems.

Plain Text & JSON

using EonaCat.Versioning;

// Plain text version file
VersionFileManager.WriteVersionFile("version.txt", "1.2.3");
string ver = VersionFileManager.ReadVersionFile("version.txt"); // "1.2.3"

// JSON version file
VersionFileManager.WriteVersionJson("version.json", SemanticVersion.Parse("1.2.3-beta.1+build.42"));
var fromJson = VersionFileManager.ReadVersionJson("version.json"); // 1.2.3-beta.1+build.42

// Structured VERSION file (key=value format)
VersionFileManager.WriteStructuredVersionFile("./output", SemanticVersion.Parse("1.2.3"), "abc123", "main");
var data = VersionFileManager.ReadStructuredVersionFile("./output/VERSION");
// data["VERSION"] = "1.2.3", data["COMMIT"] = "abc123", data["BRANCH"] = "main"

.NET Project Files

// Read/write .csproj Version
var csprojVer = VersionFileManager.ReadCsprojVersion("MyApp.csproj");
VersionFileManager.UpdateCsprojVersion("MyApp.csproj", SemanticVersion.Parse("2.0.0"));
VersionFileManager.UpdatePackageVersion("MyApp.csproj", SemanticVersion.Parse("2.0.0"));
VersionFileManager.UpdateAssemblyVersion("MyApp.csproj", SemanticVersion.Parse("2.0.0"));
VersionFileManager.UpdateFileVersion("MyApp.csproj", SemanticVersion.Parse("2.0.0"));
VersionFileManager.UpdateInformationalVersion("MyApp.csproj", SemanticVersion.Parse("2.0.0"));

Cross-Ecosystem Project Files

// Node.js
VersionFileManager.UpdatePackageJson("package.json", v);
var npmVer = VersionFileManager.ReadPackageJson("package.json");

// Rust
VersionFileManager.UpdateCargoToml("Cargo.toml", v);

// Python
VersionFileManager.UpdatePyprojectToml("pyproject.toml", v);

// Ruby
VersionFileManager.UpdateGemspec("myapp.gemspec", v);

// Java/Maven
VersionFileManager.UpdatePomXml("pom.xml", v);

// Gradle
VersionFileManager.UpdateBuildGradle("build.gradle", v);

// Auto-detect format based on file extension
VersionFileManager.AutoUpdate("MyApp.csproj", v);
VersionFileManager.AutoUpdate("package.json", v);
VersionFileManager.AutoUpdate("Cargo.toml", v);

Code Generation

Generate version files for any programming language:

// C/C++ header
string header = VersionFileManager.GenerateCHeader(v);
// #ifndef VERSION_H
// #define VERSION_H
// #define VERSION_MAJOR 1
// ...

// Swift struct
string swift = VersionFileManager.GenerateSwiftVersion(v);

// Kotlin object
string kotlin = VersionFileManager.GenerateKotlinVersion(v);

// TypeScript constants
string ts = VersionFileManager.GenerateTypeScriptVersion(v);

// Python __version__.py
string py = VersionFileManager.GeneratePythonVersion(v);

// Go package
string go = VersionFileManager.GenerateGoVersion(v);

// Rust constants
string rust = VersionFileManager.GenerateRustVersion(v);

// Java class
string java = VersionFileManager.GenerateJavaVersion(v, "com.example", "BuildVersion");

// Dart constants
string dart = VersionFileManager.GenerateDartVersion(v);

// PHP constants
string php = VersionFileManager.GeneratePhpVersion(v);

// Ruby module
string ruby = VersionFileManager.GenerateRubyVersion(v);

Platform-Specific Files

// Windows RC VERSIONINFO
string rc = VersionFileManager.GenerateWindowsRc(v, "MyApp", "MyCompany");

// Android Gradle
string android = VersionFileManager.GenerateAndroidVersionGradle(v);
// versionCode 10203
// versionName "1.2.3"

// iOS Info.plist
string plist = VersionFileManager.GenerateIosPlistVersion(v, 42);

// Flutter pubspec.yaml
string flutter = VersionFileManager.GenerateFlutterVersion(v, 42);
// version: 1.2.3+42

// Electron Builder
string electron = VersionFileManager.GenerateElectronBuilderVersion(v);

// Helm Chart.yaml
string helm = VersionFileManager.GenerateHelmChartVersion(v);

// Terraform
string terraform = VersionFileManager.GenerateTerraformConstraint(v);
// version = "~> 1.2"

Changelog Management

// Prepend changelog entry
VersionFileManager.PrependChangelog("CHANGELOG.md", "## 2.0.0 (2024-06-15)\n\n- Breaking change\n");

Directory Scanning

// Scan a directory for all version files
var found = VersionFileManager.ScanDirectory(@"C:\MySolution");
// { "Project1.csproj": 1.2.3, "Project2.csproj": 1.0.0, "package.json": 2.0.0 }

Version Workspace API

The VersionWorkspace class provides multi-project/monorepo version management with dependency tracking, compatibility analysis, and build ordering.

Project Registration

using EonaCat.Versioning;

var workspace = new VersionWorkspace();

// Register projects
workspace.AddProject("Core", "1.2.3");
workspace.AddProject("Api", "1.1.0");
workspace.AddProject("Web", "1.0.0");

// Add dependencies
workspace.AddDependency("Api", "Core", "^1.2.0");
workspace.AddDependency("Web", "Api", ">=1.0.0 <2.0.0");
workspace.AddDependency("Web", "Core", "^1.0.0");

Version Operations

// Get/set versions
var coreVer = workspace.GetVersion("Core"); // 1.2.3
var allVers = workspace.GetAllVersions();

// Bump all projects
workspace.BumpAll(VersionBumpType.Minor);

// Lock all to same version
workspace.LockAll(SemanticVersion.Parse("2.0.0"));

// Check sync status
bool inSync = workspace.AreAllVersionsSynced();
var outOfSync = workspace.GetOutOfSyncProjects();

Dependency Analysis

// Validate all dependency constraints
var violations = workspace.ValidateDependencies();
// ["Api requires Core ^1.2.0, but found 2.0.0."]

// Get dependency graph
var graph = workspace.GetDependencyGraph();
// { "Core": [], "Api": ["Core"], "Web": ["Api", "Core"] }

// Get build order (topological sort)
var buildOrder = workspace.GetBuildOrder();
// ["Core", "Api", "Web"]

// Get dependents of a project
var dependents = workspace.GetDependents("Core"); // ["Api", "Web"]

// Check breaking impact before updating
var impact = workspace.CheckBreakingImpact("Core", SemanticVersion.Parse("2.0.0"));
// ["Api requires Core ^1.2.0, but proposed version is 2.0.0."]

Compatibility & Export

// Generate compatibility matrix
string matrix = workspace.GenerateCompatibilityMatrix();

// Export formats
string markdown = workspace.ExportMarkdownTable();
string json = workspace.ExportJson();
string props = workspace.ExportDirectoryBuildProps();

// Workspace summary
var summary = workspace.GetSummary();
// ProjectCount=3, InSync=false, TotalDependencies=3, ...

// Apply changesets
var newVersions = workspace.ApplyChangesets(new[]
{
    new ChangesetEntry("Core", ChangesetBumpLevel.Minor, "New feature"),
});

Version History API

The VersionHistory class provides version tracking, timeline analysis, release cadence metrics, and changelog generation.

Recording & Querying

using EonaCat.Versioning;

var history = new VersionHistory();

// Record releases
history.Record(SemanticVersion.Parse("1.0.0"), "Initial release", "john");
history.Record(SemanticVersion.Parse("1.1.0"), "Feature release", "jane",
    new[] { "feat: add search", "fix: pagination" });
history.Record(SemanticVersion.Parse("2.0.0"), "Major release", "john",
    new[] { "feat!: new API", "refactor: core" });

// Query
var latest = history.GetLatest();           // 2.0.0
var entry = history.Get(SemanticVersion.Parse("1.1.0"));
var prev = history.GetPrevious(SemanticVersion.Parse("2.0.0")); // 1.1.0
var next = history.GetNext(SemanticVersion.Parse("1.0.0"));      // 1.1.0
var series = history.GetSeries(1);   // all 1.x releases
int count = history.Count;           // 3

Time-Based Analysis

// Time between versions
var span = history.GetTimeBetween(
    SemanticVersion.Parse("1.0.0"),
    SemanticVersion.Parse("2.0.0"));
// TimeSpan

// Average release cadence
var cadence = history.AverageReleaseCadence();
// e.g. 14 days average

// Releases per month
var perMonth = history.ReleasesPerMonth();
// { "2024-01": 1, "2024-03": 2 }

// Release type breakdown
var byType = history.ReleasesByType();
// { Major: 1, Minor: 1, Patch: 0, PreRelease: 0 }

// Date range query
var recent = history.GetBetween(
    DateTimeOffset.UtcNow.AddMonths(-3),
    DateTimeOffset.UtcNow);

Changelog & Release Notes

// Full changelog
string changelog = history.GenerateChangelog();
// # Changelog
// ## 2.0.0 (2024-06-15)
// - feat!: new API
// ...

// Release notes for a specific version
string notes = history.GenerateReleaseNotes(SemanticVersion.Parse("2.0.0"));
// # Release 2.0.0
// Released: 2024-06-15
// Previous: 1.1.0
// Time since last release: 30 days
// ...

// Version diff
string diff = history.GetDiff(
    SemanticVersion.Parse("1.0.0"),
    SemanticVersion.Parse("2.0.0"));

Rollback & Timeline

// Find rollback target
var rollback = history.FindRollbackTarget(SemanticVersion.Parse("2.0.0"));
// 1.1.0 (previous stable)

// Visual timeline
string timeline = history.GetTimeline();
// ● 1.0.0              2024-01-15  Initial release
// ● 1.1.0              2024-03-01  Feature release
// ● 2.0.0              2024-06-15  Major release

// Export as JSON
string json = history.ExportJson();

License

See LICENSE file.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
.NET Framework net48 is compatible.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETFramework 4.8

    • No dependencies.
  • .NETStandard 2.1

    • No dependencies.
  • net6.0

    • No dependencies.
  • net7.0

    • No dependencies.
  • net8.0

    • No dependencies.

NuGet packages (8)

Showing the top 5 NuGet packages that depend on EonaCat.Versioning.Helpers:

Package Downloads
EonaCat.Dns

This is a Dns Server

EonaCat.Logger

EonaCat.Logger is a logging library

EonaCat.Versioning

Generate build information of GIT and SVN to be used as your product versioning.

EonaCat.Security

EonaCat Security library

EonaCat.LogStack

flow-based logging library for .NET, designed for zero-allocation logging paths and superior memory efficiency. It features a rich fluent API for routing log events to dozens of destinations from console and file to Slack, Discord, Redis, Elasticsearch, and beyond.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.5.0 226 5/14/2026
1.0.2 6,123 2/17/2025
1.0.1 866 9/12/2024