Note that I’m using TeamCity 9.0 (build 32060) and GitVersion 2.0.1. These steps may be different in future versions. GitVersion seems to be slated for a 3.0 release very soon.
I’m setting up TeamCity using GitVersion for a new open source project that I want to deploy via NuGet. I’ve used TeamCity a few times to set up basic builds but I’ve never got SemVer working in a nice way before, so I thought this would be a nice opportunity to try GitVersion.
The Release configuration is triggered manually to deploy the last built version to NuGet. It would probably be nicer to do this from Octopus but for now I’ll just use TeamCity.
I’ve started out with an Azure VM configured with TeamCity 9. I first installed GitVersion on my build agent using Chocolatey. Install Chocolatey using an elevated Powershell console:
iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))
Then install GitVersion:
cinst gitversion.portable
You may also have to install msysgit. TeamCity has its own Git client built into the server but GitVersion needs to be able to access the Git history on the agent, which means the VCS checkout has to happen on the agent (configured below). Reboot the machine once this is done to make sure everything is on the path.
Now start setting up the project in TeamCity.
CI
Now create the first build step for GitVersion. I used Jake Ginnivan’s post on his typical TeamCity build setup as a guide.
GitVersion
. /updateAssemblyInfo /assemblyVersionFormat MajorMinorPatch /output buildserver
Note that there is a space between the .
and the /updateAssemblyInfo
:
Note with the 3.0 release of GitVersion the command parameters may be able to be removed in favour of a GitVersionConfig.yaml
configuration file. Stay tuned.
Now create another build step to build the solution.
PROJECT_NAME.sln
. Select the step then clicked Use selected..git
folder will exist and GitVersion should work properly.To run GitVersion before building the solution:
Now select Triggers and Add a new trigger. Select VCS Trigger then Save.
Running the configuration worked for me at this point, resulting in a build versioned 0.1.0+21
(there were 22 commits, so that’s 21 commits since version 0.0.0
). If you get an error about not being able to find GitVersion
or git.exe
make sure the build agent has rebooted and that GitVersion and Git are on the path.
Next you can add a step to run tests. I’m using xUnit. This is just a Command Line runner with the following custom script:
packages\xunit.runner.console.2.0.0\tools\xunit.console.exe src\YOUR_PROJECT.Tests\bin\Release\YOUR_PROJECT.Tests.dll
First you need to add a nuspec
file alongside the library being released (add it to the project in Visual Studio) and push it up so TeamCity can see it. For example, .\src\frankenwiki\Frankenwiki.nuspec
:
<?xml version="1.0" encoding="utf-8"?>
<package>
<metadata>
<id>frankenwiki</id>
<title>Frankenwiki</title>
<version>0.0.0</version>
<authors>Rebecca Scott</authors>
<description>Markdown based statically generated wiki engine</description>
<language>en-US</language>
<licenseUrl>https://github.com/frankenwiki/frankenwiki/blob/master/LICENSE.md</licenseUrl>
<releaseNotes>https://github.com/frankenwiki/frankenwiki/releases</releaseNotes>
<projectUrl>https://frankenwiki.com</projectUrl>
</metadata>
<files>
<file src="bin\release\Frankenwiki.dll" target="lib\net451"/>
</files>
</package>
The easiest way to generate the NuGet package (.nupkg
) seems to be Octopack. Install Octopack to the library being released and push the changes up to the repository. Now edit the CI configuration and in the Visual Studio (sln) step (the actual build step) show the advanced options and add this to the Command line parameters:
/p:RunOctoPack=true
Now when a build happens, OctoPack will create the .nupkg
file named something like Frankenwiki.0.1.0.nupkg
. This package gets consumed in the next step. Trigger a build now to make sure everything works and the package is created as an artifact.
Create a new build configuration called Release or Promote or Fly, my pretties, ah hahahaha!:
.nupkg
file (so it is independent of the version). Eg. Frankenwiki.*.nupkg
.The last few steps are directly based on Jake’s post. Go to Build Features to set up labelling:
build-%system.build.number%
. Take out the build-
part so it is just %system.build.number%
Now go to Dependencies to set up the build chain:
.nupkg
fileGo to General Settings and show advanced options. Change the Build number format to the following:
%dep.MyProject_Ci.build.number%
where MyProject_Ci
is the build configuration ID of the CI step. Once you type in %dep
it will suggest the available configurations.
Now you should be able to trigger a Release, which should successfully publish the package to NuGet! If everything works.
TeamCity can build feature branches and tags. This lets GitVersion version feature branches to reduce surprises.
+:refs/heads/*
(Working with Feature Branches)Jake’s post about Simple Versioning and Release Notes has some great info about changing the version but a good one seems to be using a feature branching strategy.
Push a branch with the new version number in the name. For example:
git checkout -b version-0.3.0
git commit ...
git push
Note that just pushing the branch won’t trigger the branch build, there needs to be a non-empty commit.
You can see that TeamCity has built a new release from the feature branch and GitVersion has versioned it at 0.3.0-beta.1+4
. Subsequent commits to this feature branch will increment the build number (eg. 0.3.0-beta.1+5
). When the feature branch is merged into master, the master version will become 0.3.0
and you can just manually run the Release configuration to deploy to NuGet.
Don’t add a branch or a commit with a version number in it unless you expect it to bump the version number. I merged a branch called change-to-dotnet-4.5.1
which GitVersion helpfully interpreted as a version bump to 4.5.1
. I had to fix this by rewriting the commit comments to say 4dot5dot1
.
If GitVersion report a particular version but Octopack generates nuspec files with a different version, check in the AssemblyInfo.cs
file for a different version in the AssemblyVersion
and AssemblyFileVersion
attributes. This can be due to the versioning scheme, which can be set using the /assemblyVersionFormat
parameter as above (or in GitVersionConfig.yaml
once it is supported by GitVersion).