TL;DR: Using an upgraded (and fixed) Parallel Build Process Template allows to use multiple TFS2012 build agents simultaneously, which can be more than welcome when building metro apps that target all three supported platforms. A build that took 11 minutes can go down to 3.5 minutes.
Download the Parallel Build Process Template for TFS2012 here.
CI is a wonderful feature, especially when associated with Gated Checkins.
You’re certain that what’s in your source control is in line with your build definition and constraints, and that there is always a binary that respects a minimum set of rules. This does not ensure that your app is bug free, but still, that’s a minimum.
Build time matters
The downside of this validation is that there cannot be multiple builds running at the same time. This can become a bottleneck when multiple developers checkin within the duration of a single build run.
This means that the longer your build gets, the longer a developer might wait for its task completion because of a long build queue, and increase its task switching cost. If a build fails, the developer needs to unshelve its changes, make the necessary adjustments, then check-in again.
Below 4 minutes of build time, this stays in the acceptable range where the developer’s task context may not be lost if the build fails.
The case of Metro Apps
Metro apps are a bit tricky in this regard, because when a .NET based app needs a native dependency, such as Bing Maps SDK, then it is not possible to use the Any CPU configuration anymore.
In such case, building the app requires the target the three Metro Apps supported platforms: ARM, x86, x64.
The msbuild configuration for metro apps enforces that all projects for a single platform be compiled under the same platform, meaning that every assembly must be build three times to produce a complete app submission package.
If your build takes 4 minutes for one platform, then multiply it by three (or more) for all platforms. This is where the CI build time gets in the way of development efficiency.
And if you’re multi-targeting to include Windows Phone apps, and desktop apps that share code with metro apps, Build Time can get out of hand very quickly. And I'm not even mentioning obfuscation...
Building in Parallel
I’m a fan of msbuild projects authoring (over Workflow authoring) but in this case, msbuild does not cut it. This will probably please my TFS MVP friend Etienne Margraff, which gives a lot of love to customizing its workflows.
When building using msbuild, parallelization can occur inside a single solution, for a single Configuration/Platform combination. While this improve the build time a bit, this does not work at all for multiple combinations.
There’s also the trick that the guys over a the MSBuild Extension Pack that enables the execution of multiple tasks inside of a single MSBuild project file to run in parallel. The problem with this is that the same source tree is used for all builds at the same time, which can cause trouble over shared files or resources. You have to make sure that all projects include the platform in their respective outputs, but even with that, you can’t be sure that a race condition might not happen at any time.
Using the Parallel Build Process Template
A few years back, a Jim Lamb posted a custom Build Process Template that allows to build multiple configurations in parallel. The beauty of this template is that it allows for each configuration to run on a separate build agent !
This means that the build can be split on multiple machines, running each on their own copy of the source tree, avoiding race conditions over shared resources from the source tree.
I’ve migrated a few projects over to this updated template and the results are very interesting. A build that would take 11 minutes to run would fall down to 3.5 minutes when ran over three build agents on the same machine.
One thing though, the original template is built for TFS2010, so I had to port it over to TFS2012 using this cleanup tool from Jason Prickett. If you don’t want to migrate it by yourself, download the file at the top of the post.
I also had to modify the original error handling, because if one of the configuration build failed, the overall build would not fail. In the context of a gated checkin, this can be problematic…
Getting a bit farther
The interesting thing with this parallel build template is that it can be used to parallelize validation or non-output generating tasks. For instance, creating a zip file of the source tree, validating some portions of the xaml for best practices, running some non-interactive unit tests… and so on.
This relies on scaling out, instead of scaling up, which is more than welcome, particularly in virtualized environments.