【问题标题】:'Create copy of work item' via REST API for Azure DevOps?通过 REST API 为 Azure DevOps“创建工作项的副本”?
【发布时间】:2020-07-06 04:56:02
【问题描述】:

我想要“创建工作项的副本”,它可以通过 UI 获得,最好是通过 API。 我知道如何创建一个新的工作项,但是 UI 中连接所有当前父链接/相关链接以及所有其他细节的功能非常有用。

通过此 API 创建:https://docs.microsoft.com/en-us/rest/api/azure/devops/wit/work%20items/create?view=azure-devops-rest-5.1

任何帮助将不胜感激。

【问题讨论】:

    标签: tfs azure-devops azure-devops-rest-api


    【解决方案1】:

    我们不能仅仅复制一个工作项,因为它包含我们应该跳过的系统字段。此外,您的流程可能有一些规则可能会阻止创建步骤中的某些字段。这是通过 REST API 使用 https://www.nuget.org/packages/Microsoft.TeamFoundationServer.Client 克隆工作项的小示例:

    class Program
    {
        static string[] systemFields = { "System.IterationId", "System.ExternalLinkCount", "System.HyperLinkCount", "System.AttachedFileCount", "System.NodeName",
        "System.RevisedDate", "System.ChangedDate", "System.Id", "System.AreaId", "System.AuthorizedAs", "System.State", "System.AuthorizedDate", "System.Watermark",
            "System.Rev", "System.ChangedBy", "System.Reason", "System.WorkItemType", "System.CreatedDate", "System.CreatedBy", "System.History", "System.RelatedLinkCount",
        "System.BoardColumn", "System.BoardColumnDone", "System.BoardLane", "System.CommentCount", "System.TeamProject"}; //system fields to skip
    
        static string[] customFields = { "Microsoft.VSTS.Common.ActivatedDate", "Microsoft.VSTS.Common.ActivatedBy", "Microsoft.VSTS.Common.ResolvedDate", 
            "Microsoft.VSTS.Common.ResolvedBy", "Microsoft.VSTS.Common.ResolvedReason", "Microsoft.VSTS.Common.ClosedDate", "Microsoft.VSTS.Common.ClosedBy",
        "Microsoft.VSTS.Common.StateChangeDate"}; //unneeded fields to skip
    
        const string ChildRefStr = "System.LinkTypes.Hierarchy-Forward"; //should be only one parent
    
    
        static void Main(string[] args)
        {
            string pat = "<pat>"; //https://docs.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate
            string orgUrl = "https://dev.azure.com/<org>";
            string newProjectName = "";
            int wiIdToClone = 0; 
    
    
            VssConnection connection = new VssConnection(new Uri(orgUrl), new VssBasicCredential(string.Empty, pat));
            var witClient = connection.GetClient<WorkItemTrackingHttpClient>();
    
            CloneWorkItem(witClient, wiIdToClone, newProjectName, true);            
        }
    
        private static void CloneWorkItem(WorkItemTrackingHttpClient witClient, int wiIdToClone, string NewTeamProject = "", bool CopyLink = false)
        {
            WorkItem wiToClone = (CopyLink) ? witClient.GetWorkItemAsync(wiIdToClone, expand: WorkItemExpand.Relations).Result
                : witClient.GetWorkItemAsync(wiIdToClone).Result;
    
            string teamProjectName = (NewTeamProject != "") ? NewTeamProject : wiToClone.Fields["System.TeamProject"].ToString();
            string wiType = wiToClone.Fields["System.WorkItemType"].ToString();
    
            JsonPatchDocument patchDocument = new JsonPatchDocument();
    
            foreach (var key in wiToClone.Fields.Keys) //copy fields
                if (!systemFields.Contains(key) && !customFields.Contains(key))
                    if (NewTeamProject == "" ||
                        (NewTeamProject != "" && key != "System.AreaPath" && key != "System.IterationPath")) //do not copy area and iteration into another project
                        patchDocument.Add(new JsonPatchOperation()
                        {
                            Operation = Operation.Add,
                            Path = "/fields/" + key,
                            Value = wiToClone.Fields[key]
                        });
    
            if (CopyLink) //copy links
                foreach (var link in wiToClone.Relations)
                {
                    if (link.Rel != ChildRefStr)
                    {
                        patchDocument.Add(new JsonPatchOperation()
                        {
                            Operation = Operation.Add,
                            Path = "/relations/-",
                            Value = new
                            {
                                rel = link.Rel,
                                url = link.Url
                            }
                        });
                    }
                }
    
            WorkItem clonedWi = witClient.CreateWorkItemAsync(patchDocument, teamProjectName, wiType).Result;
    
            Console.WriteLine("New work item: " + clonedWi.Id);
        }
    }
    

    完整项目链接:https://github.com/ashamrai/AzureDevOpsExtensions/tree/master/CustomNetTasks/CloneWorkItem

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-22
      • 2020-07-26
      • 2019-08-24
      • 1970-01-01
      • 2020-06-11
      • 2022-11-15
      • 1970-01-01
      • 2021-03-19
      相关资源
      最近更新 更多