You can see that there are some folders here, e.g. 1.5.4.161. You might recognize the format of a .NET assembly version number. This version number is generated by the build server. The build server also creates this version folder here and deploys the corresponding version.

Security note: Please notice that for that to work, the folder needs to be writable by the group, which can be a security issue. Additionally, to automatically remove version folders automatically (not discussed in this blog post), you also need the version folders themselves to be writable.

So the application is served from /var/www/BuzzStats, as one would typically expect to avoid surprises. That one is a symbolic link to /opt/BuzzStats/current. And finally that one in turn is a symbolic link pointing to the active version folder.

Switching between versions is as easy as changing the symbolic link of current to point to a different version folder. Activate the latest and greatest, figure our there’s a missing image? Rollback immediately and easily to the previous version.

Automatic build

Let’s have a look at how the version number can be generated on the build server.

With this setup, I have an environment variable called ASSEMBLY_VERSION_NUMBER which will contain a value like 1.5.4.42 that will be incremented automatically every time Jenkins bakes a new build.

A note on version semantics: for now I’m using a simple solution. The first part of the version is hard-coded in my Jenkins settings (1.5.4). The last part is Jenkins’ own build number which is automatically incremented. You can chose a different strategy for the version, e.g. based on the date of the build. I will probably also change this in the future so that only the 1.5 part is hard-coded. If you like this topic (I do), you can further read Semantic Versioning 2.0.0 and Which Version of Version?.

Build Steps

Now that we have the version number as an environment variable, we can use it during the build process.

Pre-Build: Modify AssemblyInfo.cs files to use the ASSEMBLY_VERSION_NUMBER.This will make the built assemblies use the same version number. I’ve used various ways in the past, for now I’m doing it with a simple shell script:

Build: Simply run xbuild, mono’s msbuild equivalent. This actually works (TM) these days, also with full NuGet support for package restore.

Package the web site into a folder, preparing for deployment. I currently do this with a very old NAnt script. The result is a temporary folder ready to be deployed (as in copy-pasted) to the final deployment location.

Deploy to a local folder. Again with the same old NAnt script:

create the folder /opt/BuzzStats/${ASSEMBLY_VERSION_NUMBER}

copy the package into that folder

This is my current limitation: I can only deploy to a local folder, so the web server and the build server have to be on the same machine. Once I go past that (perhaps using rsync), I will be able to deploy automatically to my actual web server where this blog is hosted.

Activating and rolling-back

With this setup, after each build we have a new version folder under the main folder /opt/BuzzStats. The version is not activated; remember that the web application is still pointing to /var/www/BuzzStats which in turn points to /opt/BuzzStats/current which still points to the old version.

One caveat here is that mono doesn’t detect the change and still continues to run on the old folder. The only way I’ve found so far to “fix” this is to kill the mono process with pkill mono. Obviously this will kill all mono processes which could be a bit more than what you want…

So, for now, I’ve left that as a manual step. I’ve written a small web application to manage activation and rolling-back using a simple UI and I’ll show/share that on a follow-up post.