Build Automation on Windows

I have heard  people complain that it is hard to automate almost anything on Windows/.Net. It is one of the few things that even I agreed with, until I tried to do it a couple of days ago. To do it you may have to  not do everything that Microsoft tells you to and not use every tool in the ‘traditional’ Microsoft ecosystem. Here’s what my problem was; I had to setup a build pipeline for a Windows WPF application. To do that I had to solve the following problems.

1. Choice of build tool: Microsoft still sells MSBuild as a complete build tool. If you are writing a .Net application on Windows and are using Visual Studio to do it(of course you are), then it is the pretty much the only contender for compiling code. It does that pretty well. For everything else, like running tests, managing configuration files etc, it is not the most intuitive tool (It is in the end xml, which again is not best language for code/scripting). That is why I decided to try Rake, which is a nice DSL in Ruby. Rake by itself is not a ‘build tool’, as it says in it’s wikipedia page, it is a task automation framework. It gives you basic features like managing dependencies between tasks and executing shell commands. The game changer for me though was the nice human readable syntax (minus the bloat of the xml braces) and more importantly the power of using pretty much any Ruby library. In the past I have used Nant (xml !!), Powershell (shell scripting on .Net steroids) and Psake (a DSL in powershell that come close to Rake, but is quite immature). Rake felt more stable and much more intuitive to use.

2. Compile : Like I said before, MSbuild is pretty much the defacto tool for compilation and using it in Rake becomes a breeze with the Albacore Gem. The compile task looks like this

desc "Compile the C# code"
msbuild :compile do |msb| = { :configuration => :Release }
 msb.targets = [ :Clean, :Build ]
 msb.solution = "MyApplication.sln"

3. Test C# code: To run Nunit tests, Albacore makes it easy again.

desc "Test the .Net Code"
nunit :test => [:compile] do |nunit|
 nunit.command = "C:/Program Files (x86)/NUnit 2.6.2/bin/nunit-console.exe"
 nunit.assemblies "MyApp/Tests/bin/Release/MyApplication.Tests.dll"

If you prefer MsTest, then there is an Albacore task for that too.

4. Test JavaScript code: We used Mocha to write our javascript tests, and Phantomjs as the headless browser to run them on. There is a node.js module called mocha-phantomjs which gives you a single command to do both. Here we use the sh function of a rake task to run a windows command. The rake command will fail if the sh function fails.

desc "Test the Javascript using mocha-phantomjs"
task :jstest do
 sh 'node "node_modules/mocha-phantomjs/bin/mocha-phantomjs" "js/tests.html"'

5. Transcompile scss to sass: If you want a better language than vanilla CSS then you can use Sass (or any other CSS meta language). To transcompile the Sass to CSS, there another ruby gem called (surprisingly) Sass. The rake task for this is,

desc "Transcompile sass to css"
task :sass do
 sh 'sass --update source_sass destnation_css'

6. Generate a windows installer: Microsoft stopped supporting the setup project type from Visual Studio 2012 (Thank God for that). But since Visual Studio 2012, the official way to create installers is to use InstallShield Limited edition. You will realize soon that you can do much with the limited edition and will have to move to the paid for editions. The fundamental problem I see with InstallShield is that they try to shield you from the internals of Windows installers/MSIs. It can be quick for trivial applications but when you want more control and automation, it starts getting tough. That is precisely the reason we chose Wix, which has a declarative xml syntax (can’t seem to avoid xml, sigh!). To use it however you need to understand the internals of Windows Installer, but once you do, you can do pretty much everything to generate your MSI. It is automation friendly with a nice set of command line tools. I also hear that teams within Microsoft themselves use it for building MS office installers (do I smell hypocrisy ?)

7. Configuration Management: Most configuration management tools have some level of support for windows. I chose Chef to do it this time. It turned out to be quite easy to get software on windows through Chef (it runs on Ruby and I got Ruby for free .. yay!).  You need to have their windows cookbook, and then requiring .Net 4 on my box was as simple as,

windows_package "Microsoft .NET Framework 4.0" do
 source node['location']['framework40']  #this is the attribute that gives the file/http location of the windows installer.
 installer_type :custom
 options "/quiet /norestart"
 action :install
 not_if { Registry.key_exists?('HKLM\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4') } #Does not install if .Net is already installed.

The Windows ecosystem may not be as simple as “put a text file there and it works”, nor does it have a standard package management system like the Linuxes, but I have to say this; Automation has become easier for sure in the last few years, thanks to open source. All you need to do is look beyond what Redmond preaches.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s