Controlling application version number with NAnt and TeamCity

I’m pretty sure almost every developer has ever struggled on how to change version number in the different way than TeamCity provides that by default. In my case I wanted to get date-based version number to clearly represent a sprint in which the build was created.
Currently I use 2 weeks long sprints in my project and want version number following the pattern <Major>.<Sprint>.<Revision>.<Counter>. So, <Sprint> should be calculated depending on Today date and date when the project was started.

BTW, it’s more interested to me to have the following pattern <Major>.<Sprint>.<Date>.<Revision> since <Counter> is useless. But in this example I will use the first one.

By default, it’s impossible to add a calculation to get version number in the TeamCity. I guess there should be some way to do that using plug-in or something like that. But I could not find anything useful to me yet. I would be very appreciated if someone sends me a link to such solution.

My approach relies on NAnt scripting potential.

NAnt has in its arsenal the task <script> which appeared very useful in my case. You should look its description here. You should place it within the target where you want to use it.

I have not investigate for possible scope visibility issues so this is the open question whether functions declared within the script are visible in other targets.

The following code presents the code which actually does all required work:

  <target name="version">
    <script language="C#" prefix="myCode">
        public static string GetSprintNumber() {
          DateTime projectStartDate = new DateTime(2011, 04, 25); // project beginning date
          ... // calculate sprint number
          return sprintNumber.ToString();
    <property name="teamCityVersion" value="${Version}"/>
    <property name="sprintNumber" value="${myCode::get-sprint-number()}"/>
    <property name="correctedVersion" value="${string::replace(teamCityVersion, '{sprint.number}', sprintNumber)}"/>
    <echo message="##teamcity[buildNumber '${correctedVersion}']" />
    <echo message="Building version ${Version}" />
    ... // patching version number in the solution

Some lines were removed to not harm property rights of my client. The algorithm is very simple though.

Several things you should notice about the code above:

    1. You should use the attribute [Function(“function-name”)] to expose the custom function to the NAnt script
    2. You should call the custom function using the expression: ${prefix:function-name()}
    3. You should interact with TeamCity from your NAnt script

The first and the second should be clear except the last one. The ways to interact with TeamCity is described pretty clear in the TeamCity Online Documentation. It’s worth to get to know about that because it surely is useful.

So, keeping all that in mind I should tell you about weak point of the approach. It’s necessary to specify a custom tag in Build number format field of the TeamCity project configuration. I use {sprint.number}. The weak point is that you must remember about that and it seems in UI.

This is how I specify the tag in TeamCity:


This is how it seems in UI:


Although the number is replaced and presented in build history correctly. You can see that on the screenshot above.

Tags: ,

2 thoughts on “Controlling application version number with NAnt and TeamCity”

  1. Hi

    I’m trying to follow the above, but I am currently getting a:
    [13:29:10]: [Step 1/3] Expression: ${Version}
    [13:29:10]: [Step 1/3] ^^^^^^^
    [13:29:10]: [Step 1/3] Property ‘Version’ has not been set.

    My Nant script doesn’t complete look as yours, as I only want to set the version number along with the counter.
    What is the $Version property, is that something you are retrieving from TeamCity ???

    1. Hi Dennis.

      Thank you for the question.
      You should create this property in the beginning of the script as follows:
      < property name=”Version” value=”″ />

      This is the default value for the other property ‘teamCityVersion’. The later is changed after that as stated above.

      Let me know, please, if that helps?

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Related Post

%d bloggers like this: