2015-11-06 3 views
1

Я хотел бы знать, могу ли я создать новую связанную задачу при создании рабочего элемента.Как создать задачу автоматически, создав новый рабочий элемент в TFS?

Может ли кто-нибудь дать подсказку, как это сделать?

+1

Вы используете ВСО или TFS? Если TFS, вы можете создать так называемый серверный плагин. Или вы используете служебные крючки для уведомления, когда рабочий элемент создан, а затем создайте новую задачу. –

+0

Привет! Спасибо за Ваш ответ! Я использую TFS ... Для создания плагина сервера у вас есть какая-либо ссылка, которую я могу использовать в качестве руководства? В моей компании они просят меня сделать этот процесс автоматизированным, поэтому серверный плагин - лучший вариант для меня. – Luciano

ответ

4

Я прошел через старый код, который я ранее использовал для этого сценария. Следующий код создает связанную задачу всякий раз, когда новая ошибка настроена на одобрение.

Код фильтрует конкретный проект команды и использует определенную учетную запись для подключения. Вам нужно ввести их, прежде чем плагин будет работать. Затем вы можете изменить этот код для создания требуемых задач.

Для общего введения в серверных плагинов и как включить следующий код в функционирующем плагин см Extending Team Foundation

using Microsoft.TeamFoundation.Framework.Server; 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using Microsoft.TeamFoundation.Common; 
using Microsoft.TeamFoundation.WorkItemTracking.Server; 
using Microsoft.TeamFoundation.WorkItemTracking.Client; 
using Microsoft.TeamFoundation.Client; 
using System.Net; 
using System.Collections; 

namespace TfsExtension.CreateTaskForBug 
{ 
    public class CreateTaskForBugEventHandler : ISubscriber 
    { 
     const string projectName = "<Enter your project name here>"; 

     public string Name 
     { 
      get 
      { 
       return "CreateTaskForBugEventHandler"; 
      } 
     } 

     public SubscriberPriority Priority 
     { 
      get 
      { 
       return SubscriberPriority.Normal; 
      } 
     } 

     public EventNotificationStatus ProcessEvent(
      TeamFoundationRequestContext requestContext, 
      NotificationType notificationType, 
      object notificationEventArgs, 
      out int statusCode, 
      out string statusMessage, 
      out ExceptionPropertyCollection properties) 
     { 
      statusCode = 0; 
      properties = null; 
      statusMessage = String.Empty; 

      try 
      { 
       ProcessNotification(notificationType, notificationEventArgs, requestContext); 
      } 
      catch (Exception exception) 
      { 
       TeamFoundationApplicationCore.LogException("Error processing event", exception); 
      } 
      return EventNotificationStatus.ActionPermitted; 

     } 

     private static void ProcessNotification(NotificationType notificationType, object notificationEventArgs, TeamFoundationRequestContext requestContext) 
     { 
      if (notificationType == NotificationType.Notification && notificationEventArgs is WorkItemChangedEvent) 
      { 
       var ev = notificationEventArgs as WorkItemChangedEvent; 

       if (ev.PortfolioProject == projectName) 
       { 
        string workItemType = (from field in ev.CoreFields.StringFields 
              where field.Name == "Work Item Type" 
              select field.NewValue).Single(); 

        if (workItemType == "Bug") 
        { 
         ProcessBug(ev, requestContext); 

        } 
       } 
      } 
     } 

     private static void ProcessBug(WorkItemChangedEvent ev, TeamFoundationRequestContext requestContext) 
     { 
      var stateChange = (from field in ev.ChangedFields.StringFields 
           where field.Name == "State" && field.NewValue == "Approved" 
           select field).SingleOrDefault(); 

      if (stateChange != null) 
      { 
       AddChildTaskToBug(ev, requestContext); 
      } 
     } 

