Introduction to Build Automation with CAKE (C# Make)
Continuous integration (CI), is a very important part of delivering quality software. CI involves developers in a team merging their changes to a central repository continuously throughout the development cycle. As developers continue to merge code to the main branch, each merge is expected to trigger an automated build, which runs after all the automated tests have been run and ideally have passed.
The idea behind Continuous integration is to make sure that developers ship tested code with confidence. This places great emphasis on automated tests checking that the solution is not broken whenever new commits are merged into the main branch. In essence, using automated tests to catch any regression bugs earlier on in the development cycle.
The desired result is that anyone in the team with enough privileges to deploy a new release can deploy at any time. To achieve this, the team must aim at eliminating most manual tasks through continuous delivery, thereby leaving developers to be more productive . Having said that, automating the build is one of the prerequisites of achieving an almost pure continuous delivery cycle.
Build automation
Build automation refers to the practice of automatically building your software on every commit or once a day. In software, build refers to the process that converts files and other assets under the developers’ responsibility into a software product in its final or consumable form. Build automation is automating how the software is built using build tools like Make, Rake, Cake, MS build, Ant, Gradle, VSTS etc .
Below is a diagram that shows a build process that can be automated using build tools.
Cake
For the last nine months I have been working for a client that believes strongly in open source software. The tools that the client uses are mostly open source, for example the CI build server that we use is Jenkins. For build automation Cake fits the bill in the context of C# projects. Cake gives you the capability of building and automating your .NET application build process using C# build scripts .
One of the many reasons you would consider Cake is that, it has built in support to invoke tools like MSBuild, XBuild and dotnet. Cake can invoke test runners like xUnit.net and nUnit. It also integrates seamlessly with continuous integration servers like TeamCity, Jenkins, Visual Studio Team build and Travis CI just to mention a few.
In this post I will dive a little into setting up Cake in Visual Studio and I will explain what Cake is and how you can use it to automate your builds in support of your CI/CD pipeline.
What is Cake?
Cake is a build-automation utility similar in purpose to Make, Rake, Ant and NAnt. Cake is an executable that you will run as part of your build process. You can use Cake to automate activities like compiling code, running unit tests, downloading NuGet packages, copying and moving files around. The Cake team call Cake “C# MAKE”. Cake documentation puts Cake as :
Three important factors to note about Cake:
- You use C# to write your build scripts making it familiar to most .Net developers.
- Cake is open source. There is a big supporting community around it
- Cross platform. Cake is available on Windows, Linux and macOS.
Tasks
Cake uses dependency tracking model as its backbone for scripting. A build process in Cake consists of a series of activities known as tasks. Basically, a task is a unit of work that performs specific work, like running automated tests. Sample tasks below.
Task(“RunTests”) .Does(() => {
});
Task(“Build”)
.IsDependentOn(“RunTests”);
.Does(() => {
});
RunTarget(“Build”);
Dependency-tracking Model
Tasks in a build process must occur in a specific order. Instead of writing a script with sequential tasks you define dependencies, for example, task three depends on task two which in-turn depends on task one. By following “Dependency Based Programming” model, you can choose which task to run and the script will be able to figure out the next steps. In the snippet above it shows dependency based programming, run target will run task Build but Build depends on RunTests, therefore RunTests task will run first.
Getting Started with Cake
To get you started you need three files for a build. According to the Cake documentation these will be the only files that you will need to commit to your repository. Of the three files, I am particularly drawn to the following two files as explained by the documentation :
- build.ps1 and build.sh
These are bootstrapper scripts that ensure you have Cake and other required dependencies installed. The Cake build script is written in PowerShell and is responsible for invoking Cake. These files are optional, and not a hard requirement. If you would prefer not to use these scripts you can invoke Cake directly from the command line, once you have downloaded and extracted it.
2. build.cake
This is the actual build script. This is the file that you will be writing all your build steps for automating the build process.
Preparing Visual Studio for Cake
To get started with cake in Visual Studio 2017, you need to install Cake for Visual Studio Extension.
To install Cake for Visual Studio Extension
- In Visual Studio, go to tools => Extensions and Updates, then online search for Cake
2. Select and download Cake for Visual Studio and then install Cake.
3. Restart Visual Studio after the install has finished.
4. Open your project again and go to the build menu, you will find that there is now a new menu option “Cake Build”.
The build option allows you to download and install the PowerShell bootstrapper file. As explained before, the bootstrapper is the file that will download and install Cake from the NuGet Gallery and runs the Cake build script.
Setting up Cake in your Solution
In your solution, in Visual Studio go to the build Menu => Install PowerShell bootstrapper. The bootstrapper is used to download Cake and the tools required by the build script. This will add a build.ps1 PowerShell script in the Solution items folder like below:
In Solution Items, right click and select add items and choose a text file and name it build.cake like below:
The build.cake file should be in the same location as the bootstrapper script that you downloaded. Your Solution explorer should look like the one below:
First build.cake
In the build cake file is where we write C# code that will contain all the tasks and build automation steps we want to execute.
The code is fairly simple and one can build on top of it.
At the top of the script some arguments are defined. Target defines the task to run first. Configuration defines the build configuration to use. The configuration can be debug or release, in my case it is release.
The first task defined is “Clean”, this is the task that will run to clean and it deletes all the artifacts for the previous build in our destination folder. The next task is the “Restore” task, this is responsible for running dotnet to restore all the packages in the solution. Note that the “Restore” is dependent on “Clean”, it will only run after the “Clean” task has completed.
The “Build” task will build the specified project using the configuration defined in the configuration variable.”Test” is the next task to be run, this will run dotnet test on the test project in the solution. In our production project we also drop the xml test results file in the artifacts folder where it is used by Jenkins build server to check whether our tests passed or failed. Lastly, the “Default” task, default task is run in the RunTarget function. RunTarget will execute the task specified in the target argument.
Conclusion
It is a good idea to commit the build files. In our case when a developer commits code into our repo, jenkins is configured to kick off a build which sets off Cake to run a build on the server. With cake we achieve having a build without dependency on Visual Studio on the build server.
There is a lot of documentation to get you started with CAKE. You can read more on the Cake website. Another interesting article is the one written by Andrew Lock “Building ASP.NET Core apps using Cake in Docker”. Andrew explains how to build .Net Core apps using cake in docker.