TFS:如何在成功构建时自动关闭匹配的工作项?

时间:2009-05-11 14:33:06

标签: tfs build-automation

我们正在使用持续集成作为构建自动化的一部分。对于每次签入,tfs构建服务器构建项目并成功部署到我们的Web服务器。

当构建失败时,它会自动创建一个新Bug,其中包含构建失败的详细信息。

由于CI和服务器上的活动,在构建开始成功之前,这可能会导致10或20个失败工作项。

所以,我有两个选择。我想让构建过程看看是否已存在构建失败的开放工作项,只是添加详细信息;或者,我希望构建服务器在它再次开始工作时自动关闭所有构建失败项。

有什么想法吗?

1 个答案:

答案 0 :(得分:2)

您可以创建MSBuild任务来执行其中任一选项。以下是我用来启动您的类似代码,但由于我不知道您的工作项或流程的详细信息,因此您必须对其进行更改。

此代码获取与构建关联的所有工作项并更新其状态。

如果选择第一个选项,则只需更改UpdateWorkItemStatus方法并更新任何现有的WI。对于第二种方法,您需要做更多的工作,因为您需要查找先前的构建而不是将其作为输入。

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"/>