«Создать копию рабочего элемента» через REST API для Azure DevOps? - PullRequest
1 голос
/ 25 марта 2020

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

Создание с помощью этого API здесь: https://docs.microsoft.com/en-us/rest/api/azure/devops/wit/work%20items/create?view=azure-devops-rest-5.1

Любая помощь будет принята с благодарностью.

1 Ответ

0 голосов
/ 25 марта 2020

Мы не можем просто скопировать рабочий элемент, потому что он содержит системные поля, которые мы должны пропустить. Кроме того, ваш процесс может иметь некоторые правила, которые могут блокировать некоторые поля на этапе создания. Вот небольшой пример клонирования рабочего элемента через 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

...