Showing posts with label build. Show all posts
Showing posts with label build. Show all posts

Friday, February 20, 2009

How to add custom build step to a TFS Server Build ?

Most of the time when you are creating a build script (TFSBuild.proj), you need to do some steps after the build. Wether it's creating an MSI for easier deployment, creating a VSI for a Visual Studio Add-in, or whatever if may be... you normally do a post build.

A post build event looks like the following inside the TFSBuild.proj :

<Target Name="AfterDropBuild">
  <CallTarget Targets="PostBuildStep" />
</Target>

<Target Name="PostBuildStep">
  <!-- Do something -->
</Target>

When you only have 1 or 2 tasks and that one fails, it might be easy to find the one that failed. What if you have 8 to 20 tasks? It then becomes incredibly hard to find which one failed. What I've seen the most is normally some "<Message />" tags with some descriptive tasks. This is the equivalent of debugging with Console.WriteLine or Debug.Print.

What if you could know EXACTLY which task failed to run? Here is a way to add a custom build step to your TFS build which will allow you to easily know what crashed.

<Target Name="PostBuildStep">
  <!-- Create the build steps which start in mode "Running" -->
  <BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" Message="Doing Something on a PostBuild Event" Condition=" '$(IsDesktopBuild)' != 'true' ">
    <!-- Return the ID of the tasks and assigned it to "PropertyName" -->
    <Output TaskParameter="Id" PropertyName="PostBuildStepId" />
  </BuildStep>

  <!-- Do something -->

  <!-- When everything is done, change the status of the task to "Succeeded" -->
  <BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" Id="$(PostBuildStepId)" Status="Succeeded" Condition=" '$(IsDesktopBuild)' != 'true' " />

  <!-- If an error occurs during the process, run the target "PostBuildStepFailed" -->
  <OnError ExecuteTargets="PostBuildStepFailed" />
</Target>


<Target Name="PostBuildStepFailed">
  <!-- Change the status of the task to "Failed" -->
  <BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" Id="$(PostBuildStepId)" Status="Failed" Condition=" '$(IsDesktopBuild)' != 'true' " />
</Target>

With that in place, you will see exactly which task failed. As a bonus, it will also give you the time at which it completed. This will easily allow you to compare with your other task to see which one is taking the most time.

I would like to thank Martin Woodward which is a TeamSystem MVP. The question originated from Stackoverflow and more details are also available on Martin's website.

Submit this story to DotNetKicks

Friday, January 30, 2009

Build fail only on the build server with delay-signed assemblies

[Any CPU/Release] SGEN(0,0): error : Could not load file or assembly '<YOUR ASSEMBLY>' or one of its dependencies. Strong name validation failed. (Exception from HRESULT: 0x8013141A)

I got that error from our build machine. It crashed wonderfully and would tell me that an assembly could not be loaded.

After 1 hour of search I finally found the problem.

We are in an environment where we delay-sign all of our assemblies and we are fully signing them on the build server as an "AfterDrop" event. Of course, we add a "Skip Verification" for the public key token we are using so that we can put them inside the GAC.

All of our projects (more than 20) we built exactly that way and I was seeing no way why it would happen. I then decided to look at what depended on this assembly. 1 project and it was the one that was failing inside the "Build Status".

I then found something that was used inside that specific project that was never used anywhere else. Somebody used the tab "Settings" to store application settings. Not a bad choice and a perfectly sound decision but... how can this make the build crash?

Well... it seems like using "Settings" force a call to SGEN.exe and SGEN.exe won't take any partially signed assemblies. It's then that I figured out that our build server didn't had any of those "Skip Verification".

After searching Google for some different terms, I found out under the "Build" tab a way to deactivate the call to SGEN. It's called "Generate Serialization Assembly". By default, the value is "Auto". After settings the value at "Off" for "Release" mode only, the build was fixed and we were happy campers.

Submit this story to DotNetKicks