Using Date Version Numbers for Assemblies in TeamCity

Date Version Number in TeamCityIn some projects, I use the AssemblyInfo Patcher build feature to modify the AssemblyInfo.cs’s version information.  Mainly I was just using a static version with the %build_number% suffixed at the end.  Something like 1.2.3.%build_number%.  However, I decided to go with a date version number of YYYY.MM.DD.%build_number%

Variables

The first thing that caused me an issue was there is no existing system or environment variables defined that provide you with date parts.  I figured this by adding a new build step for creating an environment variable using Service Messages.

Service messages are specially constructed pieces of text that are used to pass commands/information about the build from the build script to the TeamCity server.

To be processed by TeamCity, they need to be written to the standard output stream of the build, i.e. printed or echoed from a build step. It is recommended to output a single service message per line (i.e. divide messages with newline symbol(s))

What this allowed me to do was create a build step in PowerShell and use Write-Host to output a service message:

Write-Host "##teamcity[setParameter name='env.BUILD_DATE' value='$([DateTime]::Now.Year.ToString() + "." + [DateTime]::Now.Month.ToString() + "." + [DateTime]::Now.Day.ToString())']"

This will create a new environment variable that I can use called %env.BUILD_DATE%

AssemblyInfo Patcher

As mentioned, I use this build feature to modify the AssemblyInfo.cs, however, I immediately ran into an issue.

AssemblyInfo Patcher should be used with the automatic checkout only: after this build feature is configured, it will run before the first build step. TeamCity will first perform replacement in the files found in the build checkout directory and then run your build.

The issue is that the AssemblyInfo patcher is run before the first build step which is setting the environment variable.  Meaning I cannot use the environment variable in the AssemblyInfo patcher.

Snapshot Dependencies

What I decided to do was create a new build configuration that only contained one build step.  That build step would be the PowerShell above which sets the environment variable.  Then I would link my existing build configuration to this new build configuration.  In TeamCity these are defined as SnapShot Dependencies.

Build configurations linked by a snapshot dependency will use the same snapshot of the sources. The build of this configuration will run after all the dependencies are built. If necessary, the dependencies will be triggered automatically.

Dependency Properties

Once I had my dependencies defined, you can use build parameters from linked dependencies.  Now in the assembly patcher, I can use the environment variable by:

%dep.[ConfigurationID].env.BUILD_DATE%

 

Octopus Deploy in Your Cake (C# Make)

Octopus DeployI’ve looked at using Cake (C# Make) for build automation in C#.  The basics were to compile a solution/project using MSBuild and then run our automated tests with xUnit.

Another common set of tasks that are performed in a build pipeline are:

  • Create a NuGet package
  • Push the NuGet package to Octopus Deploy
  • Create an Octopus Deploy Release

NuGet

First thing we need to do is to create a NuGet package.  You have a couple options here, one is to create a nuspec and invoke the Nuget.exe to create your package.  I’m going to choose an alternative which is to use the built-in Nuget support to generate our NuGet package all within code.

I’ve added a new “Pack” task which is called from our “Default” task.  This task will create our NuGet package when we run our build.ps1

Now when we run our build, we can see the Pack task was created our NuGet package: “CakeDemo.0.0.0.1.nupkg”

pack

Octopus Deploy

Cake has built-in support for Octopus Deploy.  To get started, you need to include the OctopusTools in your build.cake file.

#tool "nuget:?package=OctopusTools"

We can use the OctoPush method for pushing your newly created NuGet package to the Octopus Deploy NuGet Server.

Create Release

Now that our NuGet package has been pushed to Octopus Deploy, we can create a release using the OctoCreateRelease method.

To tie this all together, we need to make sure that our Default task will run our OctoPush and OctoRelease tasks.  Here is our final build.cake file

Now when we run our build we can see that our Octopus Deploy release was created.

result

More

There are a ton of built-in tasks and the Cake documentation is really good.  Hopefully you can see the benefits of having a build script in code which can be version controlled and run anywhere.

Let me know if you have any comments related to Cake or any other build automation tooling either in comments or on twitter.


Source Code

GithubThe source code for this demo is available on GitHub.

Automating Builds with Cake (C# Make)

Cake C# MakeI’ve used various build systems for compiling, testing and deploying .NET based applications.

TFS, VSTS, AppVeyor, TeamCity have had one thing in common.

They all contained the configuration of my build, test and deploy pipeline in their system with no way to extract it.

Build as Code

Removing the build steps out of your build system and turning into code has two major benefits to me:

  1. Build Anywhere: Once you have a build script, you should be able to execute and build it anywhere.  No longer are you relying on the build server and it’s build steps which are specific to that build system.
  2. Source Control: Since you build is now in code, can can live right along side your application in source control.  This means that if you have the source, you have the build script.

Cake?

Cake (C# Make) is a build automation tool for .NET.  It allows you to write C# to run various Tasks that you would likely find as build steps on your build server.  Such as compile code (msbuild), run unit tests (xunit, nunit, mstests), creating nuget packages, create deployments via Octopus Deploy and a pile more.

Getting Started

It’s really easy to get started using Cake.  I’ve created a demo which is available on GitHub.  It contains a basic Hello World application along side the Cake script described in the rest of this blog.

Video

If you prefer watching a video tutorial, I’ve added a video that outlines the same content as this blog.

Build Script

First thing you need to do is get the Cake build script that is written in PowerShell.  From your project folder, run the following command to download the latest PowerShell Ssript (build.ps1)

Invoke-WebRequest http://cakebuild.net/download/bootstrapper/windows -OutFile build.ps1

Cake Script

Next we need to create our Cake script.  This script will define all the build tasks that the PowerShell Build Script (build.ps1) will execute.

Create an empty file “build.cake” in the same directory along side the build.ps1.

I recommend using VS Code along with the Cake extension to create and edit your build.cake file.

Build

In this my demo application, I have a CakeDemo.sln that I’m going to build.  it contains two projects, CakeDemo and CakeDemo.Tests which has an xUnit test.

solution

 

In our build.cake, let’s setup our first task to run MSBuild on our solution.

Above we define a task named “Default” which calls MSBuild.  Then to invoke Cake by calling RunTarget specifying our default task.

Now we can run our build.ps1 powershell script which will execute our build.cake C# script.

output

You can see that Cake downloaded some packages from NuGet which it requires to run the build, compiled our build.cake, and then executed it and its tasks (MSBuild).

If we take a look in our bin\ directory, we can see all the build output files.

C# Make

Running Tests

There are many different types of tasks you can define in your cake script.  Take a look at all the built-in API’s.

A common task you may perform is running Unit Tests.  In my Demo I have a project with an xUnit test.

We can run the xunit console test running from our cake script as well.

The fist thing we do is tell Cake we need an external tool from NuGet. In our case we need the xunit console runner.  At the top of our build.cake script, add

#tool "nuget:?package=xunit.runner.console"

Now we can add a task to run our xunit tests.

I’m going to modify our script a bit further in order to separate our compiling using msbuild and running our xunit tests into separate tasks.  You can tell Cake which tasks are depend on on others.

In this example, our xUnit task is going to be dependent on a build.

Let’s execute our build script again and see the output of our build and the xUnit console runner.

xunit

Integration

Now that we have our build in source code instead it being defined as build steps on our build server, we can simply invoke our build.ps1 from our build server as a single step.

More

There are a ton of built-in tasks and the Cake documentation is really good.  Hopefully you can see the benefits of having a build script in code which can be version controlled and run anywhere.

Let me know if you have any comments related to Cake or any other build automation tooling either in comments or on twitter.


Source Code

GithubThe source code for this demo is available on GitHub.