Building Git repositories containing sub modules with Continua CI

Today I wanted to add a repository to the build server that contains submodules. The submodules are required because I prefer to share code via shared projects so they will always be compiled for the right platform as you can read here.

When you add a repository to a project or configuration in Continua CI, you can add authentication. However, the sub modules won’t use the same authentication which means that the submodule can never be retrieved. To solve this issue, use the steps below.

Create separate build server account (optional)

I prefer to create a read-only account for build servers so it can never screw anything up. For private projects I use Bitbucket so I created a new buildserver account and added it to the team with read-only access.

Create _netrc file on the server

The _netrc file can be used to provide default credentials to a server when they aren’t provided on the actual repository. I prefer to keep everything together so I followed the following steps:

  1. Create directory C:\Continua\Auth
  2. Create a %HOME% system variable pointing to this path (I prefer using a shared path for %HOME% so it is accessible to all users)
  3. Create the _netrc file (note that there is no extension) with the following content:

machine [host]
login [buildserveraccount]
password [password]

for example:

machine bitbucket.org
login mybuildserveraccount
password mypassword

Now Continua CI will be able to pull the submodules as well.

Introducing ContinuaInit – initialize your build server variables

I am using Continua CI as a continuous integration server. One of the things I always do is to try and mainsteam all the configurations so I know what is happening for each product. However, I always found myself doing a lot of if/else to determine the state of a build:

image

The advantage of these variables is that I can implement logic inside a configuration based on whether the build is a CI build and whether it is an official build. My goal was to replace this whole tree by a single call to an executable that contains rules to determine variables and init them all.

The result is ContinuaInit. You can replace the whole tree by the Execute Program action and call ContinuaInit.exe. That will result in a much cleaner initialization:

image

What initialization is supported?

For now, it supports the following rules:

PublishType

If the branch is master, the PublishType will be set to Official. Otherwise the PublishType will be set to Nightly.

IsOfficialBuild

true if the branch master, otherwise false

IsCiBuild

true if the branch does not equal master, otherwise false

DisplayVersion

Will be set to the version provided by the command line. Then it will apply one of the following values:

nightly => when nightly build

ci => when CI build

How can you get it?

ContinuaInit is available on both NuGet and Chocolatey.

Automatically determine a version using GitFlow or GitHubFlow

I am a big fan of automating builds. Even for simple and small projects, the builds should be fully automated. This makes sure that the software is built on a different machine than it is developed on. A great side effect is that the unit tests are really ran (because how many developers actually run the unit tests before checking in the code?). I am also a big fan of GitFlow. I won’t go into details, but I like that fact that you can always release a hotfix on the master branch while keeping a separate development branch.

After reading this blog post, you can automatically determine the version of software that follow GitFlow or GitHubFlow:

image

Stop versioning the software yourself

One issue though is that you have to manage the versioning in the Continuous Integration (CI) software. Managing the versions of all software projects I contribute to is almost a daytime job. Then I came along an awesome project called GitVersion. It can automatically determine the version of your software based on your repository. This means you no longer have to manage any states of the software, but you can simply ask GitVersion to determine the version for you following the GitFlow / GitHubFlow:

Copyright notice: image originally comes from the GitVersion website

To determine the version of a repository, use the following command line:

This will result in this version for the 8th commit in the develop branch:

Integration in your favorite CI software

The CI software I prefer to use is Continua CI. The reason I like it is that it is very easy to understand but in the same time it is really, really powerful. Another great advantage is their support: they implement features / fix bugs within a week which is nice compared to other companies where you have to wait until the next major release to hopefully find your feature request implemented.

To integrate GitVersion into Continua CI, use the steps below.

1) Add GitVersion.exe to your repository

Add GitVersion.exe to your repository (or put it on the build server, whatever you prefer). I like to put it in the tools directory of my repository:

image

2) Define version variables in the Continua CI configuration

Note that you can use all versions that GitVersion exposes in the example above. The naming convention must be GitVersion_[VariableName]. Below is an example of versions that I find useful during builds:

image

3) Call GitVersion.exe at the start of the build

In Continua CI, add the Execute Program action to a stage and use the settings below:

image

Don’t forget the set the arguments as well:

4) Update the AssemblyInfo

I prefer to put the version of a solution in a centralized SolutionAssemblyInfo which is shared over all the projects that are part of a solution. After calling GitVersion.exe, you can update the version in the AssemblyInfo of your project:

image