Team Build and Azure

I’m a big fan of Team Build, it keeps the project rhythm going and without it there is no real way of knowing that the code people are checking in works.  It was therefore an easy choice to decide to use it on my current project.

Normally it does take a bit of time to get the build up and running properly (hopefully something that will be easier in Rosario), but I was a little surprised to see that we were hitting issues with Azure projects.  Whilst an IDE build worked, a Team Build of the same source tree didn’t.  It kept complaining about the source path being to long.  This error kept our build manager struggling for a while as Team Build is notorious for falling over due to the Windows max path length of 260 characters.

However we were seeing something really weird.  We were getting recursive copying of our worker role binaries folder.

In our release folder we had this structure.

 
\Release\CloudService.csx\roles\worker\CloudService.csx\roles\worker\CloudService.csx\roles\worker…

This carries on until the path length exceeds 260 characters.

We eventually tracked it down to an issue with ‘CSPack’, a build task that the Azure project type uses to build itself.

We fired an email off to some people in the Azure product team and got an answer fairly quickly.

“Team Build flattens the output from each project into the binaries folder, because we build into a sub folder (the .csx one), Team Build recursively copies and flattens the output.”

We also got a fix.

By setting the following flag in our tfsbuild.proj file

 <PropertyGroup>
  <CustomizableOutDir>true</CustomizableOutDir>
</PropertyGroup>

our project-specific OutputPath properties are preserved, the flattening doesn’t happen, and we get a successful Team Build.  A side effect of setting that flag is that nothing ends up in the ‘Binaries’ folder, so nothing ends up in your drops folder.  You can solve this using the following target, again in your tfsbuild.proj file.

 <Target Name="BeforeDropBuild" Condition=" '$(IsDesktopBuild)'!='true' ">
  <ItemGroup>
    <BuildOutputFilesToCopy Include="$(SolutionRoot)\My.CloudService\bin\Release\**\*.*" />
  </ItemGroup>

  <Copy
    SourceFiles="@(BuildOutputFilesToCopy)"
    DestinationFiles="@(BuildOutputFilesToCopy ->'$(BinariesRoot)\%(RecursiveDir)%(Filename)%(Extension)')" />
</Target>

Hope this helps.  Thanks to Hani Atassi and Stuart McCarthy.