Sprydon

Richard Harding's spot on the web

Custom activity to tag sources in git from TFS

The problem

I want to be able to trace an assembly back to the source that was used to build it, the way I usually accomplish this is to have the continuous integration server set the assembly version (including file version) based on some auto incrementing build number and incorporate that same build number in a source control label. Then given an assembly I can use its version to pull the source that built it.

However while there is a built in activity to label workspace files for the TFS Source control repository it doesn’t seem to support the Git repository option which seems like a strange omission.

The TFS Community extensions don’t have anything suitable either

The Solution – Custom Activity & Libgit2sharp

I took a look at the source of the built in activities that interact with Git – especially the InitializeEnvironment activity that clones the repository. They all use the libgit2sharp library to interact with the TFS git repository, so using the examples on project wiki I put together a quick test to check I could apply and push a tag

   1:  using (var repo = new Repository(@"c:\repos\MyTestRepo"))
   2:              {
   3:                  var tagName = "MyTagName";
   4:                  var tag = repo.ApplyTag(tagName);
   5:                  var remote = repo.Network.Remotes["origin"];
   6:                  var pushOptions = new PushOptions { Credentials = new DefaultCredentials() };
   7:                  repo.Network.Push(remote, string.Format("refs/tags/{0}:refs/tags/{0}", tagName, pushOptions));
   8:              }

 

That worked, so the next step was to build a custom activity that I could add to a build template - Martin Hinshelwood has a great blog post that helped me to get started with the custom activity and again referring to the source of the built in activities helped with extracting some of the arguments like source directory paths and build numbers.

Once you have your activity you need to get it deployed to the build agents, the process is to add the assembly and any dependencies (in this case the libgit2sharp.dll and the native binaries it uses) to a Git repository and configure the Custom Assemblies property of the build agents – this process is well documented on the Community TFS Extensions codeplex site.

Logging

This of course did not work first time….so I needed to add some logging I copied the example shown in this forum post 

context.Track(new BuildInformationRecord<BuildMessage>
                              {
                                  Value = new BuildMessage
                                              {
                                                  Importance = BuildMessageImportance.High,
                                                  Message = message
                                              }
                              });

This threw up an odd situation  - its possible for the call to Network.Push method to fail and not throw an exception – in my case it was because the service account that the TFS Build agent was running under did not have the necessary Write permission to create the tag – the PushOption object has an event handler to catch errors  - use this to see these kinds of issues and log them to the diagnostics log for the build.

I’ve put together a sample activity and the source is on my GitHub

Loading