Update Build Quality and Keep Indefinitely in TFS from the commandline

2013-06-26

As you probably know, TFS keeps all kinds of data behind when it finishes an automated build. Test Results, the stuff it copied to the drop folder, symbols etc. And by default it will keep the last 10 builds of data around and then starts cleaning up.

When you deploy a build to production, you don't want TFS to delete the symbol files and you might want to retain the test results etc as well. On the Build Detail screen, you can click a link to tell TFS you want to 'Retain the build indefinitely'.

This option cannot be set from the commandline, which is a pity when you want to ensure this is set correctly once your automated deployment process picks up the build and does stuff with it.

So I've written a little utility which handles this for you.

The actual piece of code is very simple and straightforward:

  1. Connect to TFS
  2. Request the build
  3. Change the options
  4. Save the result


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using CommandLine;
using CommandLine.Text;

using Microsoft.TeamFoundation.Build.Client;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Client.CommandLine;

namespace TfsBuildUtil
{
    class Program
    {
        private static CommandlineParams commandlineArgs;

        static void Main(string[] args)
        {
            commandlineArgs = new CommandlineParams();
            bool parseresult = CommandLine.Parser.Default.ParseArgumentsStrict(
                args,
                commandlineArgs,
                () => Console.Write(commandlineArgs.GetUsage()));
            
            if (parseresult)
            {
                var server = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri(commandlineArgs.ProjectCollection));
                server.EnsureAuthenticated();

                var buildserver = server.GetService<IBuildServer>();
                var build = buildserver.GetBuild(new Uri(commandlineArgs.BuildUri));

                bool save = false;

                if (commandlineArgs.Quality != null)
                {
                    if (!string.Equals(build.Quality, commandlineArgs.Quality, StringComparison.CurrentCulture))
                    {
                        build.Quality = commandlineArgs.Quality;
                        save = true;
                    }
                }

                if (commandlineArgs.KeepForever.HasValue)
                {
                    if (build.KeepForever != commandlineArgs.KeepForever.Value)
                    {
                        build.KeepForever = commandlineArgs.KeepForever.Value;
                        save = true;
                    }
                }

                if (save)
                {
                    buildserver.SaveBuilds(new[] { build });
                }
            }
        }
    }

    public class CommandlineParams
    {
        [Option("collection", HelpText = "The project collection Uri", Required = true)]
        public string ProjectCollection { get; set; }

        [Option("build", HelpText = "The build uri", Required = true)]
        public string BuildUri { get; set; }

        [Option("quality", HelpText = "Quality to set", Required = false)]
        public string Quality { get; set; }

        [Option("keep", DefaultValue=false, HelpText = "Set keep forever", Required = false)]
        public bool? KeepForever { get; set; }

        [HelpOption]
        public string GetUsage()
        {
            var help = new HelpText
            {
                Heading = new HeadingInfo("Tfs Build Utility", "1.0"),
                Copyright = new CopyrightInfo("Jesse Houwing", 2012),
                AdditionalNewLineAfterOption = true,
                AddDashesToOption = true
            };

            if (LastParserState.Errors.Count > 0)
            {
                var errors = help.RenderParsingErrorsText(this, 2);
                help.AddPreOptionsLine(errors);
            }

            help.AddOptions(this);
            return help;
        }

        [ParserState]
        public IParserState LastParserState { get; set; }
    }
}

The commandline will look like this:

tfsbuildutil --collection http://localhost:8080/tfs/DefaultCollection --build vsts:///Build/Build/1234 --keep true --quality "Deployed to Production"
Download the solution here.
 

Most Reading