TFS: How can I automatically close matching work items on a successful build?

We use continuous integration as part of our build automation. For each check, the tfs build server builds the project and runs successfully on our web servers.

When an assembly fails, it automatically generates a new error with the details of the assembly failure.

Due to CI and activity on the server, this can cause 10 or 20 running items to fail before the build starts running again.

So, I have two options. I would like the build process to consider if there is an open work item for the build failure and just add details to it; OR, I would like the build server to automatically close all items of the build failure when it starts working again.

Any ideas?

+1


a source to share


1 answer


You can create an MSBuild task to perform any of these options. Here's a similar piece of code that I use to get you started, but since I don't know the details of your work item or process, you'll have to modify it.

This code takes all work items associated with the assembly and updates their status.



If you choose your first option, you can simply change the UpdateWorkItemStatus method and update any existing WIs. For the second method, you will need to do a little bit of work as you need to look for the previous assembly and not accept it as input.

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Build.Utilities;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using Microsoft.Build.Framework;
using Microsoft.TeamFoundation.Build;
using Microsoft.TeamFoundation.Build.Client;

namespace Nowcom.TeamBuild.Tasks
{
    public class UpdateWorkItemState: Task
    {
        private IBuildDetail _Build;

        private void test()
        {
            TeamFoundationServerUrl = "Teamserver";
            BuildUri = "vstfs:///Build/Build/1741";
            Execute();
        }

        public override bool Execute()
        {
            bool result = true;

            try
            {
                TeamFoundationServer tfs = TeamFoundationServerFactory.GetServer(TeamFoundationServerUrl, new UICredentialsProvider());
                tfs.EnsureAuthenticated();

                WorkItemStore store = (WorkItemStore)tfs.GetService(typeof(WorkItemStore));
                IBuildServer buildServer = (IBuildServer)tfs.GetService(typeof(IBuildServer));
                _Build = buildServer.GetAllBuildDetails(new Uri(BuildUri));
                //add build step
                IBuildStep buildStep = InformationNodeConverters.AddBuildStep(_Build, "UpdateWorkItemStatus", "Updating Work Item Status");


                try
                {
                    Log.LogMessageFromText(string.Format("Build Number: {0}", _Build.BuildNumber), MessageImportance.Normal);

                    List<IWorkItemSummary> assocWorkItems = InformationNodeConverters.GetAssociatedWorkItems(_Build);

                        // update work item status 
                        UpdateWorkItemStatus(store, assocWorkItems, "Open", "Resolved");

                    SaveWorkItems(store, assocWorkItems);
                }
                catch (Exception)
                {
                    UpdateBuildStep(buildStep, false);
                    throw;
                }

                UpdateBuildStep(buildStep, result);
             }
            catch (Exception e)
            {
                result = false;

                BuildErrorEventArgs eventArgs;
                eventArgs = new BuildErrorEventArgs("", "", BuildEngine.ProjectFileOfTaskNode, BuildEngine.LineNumberOfTaskNode, BuildEngine.ColumnNumberOfTaskNode, 0, 0, string.Format("UpdateWorkItemState failed: {0}", e.Message), "", "");

                BuildEngine.LogErrorEvent(eventArgs);

                throw;
            }

            return result;
        }

        private static void SaveWorkItems(WorkItemStore store, List<IWorkItemSummary> assocWorkItems)
        {
            foreach (IWorkItemSummary w in assocWorkItems)
            {
                WorkItem wi = store.GetWorkItem(w.WorkItemId);

                if (wi.IsDirty)
                {
                    wi.Save();
                }
            }
        }

        // check in this routine if the workitem is a bug created by your CI process. Check by title or assigned to or description depending on your process.
        private void UpdateWorkItemStatus(WorkItemStore store, List<IWorkItemSummary> assocWorkItems, string oldState, string newState)
        {
            foreach (IWorkItemSummary w in assocWorkItems)
            {
                Log.LogMessageFromText(string.Format("Updating Workitem Id {0}", w.WorkItemId), MessageImportance.Normal);
                WorkItem wi = store.GetWorkItem(w.WorkItemId);
                if (wi.Fields.Contains("Microsoft.VSTS.Build.IntegrationBuild") && wi.State != "Resolved")
                {
                    wi.Fields["Microsoft.VSTS.Build.IntegrationBuild"].Value =_Build.BuildNumber;
                }
                if (wi.State == oldState)
                {
                    wi.State = newState;
                    foreach (Field field in wi.Fields)
                    {
                        if (!field.IsValid)
                        {
                            break;
                        }
                    }
                }

                if (wi.IsDirty)
                {
                    wi.Save();
                }
            }
        }

        private void UpdateBuildStep(IBuildStep step, bool result)
        {
            step.Status = result ? BuildStepStatus.Succeeded : BuildStepStatus.Failed;
            step.FinishTime = DateTime.Now;
            step.Save();
        }

        [Required]
        public string BuildUri { get; set; }

        [Required]
        public string TeamFoundationServerUrl {get; set;}
    }
}



 < UpdateWorkItemState
TeamFoundationServerUrl="$(TeamFoundationServerUrl)"
BuildUri="$(BuildUri)"
ContinueOnError="false"/>

      

+2


a source







All Articles