How to: Customize the build process

After hearing this q a zillion times, I have finally gathered enough enthu to post an entry on this. In fact, this is one of my favourite features in Team Build – the ability to plug in custom tasks at any point in the build process.

The tfsbuild.proj project file contains only properties grouped together that can be modified to achieve different effects in the build process. These properties are actually used as input parameters to the tasks in the TeamBuild.targets file that can be found on the build machine. Here are the targets that are plumbed between the constituent tasks of the targets file: 

  • BeforeClean
  • AfterClean
  • BeforeGet
  • AfterGet
  • BeforeLabel
  • AfterLabel
  • BeforeCompile
  • AfterCompile
  • BeforeTest
  • AfterTest
  • BeforeDropBuild
  • AfterDropBuild
  • BeforeOnBuildBreak
  • AfterOnBuildBreak

Where exactly these are intertwined in the build proces is predictably easy from the names themselves. Now, let’s try and figure out what interesting tasks are likely to be performed in these targets above. You might want to backup your older files in the build directory in the BeforeClean target, drop an extra file(s) into the build directory once cleaning is over in the AfterClean target, you could possibly make a change to the created workspace in the BeforeGet target thereby excluding some of your files, again you might want to add some file(s) to the build directory in the AfterGet target. The BeforeLabel target is a good place to add tasks that could write on the synced files before a label is applied on to them, the AfterLabel target can be used to place a task that might want to do some relabelling actions. BeforeCompile can be used to place a number of the prebuild tasks that are so common, AfterCompile can be used to perform your own custom checks on the assemblies just compiled. BeforeTest target can be used as a placeholder for a task that can probably install the built assemblies before performing tests on them while AfterTest target could hold tasks that could uninstall the product and leave the build machine in a state that it was in before installation of the assemblies. BeforeDropBuild could be used to copy extra file(s) from maybe the Sources folder into the Binaries folder on your build directory so that those can also be copied to drop location. AfterDropBuild can house tasks that would copy your assemblies to additional drop locations or perhaps zip sources and copy them to additional locations. BeforeOnBuildBreak gives the user a chance to evaluate the build break and the cause before a work item is opened for it and AfterOnBuildBreak could be used to place a task that would perhaps send mail to a specific set of people saying a build break has occurred.

Here is what a sample TFSBuild.proj file would look like with all your custom tasks plugged into it:

<Target Name="BeforeBuild">

    <CreateItem Include="$(BinariesRoot)\**\*.*" >

      <Output ItemName="BinsToCopy" TaskParameter="Include" />

    </CreateItem>

    <Copy

          SourceFiles="@(BinsToCopy)"

          DestinationFiles="@(FilesToCopy ->'\\MySvr\Backup\%(RecursiveDir)%(Filename)%(Extension)')"

          SkipUnchangedFiles="false" />

</Target>

  <Target Name="AfterOnBuildBreak">

    <SendMail

          SendTo="$(BuildBreakGroup)"

          Content="Wake up! Build break in build number $(BuildNumber)"

          />

</Target>

  <Target Name="BeforeTest">

    <InstallMSI MSIPath="$(BinariesRoot)\$(Platform)\$(Configuration)" DestinationPath="C:\Program Files"/>

  </Target>

Remember that using a custom target need not entail writing a separate custom task all the time. There are several useful tasks like Exec, Copy, Message etc that ship with MSBuild. You could easily employ those tasks to work out the desired outcome with your custom targets.