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

发布于 2024-07-20 07:16:28 字数 293 浏览 0 评论 0原文

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

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

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

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

有任何想法吗?

We are using continuous integration as part of our build automation. For every check in, the tfs build server builds the project and deploys to our web servers on success.

When the build fails, it automatically creates a new Bug with the details of the build failure.

Due to CI and the activity on the server, this might result in 10 or 20 failure work items before the build starts succeeding again.

So, I have two options. I'd like to either have the build process see if an open work item already exists for a build failure and just add details to that; OR, I'd like the build server to close all of the build failure items automatically when it starts working again.

Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

悸初 2024-07-27 07:16:28

您可以创建 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"/>

You can create a MSBuild Task to do either of these options. Here is a similar piece of code I use to get you started but since I don't know the details of your work item or process you will have to change it.

This code takes all of the work items associated with a build and updates their status.

If you select your first option you can just change the UpdateWorkItemStatus method and update any existing WIs. For the Second method you will need to do a bit more work as you need to look up the prior build rather than take it as a 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"/>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文