Using the new TFS Build object model in ORCAS

*Moved to: http://fluentbytes.com/using-the-new-tfs-build-object-model-in-orcas/

At info support we participate in the so called Techncal Adoption Program(TAP) for Visual Studio Team System ORCAS. This is where we work closely with Microsoft with the latest available bits on ORCAS and provide early feedback. With our software factory Endeavour we have a software product that closely integrates with Team Foundation server. Especially on the part of the build server we have done quite some work to embrace and extend the product. Therefore we where specially interested in the new build features in ORCAS and the way that would integrate with our stuff.

One of the things we have been working on for quite a bit the last few weeks is the renewed object model for the build. Or as I would put is, there is now an object model for the build 🙂

We ran into some problems with the object model since we have a build that runs outside the TFS environment and only reports back to TFS what it has done. This creates the exact same experience as with the out of the box build of TFS. We have a lot of extension on the build (like document status verification, documentation generation, integration of NUnit, etc) that we build based on NANT. The last few weeks we have done some work to make the build work the same way it does now on ORCAS. This was more work than we anticipated since we want it to be a seamless upgrade for our current projects and customers. (Meaning no script changes, only a new assembly we roll out)

One thing we need is a way to register a build the same way we did with V1. Only in ORCAS there is the notion of a build queue where you can queue your build. This automatically results in spawning the build that is defined in the server. In V1 you could just register a build and work from there.

Something that will be added post B2 is the ability to register a Manual build. The method will be called CreateManualBuild(). This will give the same behavior as in the V1 server. This is what we needed since queuing a build and directly stopping it would result in a failed build. Therefore we now have a temporarily workaround and that is to register the build with the old object model, since that is still available. We will upgrade our code to use the new OM as well as soon as we receive RC bits that has the new feature available.

The other thing we use is the option to register a new build step with the server. Interestingly we have a Task to register the step and a second task to signal the task as completed. Microsoft now provides an out of the box msbuild task for this called BuildStep. Since we don't want to change our scripts currently deployed, we wanted to implement the task ourselves using the object model. This is no problem since you can use the InformationNodeConverters.AddBuildStep() API to register new build steps. The interesting part was the FinishBuildStep task we have. There we needed to find the step we registered previously by name, therefore you need to use the InformationNodeConverters.GetBuildSteps() method. You need to provide the correct strings in the InformationTypes to get the correct result. The correct list of strings that will be accepted as valid input are the following:

·         AssociatedChangeset

·         AssociatedWorkItem

·         BuildStep

·         CodeCoverageSummary

·         CompilationSummary

·         ConfigurationSummary

·         OpenedWorkItem

·         TestSummary

·         *

 

You can also use the convinience methods GetMinimalBuildDetails(that passes null as the informationTypes and QueryType.None) or GetAllBuildDetails(that passes * as the information types and QueryType.All)

So the final code to find the previously registered step and register it as finished needed the following code:

public void FinishBuildStep(string buildUri, string stepName, bool buildStepSucceeded)

        {

            IBuildServer buildServer = (IBuildServer)_server.GetService(typeof(IBuildServer));

            IBuildDetail details = buildServer.GetBuild(new Uri(buildUri), new string[1] { "*" }, QueryOptions.All);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; List<IBuildStep> buildSteps = InformationNodeConverters.GetBuildSteps(details);

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach (IBuildStep buildstep in buildSteps)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (buildstep.Name == stepName.Trim() && buildstep.Status == Microsoft.TeamFoundation.Build.Client.BuildStepStatus.InProgress)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (buildStepSucceeded)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buildstep.Status = Microsoft.TeamFoundation.Build.Client.BuildStepStatus.Succeeded;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buildstep.Status = Microsoft.TeamFoundation.Build.Client.BuildStepStatus.Failed;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buildstep.FinishTime = DateTime.Now;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buildstep.Save();

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } &nbsp;

&nbsp;

Now that we have the build up and running again against the new object model (partially until RC that is) we are now able to upgrade our server to beta 2 when it arrives. Hopefully we will get the pre Beta 2 bits soon so we can start our testing with the Beta 2 bits. If everything goes well, we will be upgrading our production server to Beta 2 as soon as it is available. I think that this shows that we are very confident in the stability of the new version of the TFS server.

Follow my new blog on http://fluentbytes.com