     private static void AddChildTaskToBug(WorkItemChangedEvent ev, TeamFoundationRequestContext requestContext) 
     { 
      WorkItemStore wiStore = GetWorkItemStore(requestContext); 
      WorkItem witem = wiStore.GetWorkItem(ev.CoreFields.IntegerFields[0].NewValue); 

      Project teamProject = witem.Project; 
      int bugID = witem.Id; 

      string bugTitle = witem.Fields["System.Title"].Value.ToString(); 
      string bugAssignedTo = witem.Fields["System.AssignedTo"].Value.ToString(); 
      string bugAreaPath = witem.Fields["System.AreaPath"].Value.ToString(); 
      string bugIterationPath = witem.Fields["System.IterationPath"].Value.ToString(); 
      string bugChangedBy = witem.Fields["System.ChangedBy"].OriginalValue.ToString(); 
      string bugTeamProject = witem.Project.Name; 

      string childTaskTitle = "Resolve bug " + bugID + " - " + bugTitle; 

      if (CreateResolutionTask(wiStore, bugID, childTaskTitle)) 
      { 
       witem = CreateWorkItem(wiStore, teamProject, bugID, bugTitle, bugAssignedTo, bugAreaPath, bugIterationPath); 

       if (IsValid(witem)) 
       { 
        witem.Save(); 

        LinkParentAndChild(wiStore, witem, bugID); 
       } 
      } 
     } 

     private static bool IsValid(WorkItem witem) 
     { 
      ArrayList validationErrors = witem.Validate(); 
      return validationErrors.Count == 0; 
     } 

     private static void LinkParentAndChild(WorkItemStore wiStore, WorkItem witem, int bugID) 
     { 
      var linkType = wiStore.WorkItemLinkTypes[CoreLinkTypeReferenceNames.Hierarchy]; 

      var parentWorkItem = wiStore.GetWorkItem(bugID); 
      int taskID = witem.Id; 
      var childWorkItem = wiStore.GetWorkItem(taskID); 

      parentWorkItem.Links.Add(new WorkItemLink(linkType.ForwardEnd, childWorkItem.Id)); 
      parentWorkItem.Save(); 
     } 

     private static WorkItem CreateWorkItem(WorkItemStore wiStore, Project teamProject, int bugID, string bugTitle, string bugAssignedTo, string bugAreaPath, string bugIterationPath) 
     { 
      WorkItemTypeCollection workItemTypes = wiStore.Projects[teamProject.Name].WorkItemTypes; 
      WorkItemType wiType = workItemTypes["Task"]; 

      WorkItem witem = new WorkItem(wiType); 
      witem.Fields["System.Title"].Value = "Resolve bug " + bugID + " - " + bugTitle; 
      witem.Fields["System.AssignedTo"].Value = bugAssignedTo; 
      witem.Fields["System.AreaPath"].Value = bugAreaPath; 
      witem.Fields["System.IterationPath"].Value = bugIterationPath; 
      witem.Fields["Microsoft.VSTS.Common.Activity"].Value = "Bug Resolution"; 
      return witem; 
     } 

     private static bool CreateResolutionTask(WorkItemStore wiStore, int bugID, string childTaskTitle) 
     { 
      WorkItem parentBug = wiStore.GetWorkItem(bugID); 
      WorkItemLinkCollection links = parentBug.WorkItemLinks; 
      foreach (WorkItemLink wil in links) 
      { 
       if (wil.LinkTypeEnd.Name == "Child") 
       { 
        WorkItem childTask = wiStore.GetWorkItem(wil.TargetId); 

        if ((childTask.Title == childTaskTitle) && (childTask.State != "Closed")) 
        { 
         return false; 
        } 

       } 
      } 

      return true; 
     } 

     private static Uri GetTFSUri(TeamFoundationRequestContext requestContext) 
     { 
      var locationService = requestContext.GetService<TeamFoundationLocationService>(); 
      return new Uri(locationService.GetServerAccessMapping(requestContext).AccessPoint + "/" + requestContext.ServiceHost.Name); 
     } 

     private static WorkItemStore GetWorkItemStore(TeamFoundationRequestContext requestContext) 
     { 
      NetworkCredential netCred = new NetworkCredential(
        "<username>", 
        "<password>"); 

      WindowsCredential windowsCred = new WindowsCredential(netCred); 
      var credentials = new TfsClientCredentials(windowsCred); 
      credentials.AllowInteractive = true; 

      var tpc = new TfsTeamProjectCollection(
       GetTFSUri(requestContext), 
       credentials); 

      tpc.Authenticate(); 

      return tpc.GetService<WorkItemStore>(); 
     } 

     public Type[] SubscribedTypes() 
     { 
      return new Type[1] { typeof(WorkItemChangedEvent) }; 
     } 
    } 
} 
Смежные вопросы