Team Build API: GetListOfBuilds

In part two of my 35 part series, better know a Proxy, I'll be going over the GetListOfBuilds method (of the BuildStore class in the Microsoft.TeamFoundation.Build.Proxy namespace). 

 public BuildData[] GetListOfBuilds(
   string teamProject,
 string buildType
)

This method can be used to obtain information about all of the builds for a particular build type.  It takes two parameters - teamProject, which specifies the team project the build type belongs to; and buildType, which specifies the build type for which builds are retrieved.  It returns an array of BuildData objects, which contain various details about the individual builds. 

Here is an example custom task (based on the TeamBuildTask base class from an earlier post) that uses the GetListOfBuilds method to generate sequential build numbers.

 using System;
using Microsoft.Build.Framework;
using Microsoft.TeamFoundation.Build.Proxy;

namespace MyNamespace
{
    public class SequentialBuildNumberGenerator : TeamBuildTask
    {
        /// <summary>
        /// The build number generated by the task.
        /// </summary>
        [Output]
        public string BuildNumber
        {
            get
            {
                return m_buildNumber;
            }
            set
            {
                m_buildNumber = value;
            }
        }

        /// <summary>
        /// Returns the name of the build step to be added for this task.
        /// </summary>
        /// <returns>Name of the build step to be added.</returns>
        protected override string GetBuildStepName()
        {
            return "SequentialBuildNumberGenerator";
        }

        /// <summary>
        /// Returns the message of the build step to be added for this task - this is the
        /// string displayed in the Team Build GUI.
        /// </summary>
        /// <returns>Message of the build step to be added.</returns>
        protected override string GetBuildStepMessage()
        {
            return "Generating a sequential build number.";
        }

        /// <summary>
        /// Put real task logic in this method.
        /// </summary>
        /// <returns>True if task is successful, otherwise false.</returns>
        protected override bool ExecuteInternal()
        {
            BuildData thisBuild = BuildStore.GetBuildDetails(BuildUri);

            BuildData[] allBuilds = BuildStore.GetListOfBuilds(thisBuild.TeamProject, thisBuild.BuildType);

            if (allBuilds.Length == 1)
            {
                m_buildNumber = "1";
            }
            else
            {
                int maxBuildNumber = 0, curBuildNumber;

                foreach (BuildData build in allBuilds)
                {
                    // All non integral build numbers, including the original number for the current build, will be ignored.
                    if (Int32.TryParse(build.BuildNumber, out curBuildNumber))
                    {
                        maxBuildNumber = Math.Max(maxBuildNumber, curBuildNumber);
                    }
                }

                m_buildNumber = (maxBuildNumber + 1).ToString("D");
            }

            return true;
        }

        private string m_buildNumber;
    }
}

To use this task, you'll need to do something like the following in TfsBuild.proj:

 <UsingTask TaskName="SequentialBuildNumberGenerator" AssemblyFile="CustomTasks.dll" />

<Target Name="BuildNumberOverrideTarget">
  <SequentialBuildNumberGenerator TeamFoundationServerUrl="$(TeamFoundationServerUrl)"
     BuildUri="$(BuildUri)">
      <Output TaskParameter="BuildNumber" PropertyName="BuildNumber" />
 </SequentialBuildNumberGenerator>      
</Target>