Gitflow-style-releases with Teamcity versioning

On the current project I work on we’re using the Gitflow branching model. We also use Teamcity for CI. Using Gitflow with SemVer means that you have to specify the version number each time you release giving it a specific meaning based on the changes within that release.

Previously, when using SemVer, I’ve just used the pre-release tag to identify builds from the build server, preferably, with something that ties a version to a specific revision. This is fine, but there is some duplication. Gitflow calls for you to tag the revision of release with a label. Teamcity has a build number that you can specify. The two of these overlap and I’d rather not have to type this number twice. I want to make the process of releasing as simple as possible.

There is a meta-runner for Teamcity the uses GitVersion to set the version number. This might provide you with the functionality you need, but unfortunately, for me there are two problems for me. The first is that we run build agent accounts that cannot use chocolatey and the meta-runner attempts to use it to install GitVersion. The second was to do with a limited checkout branches that Teamcity does; it doesn’t have all the tags. GitVersion attempts to use a full checkout to get the branches, I’d rather not do this as Teamcity has its own style of checkout that I don’t want to go against.

The first thing we need to do is get the version from the tag. As I’ve already mentioned, as with GitVersion, you can’t always get the tag with Teamcity’s limited checkout. Instead, the approach I’ve taken uses Artifact Dependencies.

Gitflow assumes one releasable thing per repository, or at least, only one version number. At the moment I’m using a major version of zero so I’m not tracking API breaking changes.

Using Teamcity, create a build configuration with a VCS trigger for your master branch. This is the branch from which your releases are built. To do this you need to add the trigger with the filter of +:refs/heads/master

Then add a Powershell script build step that executes the following.

$TagVersion = git describe --tags --match v*
Write "##teamcity[buildNumber '$TagVersion']"
$Version = "$TagVersion".TrimStart("v")
Write "$Version" > library.version
$parts = $Version.split(".")
$parts[1] = [int]$parts[1] + 1
$parts[2] = "0"
$SnapshotVersion = $parts -join "."
Write "$SnapshotVersion" > library-next-minor.version

This will generate two files, one which contains the current version from the tag, and another which contains the next minor version. Add these files (library.version & library-next-minor.version, renamed as appropriate) as artifacts. These artifacts can be used by other Build Configurations that produce outputs that need to be versioned.

In your build configuration use an Artifact Dependency on the latest successful build of the master branch. To make teamcity update the build number add the following build step.

$branch=git rev-parse --abbrev-ref HEAD
$hash=git rev-parse --short HEAD
$thisVersion = Get-Content corelibrary.version
$nextVersion = Get-Content corelibrary-next-minor.version
if ($branch -eq "master") {
$version = "$thisVersion"
} elseif ($branch -eq "develop") {
$version = "$nextVersion-$hash-SNAPSHOT"
} else {
$upper = $branch.replace("/", "-").toupper()
$version = "$nextVersion-$hash-$upper-SNAPSHOT"
}

Write "##teamcity[buildNumber '$version']"

If you need to access this later from your build scripts, you can get it from the BUILD_NUMBER environment variable.

Leave a comment