GitVersion and TeamCity

One advantage of old “centralised” version control systems over Git is that commits have useful sequential numbers. Assigning version numbers automatically as the code changes (as opposed to just numbering builds) becomes tricky with Git.

My aim is to have a build process generate meaningful version number/info that:

  1. Allows for a semantic version, with “major.minor.patch” components
  2. Lets me control when the major/minor build numbers change
  3. Has a “patch” component that is incremented as the code changes
  4. Is “baked in” to the release code so I can display it on the app (UI footer, “info” API method, etc)
  5. Is displayed on the build server dashboard, so I can track a release through the build pipeline from CI to Test to Live
  6. As a bonus, will point to the specific code commit that represents the actual live code

Thankfully, there’s a tool – Git Version – that will generate more meaningful version numbers, including a sequential count of code commits.

This post covers TeamCity building .Net, but you should be able to get Git Version to work with other build tools and spit out version numbers you can use. For .Net, we need to apply the generated version number to the AssemblyInfo.cs files before compiling, but this “generate version and write to file” approach can be adapted for other languages.

Initially, I was using TeamCity’s built-in “Assembly Info Patcher” build feature, and just feeding it values of “%Major.version%.%Minor.version%.%build.counter%.0” and “%Major.version%.%Minor.version%.%build.counter%.%build.vcs.number%” for the version/file and informational numbers (I used parameters for the major and minor versions to control the semantic versioning). By default, TeamCity’s “build.vcs.number” property only gives you the commit SHA.

For “something better”, I need to configure TeamCity and GitVersion to give me “something meaningful”, then I need to tweak the versioning to match my workflow.

Setting up TeamCity and GitVersion

First download – for TeamCity use https://github.com/JetBrains/meta-runner-power-pack/tree/master/gitversion. You can just download the repository as a zip, and then unzip the archive somewhere.

GitVersion runner needs to be added to a project as a Meta Runner – you can add this to a single project, but it’s best to add to the root project.

So go to the “<Root project>”->Meta Runners, and upload

Filename: “MR_GitVersion3.xml”
File: browse to “MR_GitVersion3.xml”

(Look in the meta-runner-power-pack-master/gitversion folder).

Check by editing the meta-runner – you will see the following:

ID: MR_GitVersion3
Name: GitVersion3
Description: Execute GitVersion 3

And the source will be the content of the XML file you uploaded. You can now delete the local copy of the meta runner you downloaded. You can also set GitVersion to check for updates.

If you want to use a different build server, start with the GitVersion project code at https://github.com/GitTools/GitVersion. As you’ll see later, all you need is a GitVersion executable.

Versioning a Build

I’m assuming you have a basic build configuration setup that grabs code from Git (VCS root settings) and compiles the code (build step), and that your build doesn’t yet apply a version number. Hopefully your build will end up doing other things (eg. running unit tests, creating a release package).

Run the build, observe the output (see build logs for agent and working directory location) and you’ll see that all the newly-created DLLs have whatever default version number you put in the AssemblyInfo.cs files (check DLL properties->details).

Now we have an “unversioned” build, let’s try stamping a version number. You’ll need to add a build step to your build configuration – this should be the first step, before you do anything that requires a version number (compilation, packaging, etc). Important note – don’t use a TeamCity AssemblyInfoPatcher build feature if you’re using GitVersion.

Edit your build step, and set runner type “GitVersion3”. A remote git password is added when you first add the build step (checking the config in “ProgramData\JetBrains\TeamCity\config\projects\ProjectName\buildTypes\BuildConfig.xml” shows that this is a generated password).

For .Net, you’re going to want to check “Update AssemblyInfo files”.

Run this and TeamCity will complain about a “parameter called ‘env.Git_Branch’ with value %teamcity.build.vcs.branch.<vcsid>%”.

GitVersion needs some parameters set up for your build, so go to the “Parameters” tab and set up two parameters:

Environment variable: “env.Git_Branch”, value “%teamcity.build.vcs.branch.<vcsid>%”

Configuration parameter: “teamcity.build.vcs.branch.<vcsid>”, value “master”

So if you run this, then you’ll see that both the AssemblyInfo.cs and the DLL now have the actual generated version numbers. Unfortunately, they’re probably not the version numbers you’re looking for…

In a follow-up post I’ll cover how to configure GitVersion to spit out the version info and format you actually want.

Summary – so far we have:

  1. Set up CI build to grab code from Git
  2. Added build step to compile code
  3. Added GitVersion build step to generate a version and bake it into AssemblyInfo.cs files

Showing the GitVersion Build Number on the TeamCity Build Dashboard

You probably want to have TeamCity use this generated version number as the displayed build number, rather than an arbitrary build counter. This is especially useful if you go for a “build artifact once, deploy repeatedly” pipeline approach, rather than a branch-based / re-build on deployment approach. Go into the build configuration general settings and check the build number format. I’ve actually found that both “%build.counter%” and “%build.vcs.number%” seem to work with GitVersion.

Leave a comment