TFS: Как я могу автоматически закрыть соответствующие рабочие элементы при успешной сборке? - PullRequest
1 голос
/ 11 мая 2009

Мы используем непрерывную интеграцию как часть нашей автоматизации сборки. При каждой регистрации сервер сборки tfs создает проект и в случае успеха развертывает его на наших веб-серверах.

При сбое сборки автоматически создается новая ошибка с подробностями сбоя сборки.

Из-за CI и активности на сервере это может привести к 10 или 20 ошибочным рабочим элементам, прежде чем сборка возобновится.

Итак, у меня есть два варианта. Я бы хотел, чтобы процесс сборки посмотрел, существует ли уже открытый рабочий элемент на случай сбоя сборки, и просто добавлю к этому подробности; ИЛИ я бы хотел, чтобы сервер сборки автоматически закрывал все элементы сбоя сборки, когда он снова начнет работать.

Есть идеи?

1 Ответ

2 голосов
/ 11 мая 2009

Вы можете создать задачу 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"/>
...