XML Transformations

By eidias on (tags: tfs, xml transformations, categories: infrastructure)

A while ago Microsoft released a very handy feature that allows for transforming web.config files during builds. This is a great thing, except for some reason, they limited the functionality to web.config files, which was strange, because the engine itself was designed to work against any xml file. Thankfully, that limitation is pretty much gone with a plugin called SlowCheetah.

The plugin is free and it uses the exact same engine, so you can even get rid of the ‘old’ way of transforming web.config files and use the plugin for them as well.

As this is not a microsoft official thing (it is developed by a guy who works at microsoft but it’s not an official product – this seems to be quite a frequent practice these days) there is a little caveat. In order to run it outside of visual studio (e.g during a CI build) you need to call the TransformAllFiles target which is not available if you don’t set it up in the project. Sounds quite obvious, doesn’t it…let me explain.

Imagine you’re adding a new project to a solution that is already set up for CI – you don’t need to do any xml transformations in there. Of course, in a CI build we want to be as flexible as possible, so the xml transformation is called for every project. Ours doesn’t have the target. We get a build error.

It’s actually hardly a problem – more of an inconvenience and really easy to fix too – just right click on an xml file (or if you don’t have one, create it and delete afterwards) and select “Add Transformations”. Remove the files that were added and that you don’t need and…nothing’s changed – at least nothing that you can see. The actual modification that we were going for is hidden in the project file:

   1: <PropertyGroup>
   2:   <SlowCheetahTargets Condition=" '$(SlowCheetahTargets)'=='' ">..\..\tools\SlowCheetah\SlowCheetah.Transforms.targets</SlowCheetahTargets>
   3: </PropertyGroup>
   4: <Import Project="$(SlowCheetahTargets)" Condition="Exists('$(SlowCheetahTargets)')" />

This output is actually a bit different that the one you’ll get – the path to SlowCheetah.Transforms.targets – I changed this so that I don’t have to pass in an additional parameter to TransformAllTargets. It’s all described here. Now the only thing left is to copy the targets to the server. I keep them in a separate directory along the project source files in TFS. You can also install the plugin on the build server, but I would definitely suggest keeping it in a VCS it simply gives yo more flexibility that way.