How to trigger an Agent based release from MSBuild

I was recently asked how to trigger an Agent based release from MSBuild.  This is a valuable technique if you are upgrading from an older version of TFS and want to use the Upgrade Template are already use MSBuild for Maven or Ant builds with Team Explorer Everywhere.

The key is using the Exec task to make a call to ReleaseManagementBuild.exe

<Exec WorkingDirectory="C:/Program Files (x86)/Microsoft Visual Studio 12.0/Release Management/bin" Command="ReleaseManagementBuild release -tfs &quot;$(TeamFoundationServerUrl)&quot; -bd &quot;$(BuildDefinitionName)&quot; -bn &quot;$(BuildNumber)&quot; –tp &quot;$(TeamProject)&quot; –ts &quot;$(ReleaseTargetStage)&quot; "/>

Most of the properties used in the call are provided by Team Build with the exception of $ReleaseTargetStage. That is defined earlier in the project file via a Property Group.

<PropertyGroup>

   <ReleaseBuild>true</ReleaseBuild>

   <ReleaseTargetStage>QA</ReleaseTargetStage>

</PropertyGroup>

The Release Target Stage identifies the desired stage to deploy through. All the previous stages will also be deployed to but the release will stop at the target stage.  The Release Build property is used to decide if this build should be released or not.  It is used as the condition to the AfterDropBuild target we override to trigger the release.

<Target Name="AfterDropBuild" Condition=" '$(ReleaseBuild)'=='true' ">

Only when Release Build is set to true will the build trigger a release in Release Management.  The values set in the Property Group are just the default values each of which can be overwritten from the build definition.

If you are using Tokenization you will have to add additional targets. For an explanation of Tokenization please see the attached Release Management for Visual Studio 2013 User Guide PDF.  Before the build is dropped we will need to swap the token files.  We can make sure the swap happens by defining a dependency on the Before Drop Build target.

<PropertyGroup>

   <BeforeDropBuildDependsOn>

      SwapTokenFile;

   </BeforeDropBuildDependsOn>

</PropertyGroup>

 

<Target Name="BeforeDropBuild" DependsOnTargets="$(BeforeDropBuildDependsOn)" />

Now we just need to define the SwapTokenFile target.

<Target Name="SwapTokenFile">

   <BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" Name="SwapTokenFileBuildStep" Message="Swap token files">

      <Output TaskParameter="Id" PropertyName="SwapTokenFileBuildStepId" />

   </BuildStep>

   

   <Message Text="Swap token files" />

   <Exec WorkingDirectory="$(BinariesRoot)/ " Command="del /Q web.config" />

   <Exec WorkingDirectory="$(BinariesRoot)/ " Command="rename web.config.token web.config" />

 

   <BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" Id="$(SwapTokenFileBuildStepId)" Status="Succeeded" />

   <OnError ExecuteTargets="OnSwapTokenFileTargetFail" />

</Target>

You will need to update each Exec task to point the folder containing the files to be swapped. In the example above we are pointing to a web.config file but you can tokenize any text based file.  The BuildStep, Output, Message and OnError tasks could be removed but are shown for completeness.

When you put everything together you will end up with something like this:

<PropertyGroup>

   <BeforeDropBuildDependsOn>

      SwapTokenFile;

   </BeforeDropBuildDependsOn>

</PropertyGroup>

 

<Target Name="BeforeDropBuild" DependsOnTargets="$(BeforeDropBuildDependsOn)" />

 

<Target Name="SwapTokenFile">

   <BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" Name="SwapTokenFileBuildStep" Message="Swap token files">

      <Output TaskParameter="Id" PropertyName="SwapTokenFileBuildStepId" />

   </BuildStep>

   

   <Message Text="Swap token files" />

   <Exec WorkingDirectory="$(BinariesRoot)/" Command="del /Q web.config" />

   <Exec WorkingDirectory="$(BinariesRoot)/" Command="rename web.config.token web.config" />

 

   <BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" Id="$(SwapTokenFileBuildStepId)" Status="Succeeded" />

   <OnError ExecuteTargets="OnSwapTokenFileTargetFail" />

</Target>

 

<Target Name="OnSwapTokenFileTargetFail">

   <BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" Id="$(SwapTokenFileBuildStepId)" Status="Failed" />

</Target>

 

<PropertyGroup>

   <ReleaseBuild>true</ReleaseBuild>

   <ReleaseTargetStage>QA</ReleaseTargetStage>

</PropertyGroup>

 

<Target Name="AfterDropBuild" Condition=" '$(ReleaseBuild)'=='true' ">

   <BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" Name="StartReleaseBuildStep" Message="Starting Release">

      <Output TaskParameter="Id" PropertyName="StartReleaseBuildStepId" />

   </BuildStep>

   

   <Message Text="Starting Release, located at '$(PackageLocation)' for $(ReleaseTargetStage) stage." />

   <Exec WorkingDirectory="C:/Program Files (x86)/Microsoft Visual Studio 12.0/Release Management/bin" Command="ReleaseManagementBuild release -tfs &quot;$(TeamFoundationServerUrl)&quot; -bd &quot;$(BuildDefinitionName)&quot; -bn &quot;$(BuildNumber)&quot; –tp &quot;$(TeamProject)&quot; –ts &quot;$(ReleaseTargetStage)&quot; "/>

 

   <BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" Id="$(StartReleaseBuildStepId)" Status="Succeeded" />

   <OnError ExecuteTargets="OnStartReleaseTargetFail" />

</Target>

 

<Target Name="OnStartReleaseTargetFail">

   <BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" Id="$(StartReleaseBuildStepId)" Status="Failed" />

</Target>

The On*TargetFail targets are for error reporting should something fail during the release process.  You can simply copy the code above the close Project tag at the bottom of your MSBuild project file.

With this in place you can now trigger an Agent based release from MSBuild.

Release Management for Visual Studio 2013 User Guide.pdf (3.5MB)

Comments (5) -

  • simion

    10/26/2015 1:26:15 AM | Reply

    hi donovan

    Im currently trying to get my TFS to trigger a release in release management 2013. Im using TFS with eclipse. what you have written here seems like what i need. but what i need to know, is. do i make these alterations to the upgrade template, or to the ms build file?

    Thanks in advance.

  • simion

    10/26/2015 1:44:08 AM | Reply

    hi dovovan

    I altered my TFSbuild.proj file that was generated via eclipse. and it failed on the swap token file section. Was this really needed? it didnt seem to make sense with what i was doing, plus there is to web.config file when Ant does it's build.

  • Asif

    3/31/2016 7:25:28 PM | Reply

    Hi Donovan
    Does TFS2013 has an option to run a build definition using tfsbuild command (in a bat file maybe) with Release Build (Release Mngt) option set to True?.
    By default I’ve set it to false in build def bcoz I don’t want developers to run build and deploy to Test env and only my scheduled bat file should run build with Release Build True option, basically overwrite Release Build default option of false to True ?

    • Donovan

      5/20/2016 3:10:37 PM | Reply

      I don't think you can. I would just create another scheduled build that triggers the release. You can hide that build from your team if you want.

  • Fazil

    7/24/2017 12:10:59 PM | Reply

    Hi Donovan,

    Really a nice post , I literally need your help . I have  configured CI on one of my project solution which contains DB, SSAS , SSRS and SSIS project files as well. I could able to build the project file of Database but for BI projects it shows  MSBUILD is not supported . Could you please provide me the step by step process and argument details  with commands so that I can try . I am using TFS 2013  in my laptop.  Appreciate your help in advance or let me know if it is not possible with some evidences.

Pingbacks and trackbacks (1)+

Add comment

Loading