Net Revision Tool

to developers

I work with a team of around ten or so other developers and we’re gradually moving our applications to Git. At this stage we still have what I’d called “legacy practices” and we mostly build and deploy our applications, services and sites manually.

We had a need to recently deploy quite a few services and applications as part of a roll out of a large project, as I began this work I was thinking how nice it would be to somehow tie in the deployed code to the Git commit or tag from which the code was built, enabling us to troubleshoot any bugs or problems more rapidly and accurately by helping a developer to build from the very same source a deployed troublesome app was built from.

Clearly what I needed was a way to associated the commit ID of the latest commit with one or more generated assemblies, ideally by setting some assembly attribute to the SHA-1 of the commit and possibly more, if only…

I assumed that this is probably something I’d need to think about and probably design and build myself, but it wouldn’t be an hours work – clearly.

So while sipping yet another coffee I did a web search for some of the terms that naturally come up for this question and after a short time I found a post on StackOverflow all about this subject and noticed mention of a utility named NetRevisionTool – I read the post with mounting interest and I forked and cloned the tool’s repo in order to explore it further.

It didn’t take me long to recognize that this a very simple yet powerful little utility, and after a short time I understood that making a simple and straightforward change to any Visual Studio project would give me what I sought and more!

Basically all one has to do is add a pre and post build event to the project and add a single attribute to the projects’s AssemblyInfo.cs file. The build events are merely invocations of the tool’s .exe with some basic command line arguments.

The prebuild event analyzes a mask string in the AssemblyInformationVersion attribute, this mask describes the content and format of the string to be generated by the tool, it then generates the required string and writes it into AssemblyInfo.cs (it backs up the file first).

Then the build itself runs and the generated string gets embedded into the asembly.

Finally the postbuild event runs which simply restores the backed up copy of AsssemblyInfo.cs ready for the next build whenever that might be. (For this reason its important to designate the postbuild event to run “Always”).

Options

The tool itself has command line options and the mask string also has a host of predefined values you can embed, here’s the string I settled on for the time being (I’ve colored the brcaes for easier readability):

{b:uymd-} {b:uhms:} -> {mname} -> {cname} -> {branch} -> {CHASH:8} {!:(Warning – There were uncommited changes present)}

This will cause the tool to generate a string that contains the build date and build time, the name of the computer on which the build executed, the name of the commiter, the name of the branch the commit was on at the time of the build, the first 8 chars of the SHA-1 and finally a warning message that will be appended if the repo at the time of the build had any uncommitted changes.

(I added support for {mname} myself and made this a pull request to the tool developer’s original repo, I also added a command line option /echo which will cause the generated string to be written to the Visual Studio output window when the build runs).

Naturally it’s preferable to always deploy code that doesn’t have the warning message, also we use Github and so after a pull-request merge the most recent commit is always a merge commit with author name “Github” so this too is ideally what one would see in the final generated message because we can be certain that the commit has indeed been merged and cannot ever disappear due to the developer rebasing as could be the case if the commit were only local or on their fork.

The question of where exactly to put the executable to that all developers can invoke it when their builds run obviously comes up and after a short discussion we decided to put the tool onto an existing shared network drive – not a robust solution perhaps but easily sufficient for our current day to day working practices.

Once I’d convinced myself this did what I needed and I settled on the options and so on, it takes me just a couple of minutes to add this to any Visual Studio project. For small teams or even lone developers, I cannot overstate how valuable this little tool is and I’m surprised it isn’t more well known to developers!