A while back I blogged about how to setup SlowCheetah on a Build server. The solution was good but it was a bit unwieldy and error prone, especially those who are not comfortable with MSBuild (this solution still works and is still a good approach for some scenarios). I’ve made this much easier, but wasn’t able to make it as easy as what I wanted. The solution that I choose is using NuGet. Ideally you’d be able to install the SlowCheetah NuGet package into a project, enable package restore and the check in your code. Unfortunately due to how NuGet package restore is implemented this flow is not currently possible. Hopefully in the near future Nuget will better support these scenarios. For now we will have to work with the solution below.
The transformations are executed when your project is built. The way that this works is that when you use the SlowCheetah VS add-in to enable transformations, your project file is modified to import an additional MSBuild .targets file which knows how to do the transformations. This .targets file is placed in your %localappdata% folder. When you add the SlowCheetah NuGet package to your project, the .targets file (and supporting files) are downloaded to the packages folder. Your project is also modified to look at the packages folder for the .targets file which is imported.
For build server scenarios, when using NuGet for this it’s a bit of a chicken and egg problem. Let me clarify, we are using NuGet to update the build process for your project. If a solution is using NuGet, you will need to enable NuGet Package Restore. This is what will enable your NuGet packages to be download during build.
Package Restore is implemented to restore NuGet packages for each project whenever it is built. This is accomplished by adding an Import into your project to NuGet.targets. This works beautiful for the majority of cases, but fails completely if you are trying to update the build process for a given project with NuGet. When the build for a project starts if the the imported .targets file do not exist on disk they are not imported. You can visualize this flow as.
We need to find a way to get the packages restored, before your project is built. We can achieve this by executing a build which will be used to simply restore our packages. Now let’s see how we can workaround this issue.
We need to find a way to restore the packages before the project is built. The easiest way to do this is to add a dummy solution to be built before your actual solution/project. Follow these steps.
1. Install the SlowCheetah NuGet package into the project using SlowCheetah.
You can do this by using the Package Manager Console, and executing the command Install-Package SlowCheetah –pre. Note: after the package is released you can remove the –pre.
2. Enable Package Restore for the solution
You can do this by right clicking on the solution and selecting Enable NuGet Package Restore.
3. Configure build server to build restorePackage.proj before your solution
As described we need a new solution that can be used to restore the required packages. When you install SlowCheetah it will automatically create a packageRestore.proj file in the root of your project. You can use this to easily restore your NuGet packages. All you need to do is to build this file before you build your solution or build script. If you are using Team Build this is pretty easy. Edit the build definition and then add packageRestore.proj to the Items to Build list. You can find this on the Process tab.
Make sure that packageRestore.proj is above (built before) your solution.
With these changes when the empty solution is built, it will restore the SlowCheetah .targets file. Then the target solution will be built, the .targets file will already be downloaded and your transforms will execute as needed.
I will work with the NuGet team to see if there is something better that can be done here. I will keep you all posted if there is any update.I would love if you tried out this new support and let me know if you have any issues with it.
Sayed Ibrahim Hashimi | @SayedIHashimi