Version Task and Executable
Motivation
Manual versioning of assemblies is tedious and error-prone. Especially in a continuous deployment environment, versions have to be calculated automatically and environment agnostic.
The Version MSBuild task and executable of Appccelerate solves this problem for you.
Features
- pure git based versioning
- configuration solemnly with tags (no version file required)
- supports pull requests
- works as MS Build task and standalone executable
- support for TeamCity parameters
Road Map
The current implementation is very limited and copes badly with incorrect usage! This is the road map for improvement:
- nicer error handling
Specifying a version
A version is specified using a tag on a commit in git.
The name of the tag has to follow one of the following version patterns.
All patterns have the prefix v=
in common.
Commit Counting Pattern
You can specify that the number of commits since the tagged commit is part of the version.
When you specify a tag as v=1.{0}.0
and there are 7 commits since the tagged commit, the version will be 1.7.0.0
.
When using commit counting by specifying {<base>}
as a part of the version, the placeholder will be replaced with base + commits since
.
In the following sample, the resulting version for head is 3.5.0.0
(version is always extended to contain 4 parts).
When you want to use commit counting in the pre-release version part for nuget packages, you can specify how many digits should be used.
For example v=1.0-pre{0000}
with 15 commits since the tag results in 1.0.0-pre0015
(nuget version) and 1.0.0.0
(assembly version).
This guarantees correct version ordering with the current nuget implementation of Semantic Versioning (SemVer).
Fix Version Pattern
You can set a fix version for a commit by tagging it with a fix version (a version without commit counting placeholder). E.g. v=2.3.4
.
If there are commits since this tag, the version task or executable will throw an exception.
Specifying a seperate file version
If you want the file version to be different from the assembly version, you can extend the pattern of the tag with ;fv=
. For example v=1.{0};fv=1.1.{0}
.
Semantic Versioning, Assembly Version, Nuget Version, Informational Version
The version task and executable calculate three versions: assembly version, nuget version and informational version.
The assembly version is always a version with 4 parts: <major>.<minor>.<patch>.0 The forth part is always 0.
The nuget version is always a version with 3 parts (SemVer) and an optional pre-relase part: <major>.<minor>.<patch>[-<pre-release>] If you specify a version pattern with only one or two parts, 0s will be used.
See Nuget Versioning for more information.
The informational version is built using the annotated message of the tag (for more information about tagging in git see Git-Basics-Tagging.
You can use placeholders to insert the calculated version. There exist the following two placeholders (case sensitive):
{version}
: the 4 parts version. e.g. 1.2.3.0{nugetVersion}
: the 3 parts version with optional pre-release version part. e.g. 1.2.3-pre0003
The informational version is empty if the tag has no annotated message.
Examples
version pattern | commits since tag | annotated message | resulting assembly/file version | resulting nuget version | resulting informational version |
---|---|---|---|---|---|
v=1.2 | 0 | 1.2.0.0 | 1.2.0 | ||
v=1.2 | 1 | error! | error! | ||
v=1.{2} | 5 | 1.7.0.0 | 1.7.0 | ||
v=1.{2} | 5 | RC 1 Build: {version} | 1.7.0.0 | 1.7.0 | RC 1 Build: 1.7.0.0 |
v=1.{2} | 5 | RC 1 Build: {nugetVersion} | 1.7.0.0 | 1.7.0 | RC 1 Build: 1.7.0 |
v=1.{2}-pre | 5 | RC 1 Build: {nugetVersion} | 1.7.0.0 | 1.7.0-pre | RC 1 Build: 1.7.0-pre |
v=1.2-rc{0000} | 5 | RC 1 Build: {nugetVersion} | 1.2.0.0 | 1.2.0-rc0005 | RC 1 Build: 1.2.0-rc0005 |
GitVersion Task
The Appccelerate.GitVersionTask is a MSBuild task than can be used to version assemblies during building.
The task will set the assembly, file and informational version.
Therefore, you need to delete the corresponding attributes from the AssemblyInfo.cs
(AssemblyVersion
, AssemblyFileVersion
, AssemblyInformationalVersion
).
Otherwise an error will occur.
There is currently no way to have different assembly and file versions.
Installation
You can install the version task into a project using nuget. The package id is Appccelerate.VersionTask
.
GitVersion Executable
The Appccelerate.Version executable is a console application that writes the calculated version(s) to the console.
Usage:
path
: path pointing inside a git repository (does not have to be the root).
--output
: optional, defines what output to write. Specifying nugetversion
results in an output only containing the nuget version. This simplifies parsing.
Examples
Writing all calculated versions as json to the console:
Writing only the nuget version to the console:
Installation
Using NuGet
You can install the version executable using nuget. The package id is Appccelerate.Version
.
The executable can be found at tools\Appccelerate.Version.exe
Using Chocolatey
When you want to install the version executable with Chocolatey, use the following command:
You have to specify the source because the package is not listed on the chocolatey gallery.
TeamCity Integration
Add a powershell build step with the following code:
This will install the version executable, run it and set the calculated nuget version as the build number.
The build number can later be used to set for example the version of a created nuget package.
Samples
All projects of Appccelerate use the Appccelerate.Version.Task. Take a look at the code at GitHub.
Branching, Pull Requests
Appccelerate.Version does not consider the name of the current branch. It only checks whether it is a GitHub pull request.
If it is a pull request, the nuget version will contain the pre-release version part -commit<hash>
.
Any existing pre-release version part will be overwritten.
If you work with several branches (e.g. release branches), we suggest to branch and then tag both branches.
Example:
- Master branch with a tag
v=1.{0}
and 42 commits since the tag. - Release branch on the 42nd commit.
- Tag the commit from which is branched with
v=1.42
. This will prevent automatic commit counting and wrong versioning. - Tag the commit on master after the branch with the version of your next release. E.g.
1.{43}
(continue counting) or2.{0}
(time for a major). - Tag the commit on the release branch after the branch with a patch version number. E.g.
1.42.{0}
If this sounds too complicated, consider one of the alternatives below.
Alternatives
GitVersion is a better alternative if you follow GitFlow as a branching strategy. GitVersion also offers support for GitHubFlow (but I had some problems with it and therefore built Appccelerate.Version). It deals with release and hot-fix branches automatically.
Appccelerate.Version works best in continuous deployment scenarios with a single master branch in the main repository and pull requests. You can push to master in the main repository, you can integrate pull requests (versioned as pre-releases for nuget) and use any kind of branching strategy. However you have to make sure that you don't give the same version number to commits on different branches.