Third Shelf

Source Code Promotion Model

Posted in team foundation server by Sydney du Plooy on September 24, 2008

At work we make use of a source code promotion model. What this means is that we promote source code through the various stages of product development.

All new development is done at the tip level. Once development is completed; and I’ll leave the definition up to you; the source code is promoted to the pre-stage level. It is at this level where our internal testers can begin testing the latest release of the product.

Only when the internal testers are satisfied, is the pre-stage source code promoted to the stage level. This is the level where our business users have access to the latest product release. They will in turn begin their testing. Once the business users are satisfied with the release, the stage source code will be promoted to the live or production level.

All this is accomplished by means of source code labels in Team Foundation Server Version Control and in a moment I’ll show you how to setup an MSBuild target that will take care of performing this type of promotion for you.

Note that although the source code is promoted, the labels in the version control system are in fact being shifted downwards, as shown in the picture. Also note that for every source code promotion there is a corresponding build process that kicks-off.

The first thing that we need is a set of label names that we will use to identify the various promotion levels. For this post I’m going to use the following label names: pre-stage, stage and live. You might wonder where the label is for tip – there isn’t one. We make use of the special version spec called T, which marks the latest version of the source code in Team Foundation Server Version Control by default and is always present.

I suggest creating a property group for these labels in case they need to change at some later stage.

<propertygroup>
<prestagelabel>pre-stage</prestagelabel>
  <stagelabel>stage</stagelabel>
	<livelabel>live</livelabel>
</propertygroup>

There are rules that we need to have in place before any source code promotion can happen. Here is a summarized list of rules:

  • A valid FromLabel parameter must be specified;
  • A valid ToLabel parameter must be specified;
  • The pre-stage label can only be moved to tip;
  • The stage label can only be moved to pre-stage;
  • The live label can only be moved to stage.

Here they are represented in the build file:

<error Condition="'$(FromLabel)'==''"
	Text="The FromLabel property has not been specified."
/>

<error Condition="'$(ToLabel)'==''"
	Text="The ToLabel property has not been specified."
/>

<!-- check that the label name we are going to move is valid -->
<error Condition="'$(FromLabel)'!='$(PreStageLabel)' and '$(FromLabel)'!='$(StageLabel)' and '$(FromLabel)'!='$(LiveLabel)'"
	Text="Valid FromLabel values are $(PreStageLabel), $(StageLabel) or $(LiveLabel)"
/>

<!-- check sanity : pre-stage label can only move to tip -->
<error Condition="'$(FromLabel)'=='$(PreStageLabel)' and '$(ToLabel)'!='T'"
	Text="$(PreStageLabel) can only be moved to tip (T)."
/>

<!-- check sanity : stage label can only move to pre-stage -->
<error Condition="'$(FromLabel)'=='$(StageLabel)' and '$(ToLabel)'!='$(PreStageLabel)'"
	Text="$(StageLabel) can only be moved to $(PreStageLabel)."
/>

<!-- check sanity : live label can only move to stage -->
<error Condition="'$(FromLabel)'=='$(LiveLabel)' and '$(ToLabel)'!='$(StageLabel)'"
	Text="$(LiveLabel) can only be moved to $(StageLabel)."
/>

At this point we can be fairly sure that we are going to move labels to where they are supposed to be. On with the promotion. The actual process of moving the labels is fairly straight forward.

There are three different cases to consider when moving labels:

Special case #1 – Moving the live label:

I have not yet spoken about the labels that are attached to previously live versions. It might be necessary to track the source code version that was previously live, just in case the product needs to be rolled back for some or other reason. I term this label the previous-live label. If you need to keep track of all the previous live source code, then I suggest creating a custom build task that simply returns a current date/timestamp and mangle this with the previous-live label. If you only need to keep track of the previous version, you can simply just add it to the property group with all the other label names.

If we are moving the live label which is indicated by the FromLabel property, we first need to label the version at the current live label with the previous-live label. This is done with the following command:

    <!-- Create a previous live label -->
    <exec Condition="'$(FromLabel)'=='$(LiveLabel)' and '$(ToLabel)'=='$(StageLabel)' and '$(LiveLabelExists)'=='true'"
        WorkingDirectory="$(SolutionRoot)"
        Command="&quot;$(TfCmd)&quot; label /server:$(TeamFoundationServerName) &quot;$(PreviousLiveLabel)@$(ProjectSourceRootPath)&quot; $(ProjectSourceRootPath) /version:L$(LiveLabel)@$(ProjectSourceRootPath) /recursive"
    />

Property values in the command line:

  • $(TfCmd) points to the location, including tf.exe.
  • $(TeamFoundationServerName) is machine name where Team Foundation Server is installed on.
  • $(ProjectSourceRootPath) is the source control folder of the project, for example $/MyProject.

Note the L in /version:L – which means that we are referring to the source code version labeled with the label that follows L.

Our next step is to move the live label to the stage label, which is done with the following command:

    <!-- Move Live to Stage -->
    <exec Condition="'$(FromLabel)'=='$(LiveLabel)' and '$(ToLabel)'=='$(StageLabel)'"
        WorkingDirectory="$(SolutionRoot)"
        Command="&quot;$(TfCmd)&quot; label /server:$(TeamFoundationServerName) &quot;$(PreviousLiveLabel)@$(ProjectSourceRootPath)&quot; $(ProjectSourceRootPath) /version:L$(LiveLabel)@$(ProjectSourceRootPath) /recursive"
    />

Special case #2 – Moving the pre-stage label to tip:

When moving the pre-stage label to the tip, there is a small change that has to be made to the command line. Referring to the tip version in the versionspec is simply a T and is not prefixed with L – which indicates a label.

Below is the command line that has to be executed when moving from pre-stage to tip:

    <exec Condition="'$(ToLabel)'=='T'"
        WorkingDirectory="$(SolutionRoot)"
        Command="&quot;$(TfCmd)&quot; label /server:$(TeamFoundationServerName) $(FromLabel)@$(ProjectSourceRootPath) $(ProjectSourceRootPath) /version:$(ToLabel) /child:replace /recursive"
    />

General case:

In all the other cases we simply move the source code labels based on the criteria given. The command line for this general case is shown below:

    <exec Condition="'$(FromLabel)'!='$(LiveLabel)' and '$(ToLabel)'!='T'"
        WorkingDirectory="$(SolutionRoot)"
        Command="&quot;$(TfCmd)&quot; label /server:$(TeamFoundationServerName) $(FromLabel)@$(ProjectSourceRootPath) $(ProjectSourceRootPath) /version:L$(ToLabel)@$(ProjectSourceRootPath) /child:replace /recursive"
    />

Note: The above command lines, with the exception of Special case #1, will overwrite previous applied labels. It will also perform a recursive labeling of all the items in the source path with the new label.

And that is all that there is to it!


Tagged with: ,

7 Responses

Subscribe to comments with RSS.

  1. Jan said, on April 16, 2009 at 1:52 PM

    Hi there,

    this is a very interesting post, but there are a few things I don’t quite understand

    – why are the labels in the version control system being shifted downwards?
    How do you work with the labels then? What do you do when development is done and you want to promote it for the internal test

    – i have no experience using MSBuild targets, so how does executing it work?

    – you say that “for every source code promotion there is a corresponding build process that kicks-off”.
    How have you realised that?

    A lot of questions I know, but we are investigating if we want to use Team System so we don’t have a lot of experience with it and we havn’t worked with MSBuild also…

    T.i.a.

  2. Sydney du Plooy said, on April 16, 2009 at 8:22 PM

    Thank you for your comments and questions.

    Labels are used to mark and group a set of files that belong together, for example, the set of source files that make up the internal test version. Now, assuming that there aren’t any other labels in the version control system, you would want to apply this new “internal-test” label to current version of source code, which is known as “T”. T (Tip) is a well known version specification in Team Foundation Server. That will result in the “internal-test” label to be at the same level as T. As soon you start developing and follow that up with a check-in, the internal-test label will be at a level above or below (it’s a perspective thing) the T version. The point of the matter is that we are continually moving the “internal-test” label to the latest version T, whether you see that below or above the latest version T.

    After development is done, you would simply execute the target called “Promote” which is defined in the build file as:

    <Target Name=”Promote”>
    … all the code in the post …
    </Target>

    It will typically be executed from the command line as:

    c:\>msbuild tfsbuild.proj @tfsbuild.rsp /p:SolutionRoot=”[project source code directory]” /target:promote /p:FromLabel=pre-stage /p:ToLabel=T

    That will execute the Promote target and pass it two parameters, namely FromLabel and ToLabel with pre-stage and T as the respective parameter values. This will result in the pre-stage label being removed from the current set of files it marks and re-applied to the current version T.

    A build can be automatically kicked off by using the Exec task to execute the tfsbuild.exe start command.

  3. Jan said, on April 23, 2009 at 3:19 PM

    Hi there,

    thanks for the response, I think I almost get it.
    If I understand it correct, you manually asign the live label?

    Where do you execute the msbuild, has to be on the server?
    If I want to kick off a build for a specific promotion group I probably have to configure the build to only use sources with a specific label?

    Again thanks

  4. Sydney du Plooy said, on April 23, 2009 at 5:14 PM

    The live label is automatically assigned when you promote the build from the stage label to the live label. Have a look at special case #1 in the post. What happens is that the current version of live is first marked with a new label. It looks something along the lines of live-23042009. We then execute the following command on the command line: c:\>msbuild tfsbuild.proj @tfsbuild.rsp /p:SolutionRoot=”[project source code directory]” /target:promote /p:FromLabel=live /p:ToLabel=stage. This will move the live label to the same place in the version control system where the stage label is. This is how we promote the stage version to live. If the live label didn’t exist, it will automatically be created when the above mentioned command line is executed.

    A promotion can be done from your workstation by executing the command line c:\>msbuild tfsbuild.proj @tfsbuild.rsp /p:SolutionRoot=”[project source code directory]” /target:promote /p:FromLabel=[pre-stage/stage/live...] /p:ToLabel=[pre-stage/stage/live]. It does not have to execute on the server as it is only moving labels in the version control system. Provided that it is executed in a folder where TFS can determine your workspace.

    That’s correct, a separate build must be configured and set to checkout the source code for a specific label. In our configuration I have separate builds configured to use a different response file (.rsp) that specifies the version of source code to use. This is done using the /version:L[pre-stage/stage/live...] parameter of the tf.exe utility.

  5. Jan said, on April 23, 2009 at 5:48 PM

    Hi there,

    I assume it wasn’t possible to move the label from stage to live.
    In your post you have this condition:

    based on that I assumed it wasn’t possible, and that confused me a bit because the logical approach is to move the label ‘up’ from stage to live.


Leave a Reply