Ejemplo n.º 1
0
        public string AddAttachmentToBug()
        {
            var _id       = _configuration.WorkItemId;
            var _filePath = _configuration.FilePath;

            using (WorkItemTrackingHttpClient workItemTrackingHttpClient = new WorkItemTrackingHttpClient(_uri, _credentials))
            {
                // upload attachment to attachment store and
                // get a reference to that file
                AttachmentReference attachmentReference = workItemTrackingHttpClient.CreateAttachmentAsync(_filePath).Result;

                JsonPatchDocument patchDocument = new JsonPatchDocument();

                patchDocument.Add(new JsonPatchOperation()
                {
                    Operation = Operation.Add,
                    Path      = "/relations/-",
                    Value     = new
                    {
                        rel        = "AttachedFile",
                        url        = attachmentReference.Url,
                        attributes = new { comment = "adding link to bug" }
                    }
                });

                WorkItem result = workItemTrackingHttpClient.UpdateWorkItemAsync(patchDocument, _id).Result;
            }

            return("success");
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Uploads the screenshot at the given path to the work item with the given issue id
        /// </summary>
        /// <param name="path">path of screenshot to upload</param>
        /// <returns>Task with URL of the screenshot attachment reference, null if not connected</returns>
        internal async Task <string> AttachScreenshotToIssue(string path, int issueId)
        {
            if (!ConnectedToAzureDevOps)
            {
                return(null);
            }
            WorkItemTrackingHttpClient wit        = _baseServerConnection.GetClient <WorkItemTrackingHttpClient>();
            AttachmentReference        attachment = await wit.CreateAttachmentAsync(new FileStream(path, FileMode.Open), Invariant($"{issueId}-pic.png")).ConfigureAwait(false);

            JsonPatchDocument patchDoc = new JsonPatchDocument();

            patchDoc.Add(new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/relations/-",
                Value     = new
                {
                    rel        = "AttachedFile",
                    url        = attachment.Url,
                    attributes = new { comment = "Screenshot of element" }
                }
            }
                         );
            // Return attachment URL once this work item is updated
#pragma warning disable CA2007 // Do not directly await a Task
#pragma warning disable CA2008 // Do not create tasks without passing a TaskScheduler
            return(await wit.UpdateWorkItemAsync(patchDoc, issueId).ContinueWith(t => attachment.Url));

#pragma warning restore CA2008 // Do not create tasks without passing a TaskScheduler
#pragma warning restore CA2007 // Do not directly await a Task
        }
Ejemplo n.º 3
0
        private AttachmentReference CreateAttachmentReference(Attachment attachment)
        {
            var fileName = Path.Combine(Path.GetTempPath(), attachment.Name);

            try
            {
                using (var client = new WebClient())
                {
                    client.UseDefaultCredentials = true;
                    client.DownloadFile(attachment.Uri, fileName);
                }

                var attachmentRef = workClient.CreateAttachmentAsync(fileName).Result;

                File.Delete(fileName);

                return(attachmentRef);
            }
            catch (Exception e)
            {
                Logger.Error($"{GetType()} Failed downloading attachment from {attachment.Uri} to {fileName}{Environment.NewLine}\t{e.Message}");
            }

            return(null);
        }
Ejemplo n.º 4
0
        private static List <AttachmentReference> CreateAttachments(WorkItemTrackingHttpClient httpClient, List <string> filePathsToBeAttached)
        {
            var attachments = new List <AttachmentReference>();

            if (filePathsToBeAttached == null || !filePathsToBeAttached.Any())
            {
                return(attachments);
            }

            foreach (var filePath in filePathsToBeAttached)
            {
                try
                {
                    using FileStream fileStream = File.OpenRead(filePath);
                    var attachment = httpClient.CreateAttachmentAsync(uploadStream: fileStream, project: _project, fileName: Path.GetFileName(filePath)).Result;
                    attachments.Add(attachment);
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.Message);
                }
            }

            return(attachments);
        }
Ejemplo n.º 5
0
        public AttachmentReference UploadAttachmentBinaryFile(string filePath)
        {
            VssConnection connection = new VssConnection(_uri, _credentials);
            WorkItemTrackingHttpClient workItemTrackingHttpClient = connection.GetClient <WorkItemTrackingHttpClient>();
            AttachmentReference        attachmentReference        = workItemTrackingHttpClient.CreateAttachmentAsync(@filePath).Result;

            return(attachmentReference);
        }
        private AttachmentReference UploadAttachment(AzureDevOpsWorkItemAttachment attachment)
        {
            AttachmentReference uploadedFile;

            var name = Path.GetFileName(attachment.AttachmentPath);

            using (var attStream = new FileStream(attachment.AttachmentPath, FileMode.Open, FileAccess.Read))
            {
                uploadedFile = WorkItemTrackingHttpClient.CreateAttachmentAsync(attStream, ProjectName, fileName: name)
                               .Result;
            }

            return(uploadedFile);
        }
Ejemplo n.º 7
0
        public WorkItem AddAttachment()
        {
            int    id       = Convert.ToInt32(Context.GetValue <WorkItem>("$newWorkItem3").Id);
            string filePath = ClientSampleHelpers.GetSampleTextFile();

            VssConnection connection = Context.Connection;
            WorkItemTrackingHttpClient workItemTrackingClient = connection.GetClient <WorkItemTrackingHttpClient>();

            // upload attachment to store and get a reference to that file
            AttachmentReference attachmentReference = workItemTrackingClient.CreateAttachmentAsync(filePath).Result;

            JsonPatchDocument patchDocument = new JsonPatchDocument();

            patchDocument.Add(
                new JsonPatchOperation()
            {
                Operation = Operation.Test,
                Path      = "/rev",
                Value     = "1"
            }
                );

            patchDocument.Add(
                new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/fields/System.History",
                Value     = "Adding the necessary spec"
            }
                );

            patchDocument.Add(
                new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/relations/-",
                Value     = new
                {
                    rel        = "AttachedFile",
                    url        = attachmentReference.Url,
                    attributes = new { comment = "VanDelay Industries - Spec" }
                }
            }
                );

            WorkItem result = workItemTrackingClient.UpdateWorkItemAsync(patchDocument, id).Result;

            return(result);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Upload attachment of file at the given path to the issue with given issue id
        ///     from "AzureDevOps-dotnet-samples" repo
        /// Also adds comment about snapshot to work item
        /// </summary>
        /// <param name="path">path to file that should be attached</param>
        /// <param name="issueId">issue id to attach file to</param>
        /// <returns>Task with completed issue ID or null if user is not connected to AzureDevOps</returns>
        internal async Task <int?> AttachTestResultToIssue(string path, int issueId)
        {
            if (!ConnectedToAzureDevOps)
            {
                return(null);
            }
            WorkItemTrackingHttpClient wit = _baseServerConnection.GetClient <WorkItemTrackingHttpClient>();
            AttachmentReference        attachment;

            using (FileStream outputStream = new FileStream(path, FileMode.Open))
            {
                attachment = await wit.CreateAttachmentAsync(outputStream, Invariant($"{issueId}.a11ytest")).ConfigureAwait(false);
            }
            JsonPatchDocument patchDoc = new JsonPatchDocument();

            patchDoc.Add(new JsonPatchOperation()
            {
                Operation = Operation.Test,
                Path      = "/rev",
                Value     = "1"
            }
                         );
            patchDoc.Add(new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/fields/System.History",
                Value     = "Attached an Accessibility Insights for Windows test file and screenshot."
            }
                         );
            patchDoc.Add(new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/relations/-",
                Value     = new
                {
                    rel        = "AttachedFile",
                    url        = attachment.Url,
                    attributes = new { comment = "Accessibility Insights for Windows test file" }
                }
            }
                         );

#pragma warning disable CA2007 // Do not directly await a Task
#pragma warning disable CA2008 // Do not create tasks without passing a TaskScheduler
            return(await wit.UpdateWorkItemAsync(patchDoc, issueId).ContinueWith(t => t.Result.Id));

#pragma warning restore CA2008 // Do not create tasks without passing a TaskScheduler
#pragma warning restore CA2007 // Do not directly await a Task
        }
Ejemplo n.º 9
0
 // This method will upload attachment and return url for file and Id
 private static AttachmentReference UploadAttachment(Uri uri, VssBasicCredential credentials)
 {
     try
     {
         VssConnection _tpc = new VssConnection(uri, credentials);
         WorkItemTrackingHttpClient workItemTrackingHttpClient = _tpc.GetClient <WorkItemTrackingHttpClient>();
         AttachmentReference        attachment = workItemTrackingHttpClient.CreateAttachmentAsync(PathOfAttachment).Result;
         // Save the attachment ID for the "download" sample call later
         return(attachment);
     }
     catch (Exception ex)
     {
         Log.Logger.Error("Error occurred while Attaching Attachment in bug" + ex);
         return(null);
     }
 }
Ejemplo n.º 10
0
        public WorkItem UpdateWorkItemAddAttachment(int id, string filePath)
        {
            VssConnection connection = new VssConnection(_uri, _credentials);
            WorkItemTrackingHttpClient workItemTrackingHttpClient = connection.GetClient <WorkItemTrackingHttpClient>();

            // upload attachment to attachment store and
            // get a reference to that file
            AttachmentReference attachmentReference = workItemTrackingHttpClient.CreateAttachmentAsync(filePath).Result;

            JsonPatchDocument patchDocument = new JsonPatchDocument();

            patchDocument.Add(
                new JsonPatchOperation()
            {
                Operation = Operation.Test,
                Path      = "/rev",
                Value     = "1"
            }
                );

            patchDocument.Add(
                new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/fields/System.History",
                Value     = "Adding the necessary spec"
            }
                );

            patchDocument.Add(
                new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/relations/-",
                Value     = new
                {
                    rel        = "AttachedFile",
                    url        = attachmentReference.Url,
                    attributes = new { comment = "VanDelay Industries - Spec" }
                }
            }
                );

            WorkItem result = workItemTrackingHttpClient.UpdateWorkItemAsync(patchDocument, id).Result;

            return(result);
        }
Ejemplo n.º 11
0
        public async static Task <AttachmentReference> CreateAttachmentAsync(WorkItemTrackingHttpClient client, MemoryStream uploadStream)
        {
            return(await RetryHelper.RetryAsync(async() =>
            {
                // clone the stream since if upload fails it disploses the underlying stream
                using (var clonedStream = new MemoryStream())
                {
                    await uploadStream.CopyToAsync(clonedStream);

                    // reset position for both streams
                    uploadStream.Position = 0;
                    clonedStream.Position = 0;

                    return await client.CreateAttachmentAsync(clonedStream);
                }
            }, 5));
        }
Ejemplo n.º 12
0
        public AttachmentReference UploadBinaryFile()
        {
            // Full path to the binary file to upload as an attachment
            string filePath = ClientSampleHelpers.GetSampleBinaryFile();

            VssConnection connection = Context.Connection;
            WorkItemTrackingHttpClient workItemTrackingClient = connection.GetClient <WorkItemTrackingHttpClient>();

            Console.WriteLine("Attempting upload of: {0}", filePath);

            AttachmentReference attachment = workItemTrackingClient.CreateAttachmentAsync(@filePath).Result;

            Console.WriteLine("Attachment created");
            Console.WriteLine(" ID    : {0}", attachment.Id);
            Console.WriteLine(" URL   : {0}", attachment.Url);

            return(attachment);
        }
        static void AddAttachment(int WiID, System.IO.Compression.ZipArchiveEntry FilePath)
        {
            AttachmentReference att;

            using (var attStream = FilePath.Open())
            {
                att = WitClient.CreateAttachmentAsync(attStream, FilePath.Name).Result; // upload the file
            }
            List <object> references = new List <object>
            {
                new
                {
                    rel        = RelConstants.AttachmentRefStr,
                    url        = att.Url,
                    attributes = new { comment = "" }
                }
            };

            AddWorkItemRelations(WiID, references);
        }
Ejemplo n.º 14
0
        public AttachmentReference UploadTextFile()
        {
            // Full path to the text file to upload as an attachment
            string filePath = ClientSampleHelpers.GetSampleTextFile();

            // Get a client
            VssConnection connection = Context.Connection;
            WorkItemTrackingHttpClient workItemTrackingClient = connection.GetClient <WorkItemTrackingHttpClient>();

            Console.WriteLine("Attempting upload of: {0}", filePath);

            // Upload the attachment
            AttachmentReference attachment = workItemTrackingClient.CreateAttachmentAsync(@filePath).Result;

            Console.WriteLine("Attachment created");
            Console.WriteLine(" ID    : {0}", attachment.Id);
            Console.WriteLine(" URL   : {0}", attachment.Url);

            // Save the attachment ID for the "download" sample call later
            Context.SetValue <Guid>("$attachmentId", attachment.Id);
            Context.SetValue <string>("$attachmentFileName", Path.GetFileName(filePath));

            return(attachment);
        }
Ejemplo n.º 15
0
        public async Task <IActionResult> CreateWorkItem([FromBody] WorkTask wt)
        {
            CurrentUser cUser = new CurrentUser(HttpContext, _configuration);

            var uriLookup = await lookupRepo.GetLookupConfigByName(0, "Y", "DevOps_Uri");

            Uri accountUri = new Uri(uriLookup.Lvalue);

            var tokenLookup = await lookupRepo.GetLookupConfigByName(0, "Y", "DevOps_AccessToken");

            String personalAccessToken = tokenLookup.Lvalue;

            var projectLookup = await lookupRepo.GetLookupConfigByName(0, "Y", "DevOps_Project");

            wt.Project = projectLookup.Lvalue;

            // Create a connection to the account
            VssConnection connection = new VssConnection(accountUri, new VssBasicCredential(string.Empty, personalAccessToken));

            // Get an instance of the work item tracking client
            WorkItemTrackingHttpClient witClient = connection.GetClient <WorkItemTrackingHttpClient>();

            JsonPatchDocument patchDocument = new JsonPatchDocument
            {
                //add fields and their values to your patch document
                new JsonPatchOperation()
                {
                    Operation = Operation.Add,
                    Path      = "/fields/System.Title",
                    Value     = wt.Title
                },
                new JsonPatchOperation()
                {
                    Operation = Operation.Add,
                    Path      = (wt.Type == "Bug" ? "/fields/Microsoft.VSTS.TCM.ReproSteps" : "/fields/System.Description"),
                    Value     = wt.Description
                }
            };

            var iterationLookup = await lookupRepo.GetLookupConfigByName(0, "Y", "DevOps_IterationPath");

            if (iterationLookup != null)
            {
                patchDocument.Add(new JsonPatchOperation()
                {
                    Operation = Operation.Add,
                    Path      = "/fields/System.IterationPath",
                    Value     = iterationLookup.Lvalue
                });
            }

            var parentRelationLookup = await lookupRepo.GetLookupConfigByName(0, "Y", "DevOps_ParentRelation");

            if (parentRelationLookup != null)
            {
                int      id       = Int32.Parse(parentRelationLookup.Lvalue);
                WorkItem workitem = witClient.GetWorkItemAsync(id).Result;

                patchDocument.Add(new JsonPatchOperation()
                {
                    Operation = Operation.Add,
                    Path      = "/relations/-",
                    Value     = new
                    {
                        rel = "System.LinkTypes.Hierarchy-Reverse",
                        url = workitem.Url
                              //url = "https://dev.azure.com/inser13/SKF-Emaintenance/_apis/wit/workItems/2308"
                    }
                });
            }

            var areaPathLookup = await lookupRepo.GetLookupConfigByName(0, "Y", "DevOps_AreaPath");

            if (areaPathLookup != null)
            {
                patchDocument.Add(new JsonPatchOperation()
                {
                    Operation = Operation.Add,
                    Path      = "/fields/System.AreaPath",
                    Value     = areaPathLookup.Lvalue
                });
            }

            if (wt.Priority != string.Empty && wt.Priority != null)
            {
                patchDocument.Add(new JsonPatchOperation()
                {
                    Operation = Operation.Add,
                    Path      = "/fields/Microsoft.VSTS.Common.Priority",
                    Value     = wt.Priority
                });
            }

            patchDocument.Add(new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/fields/System.Tags",
                Value     = wt.Tags + "," + cUser.Email
            });

            //if (wt.Comment != string.Empty && wt.Comment != null)
            //{
            //    patchDocument.Add(new JsonPatchOperation()
            //    {
            //        Operation = Operation.Add,
            //        Path = "/fields/System.History",
            //        Value = wt.Comment + "<p>By :" + cUser.Email + "</p>"
            //    });
            //}

            if (wt.DeviceInfo != string.Empty && wt.DeviceInfo != null)
            {
                string Comment = null;
                if (wt.Comment != string.Empty && wt.Comment != null)
                {
                    Comment = wt.Comment + "<p>By :" + cUser.Email + "</p>";
                }
                Comment = Comment + "</p>" + wt.DeviceInfo;
                patchDocument.Add(new JsonPatchOperation()
                {
                    Operation = Operation.Add,
                    Path      = "/fields/System.History",
                    Value     = Comment
                });
            }

            try
            {
                if (wt.ScreenShot != string.Empty && wt.ScreenShot != null)
                {
                    string convert = wt.ScreenShot.Replace("data:image/png;base64,", String.Empty);
                    var    stream  = new MemoryStream(Convert.FromBase64String(convert));
                    AttachmentReference attachment = witClient.CreateAttachmentAsync(stream, wt.Project, "ScreenShot.jpg", null, null, null).Result;

                    patchDocument.Add(new JsonPatchOperation()
                    {
                        Operation = Operation.Add,
                        Path      = "/relations/-",
                        Value     = new
                        {
                            rel        = "AttachedFile",
                            url        = attachment.Url,
                            attributes = new { comment = "Emaintenance Attachment by " + cUser.Email }
                        }
                    });
                }
                WorkItem result = witClient.CreateWorkItemAsync(patchDocument, wt.Project, wt.Type).Result;
                return(Ok(result));
            }
            catch (AggregateException ex)
            {
                throw ex;
            }
        }
Ejemplo n.º 16
0
        public override async Task <IEnumerable <WorkItemFilingMetadata> > FileWorkItems(IEnumerable <WorkItemFilingMetadata> workItemFilingMetadata)
        {
            foreach (WorkItemFilingMetadata metadata in workItemFilingMetadata)
            {
                AttachmentReference attachmentReference = null;
                string attachmentText = metadata.Attachment?.Text;
                if (!string.IsNullOrEmpty(attachmentText))
                {
                    using (var stream = new MemoryStream())
                        using (var writer = new StreamWriter(stream))
                        {
                            writer.Write(attachmentText);
                            writer.Flush();
                            stream.Position = 0;
                            try
                            {
                                attachmentReference = await _witClient.CreateAttachmentAsync(stream, fileName : metadata.Attachment.Name);
                            }
                            catch
                            {
                                // TBD error handling
                                throw;
                            }
                        }
                }

                var patchDocument = new JsonPatchDocument
                {
                    new JsonPatchOperation
                    {
                        Operation = Operation.Add,
                        Path      = $"/fields/{WorkItemFields.Title}",
                        Value     = metadata.Title
                    },
                    new JsonPatchOperation
                    {
                        Operation = Operation.Add,
                        Path      = $"/fields/{WorkItemFields.ReproSteps}",
                        Value     = metadata.Description
                    },
                    new JsonPatchOperation
                    {
                        Operation = Operation.Add,
                        Path      = $"/fields/{WorkItemFields.AreaPath}",
                        Value     = metadata.AreaPath
                    },
                    new JsonPatchOperation
                    {
                        Operation = Operation.Add,
                        Path      = $"/fields/{WorkItemFields.Tags}",
                        Value     = string.Join(",", metadata.GetAllTags())
                    }
                };

                foreach (var customField in metadata.CustomFields)
                {
                    patchDocument.Add(new JsonPatchOperation
                    {
                        Operation = Operation.Add,
                        Path      = $"/fields/{customField.Key}",
                        Value     = customField.Value
                    });
                }

                if (attachmentReference != null)
                {
                    patchDocument.Add(
                        new JsonPatchOperation
                    {
                        Operation = Operation.Add,
                        Path      = $"/relations/-",
                        Value     = new
                        {
                            rel = "AttachedFile",
                            attachmentReference.Url
                        }
                    });
                }

                WorkItem workItem = null;

                try
                {
                    Console.Write($"Creating work item: {metadata.Title}");
                    workItem = await _witClient.CreateWorkItemAsync(patchDocument, project : _projectName, "Bug");

                    Console.WriteLine($": {workItem.Id}: DONE");
                }
                catch (Exception e)
                {
                    Console.Error.WriteLine(e);

                    if (patchDocument != null)
                    {
                        string patchJson = JsonConvert.SerializeObject(patchDocument, Formatting.Indented);
                        Console.Error.WriteLine(patchJson);
                    }

                    continue;
                }

                const string HTML     = "html";
                SarifLog     sarifLog = (SarifLog)metadata.Object;
                foreach (Result result in sarifLog.Runs[0].Results)
                {
                    if (workItem.Links?.Links?.ContainsKey(HTML) == true)
                    {
                        result.WorkItemUris = new List <Uri> {
                            new Uri(((ReferenceLink)workItem.Links.Links[HTML]).Href, UriKind.Absolute)
                        };
                    }
                    else
                    {
                        result.WorkItemUris = new List <Uri> {
                            new Uri(workItem.Url, UriKind.Absolute)
                        };
                    }
                }
            }

            return(workItemFilingMetadata);
        }
        private void Save(bool skipSaveSuccessDialog = false)
        {
            var isNewMode    = (tabControl1.SelectedTab == tabNewItem);
            var isUpdateMode = (tabControl1.SelectedTab == tabUpdateItem);

            btnSaveNClose.Enabled = false;
            btnSave.Enabled       = false;
            List <string> saveFilePaths = new List <string>();
            string        tempFolder    = GetTempFolder();

            try
            {
                Directory.CreateDirectory(tempFolder);
                var tfsConnection = Globals.ThisAddIn.Settings.TfsConfigurations[cbProject.SelectedIndex];
                WorkItemTrackingHttpClient witClient = GetVssClient(tfsConnection);

                WorkItem result   = null;
                var      bodyText = new StringBuilder(txtBody.Text);

                if (isNewMode)
                {
                    JsonPatchDocument patchDocument = new JsonPatchDocument();

                    //add fields and their values to your patch document
                    patchDocument.Add(
                        new JsonPatchOperation()
                    {
                        Operation = Operation.Add,
                        Path      = "/fields/System.Title",
                        Value     = txtTitle.Text
                    }
                        );

                    patchDocument.Add(
                        new JsonPatchOperation()
                    {
                        Operation = Operation.Add,
                        Path      = "/fields/Microsoft.VSTS.TCM.ReproSteps",
                        Value     = bodyText.ToString()
                    }
                        );

                    patchDocument.Add(
                        new JsonPatchOperation()
                    {
                        Operation = Operation.Add,
                        Path      = "/fields/System.Description",
                        Value     = bodyText.ToString()
                    }
                        );

                    patchDocument.Add(
                        new JsonPatchOperation()
                    {
                        Operation = Operation.Add,
                        Path      = "/fields/Microsoft.VSTS.TCM.SystemInfo",
                        Value     = txtSystemInformation.Text
                    }
                        );

                    patchDocument.Add(
                        new JsonPatchOperation()
                    {
                        Operation = Operation.Add,
                        Path      = "/fields/Microsoft.VSTS.Common.Priority",
                        Value     = cbPriority.Text
                    }
                        );

                    patchDocument.Add(
                        new JsonPatchOperation()
                    {
                        Operation = Operation.Add,
                        Path      = "/fields/Microsoft.VSTS.Common.Severity",
                        Value     = cbSeverity.Text
                    }
                        );

                    //TODO:
                    //patchDocument.Add(
                    //    new JsonPatchOperation()
                    //    {
                    //        Operation = Operation.Add,
                    //        Path = "/fields/System.AssignedTo",
                    //        Value = _exchangeUser.Name + " <" + _exchangeUser.PrimarySmtpAddress + ">"
                    //    }
                    //);

                    // add parent
                    if (parentItem != null)
                    {
                        patchDocument.Add(new Microsoft.VisualStudio.Services.WebApi.Patch.Json.JsonPatchOperation()
                        {
                            Operation = Operation.Add,
                            Path      = "/relations/-",
                            Value     = new
                            {
                                rel        = "System.LinkTypes.Hierarchy-Reverse",
                                url        = tfsConnection.TfsUrl + tfsConnection.TfsProject + "/_apis/wit/workItems/" + parentItem.Id,
                                attributes = new
                                {
                                    comment = "link parent WIT"
                                }
                            }
                        });

                        var fieldsToInherit = new string[] { "System.AreaPath", "System.IterationPath" };

                        foreach (var fieldToInherit in fieldsToInherit)
                        {
                            if (parentItem.Fields.ContainsKey(fieldToInherit))
                            {
                                patchDocument.Add(
                                    new JsonPatchOperation()
                                {
                                    Operation = Operation.Add,
                                    Path      = "/fields/" + fieldToInherit,
                                    Value     = parentItem.Fields[fieldToInherit]
                                }
                                    );;
                            }
                        }
                    }

                    /*
                     * patchDocument.Add(
                     *  new JsonPatchOperation()
                     *  {
                     *      Operation = Operation.Add,
                     *      Path = "/fields/Microsoft.VSTS.Common.ReviewedBy",
                     *      Value = _outlookCurrentMailItem.SenderName + " <" + _outlookCurrentMailItem.Sender.GetExchangeUser().PrimarySmtpAddress + ">"
                     *  }
                     * );
                     */

                    result = witClient.CreateWorkItemAsync(patchDocument, tfsConnection.TfsProject, cbWorkItemType.Text).Result;
                }
                else
                {
                    result = existingItem;
                }

                // test
                //https://github.com/microsoft/azure-devops-dotnet-samples/blob/master/ClientLibrary/Samples/WorkItemTracking/WorkItemsSample.cs

                //var commentsDocument = new JsonPatchDocument();


                //commentsDocument.Add(
                //    new JsonPatchOperation()
                //    {
                //        Operation = Operation.Add,
                //        Path = "/fields/System.History",
                //        Value = "test comment from client lib sample code",
                //    }
                //);
                //WorkItem commentsREsult = witClient.UpdateWorkItemAsync(commentsDocument, result.Id.Value).Result;

                //var q = 1;



                //// add files

                if (chkLstBoxAttachements.GetItemChecked(0))
                {
                    var subject = _outlookCurrentMailItem.Subject.GetSafeFileSystemName()
                                  + ".msg";
                    string allMessage = tempFolder + subject;
                    saveFilePaths.Add(allMessage);
                    _outlookCurrentMailItem.SaveAs(allMessage,
                                                   OlSaveAsType.olMSG);
                }

                // this is not a mistake, the first checkbox is reserved for the whole message,
                // and the outlook attachments weirdly is numbered from 1
                for (int i = 1; i < chkLstBoxAttachements.Items.Count; i++)
                {
                    if (chkLstBoxAttachements.GetItemChecked(i))
                    {
                        var filename = _outlookCurrentMailItem.Attachments[i].GetFileName();
                        filename = filename.GetSafeFileSystemName();
                        string fPath = tempFolder + filename;
                        saveFilePaths.Add(fPath);
                        _outlookCurrentMailItem.Attachments[i].SaveAsFile(fPath);
                    }
                }

                if ((saveFilePaths.Count > 0) || (isUpdateMode))
                {
                    List <string> uploadedAttachementUrl = new List <string>();
                    if (saveFilePaths.Count > 0)
                    {
                        JsonPatchDocument attachDocument = new JsonPatchDocument();
                        foreach (string fp in saveFilePaths)
                        {
                            AttachmentReference attachment = null;

                            Task taskAttach = new Task(() => { attachment = witClient.CreateAttachmentAsync(fp).Result; });
                            taskAttach.Start();
                            Task.WaitAll(new[] { taskAttach });

                            attachDocument.Add(
                                new JsonPatchOperation()
                            {
                                Operation = Operation.Add,
                                Path      = "/relations/-",
                                Value     = new
                                {
                                    rel = "AttachedFile",
                                    url = attachment.Url,

                                    attributes = new
                                    {
                                        name    = Path.GetFileName(fp),
                                        comment = txtAttachementComment.Text
                                    }
                                }
                            }
                                );;
                            uploadedAttachementUrl.Add(attachment.Url);
                        }

                        WorkItem attachmentResult = witClient.UpdateWorkItemAsync(attachDocument, result.Id.Value).Result;
                    }


                    //Prepare new body text

                    bodyText.Append("<br/>");
                    foreach (string ustr in uploadedAttachementUrl)
                    {
                        var extension = System.IO.Path.GetExtension(ustr).ToLower();
                        if (imageExtensions.Contains(extension))
                        {
                            bodyText.Append("<br/>");
                            bodyText.Append(String.Format("<img src =\"{0}\"/> ", ustr));
                        }
                    }

                    if (isNewMode)
                    {
                        JsonPatchDocument updatedItemBody = new JsonPatchDocument();
                        updatedItemBody.Add(
                            new JsonPatchOperation()
                        {
                            Operation = Operation.Add,
                            Path      = "/fields/Microsoft.VSTS.TCM.ReproSteps",
                            Value     = bodyText.ToString()
                        }
                            );

                        updatedItemBody.Add(
                            new JsonPatchOperation()
                        {
                            Operation = Operation.Add,
                            Path      = "/fields/System.Description",
                            Value     = bodyText.ToString()
                        }
                            );

                        WorkItem finalResult = witClient.UpdateWorkItemAsync(updatedItemBody, result.Id.Value).Result;
                        var      url         = GetUrlFromWorkItem(finalResult);
                        System.Windows.Forms.Clipboard.SetText(url, TextDataFormat.Text);

                        MessageBox.Show("Item Created Successfully, with ID: " + finalResult.Id + "\r\n\r\n" + url, "Item Created With Attachment, URL copied to clipboard");
                    }
                    else if (isUpdateMode)
                    {
                        JsonPatchDocument updatedItemBody = new JsonPatchDocument();
                        updatedItemBody.Add(
                            new JsonPatchOperation()
                        {
                            Operation = Operation.Add,
                            Path      = "/fields/System.History",
                            Value     = bodyText.ToString()
                        }
                            );

                        WorkItem finalResult = witClient.UpdateWorkItemAsync(updatedItemBody, result.Id.Value).Result;
                        var      url         = GetUrlFromWorkItem(finalResult);
                        System.Windows.Forms.Clipboard.SetText(url, TextDataFormat.Text);

                        if (!skipSaveSuccessDialog)
                        {
                            MessageBox.Show("Item updated Successfully, with ID: " + finalResult.Id + "\r\n\r\n" + url, "Item Updated, URL copied to clipboard");
                        }
                    }
                }
                else
                {
                    var url = GetUrlFromWorkItem(result);
                    System.Windows.Forms.Clipboard.SetText(url, TextDataFormat.Text);

                    if (!skipSaveSuccessDialog)
                    {
                        MessageBox.Show("Item Created Successfully, with ID: " + result.Id + "\r\n\r\n" + url, "Item Created, URL copied to clipboard");
                    }
                }
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                try
                {
                    foreach (string fp in saveFilePaths)
                    {
                        if (File.Exists(fp))
                        {
                            File.Delete(fp);
                        }
                    }
                }
                catch (System.Exception ex)
                {
                    //TODO: silently log?
                }
                CheckAndEnableControls();
            }
        }
Ejemplo n.º 18
0
        private static async Task CreateWorkItem(
            WorkItemTrackingHttpClient client,
            string type,
            Issue jira,
            string parentKey,
            string title,
            string description,
            string state,
            params JsonPatchOperation[] fields)
        {
            // Short-circuit if we've already processed this item.
            if (Migrated.ContainsKey(jira.Key.Value))
            {
                return;
            }

            var vsts = new JsonPatchDocument
            {
                new JsonPatchOperation
                {
                    Path  = "/fields/System.State",
                    Value = state
                },
                new JsonPatchOperation
                {
                    Path  = "/fields/System.CreatedBy",
                    Value = ResolveUser(jira.Reporter)
                },
                new JsonPatchOperation
                {
                    Path  = "/fields/System.CreatedDate",
                    Value = jira.Created.Value.ToUniversalTime()
                },
                new JsonPatchOperation
                {
                    Path  = "/fields/System.ChangedBy",
                    Value = ResolveUser(jira.Reporter)
                },
                new JsonPatchOperation
                {
                    Path  = "/fields/System.ChangedDate",
                    Value = jira.Created.Value.ToUniversalTime()
                },
                new JsonPatchOperation
                {
                    Path  = "/fields/System.Title",
                    Value = title
                },
                new JsonPatchOperation
                {
                    Path  = "/fields/System.Description",
                    Value = description
                },
                new JsonPatchOperation
                {
                    Path  = "/fields/Microsoft.VSTS.Common.Priority",
                    Value = ResolvePriority(jira.Priority)
                },
                new JsonPatchOperation
                {
                    Path  = "/fields/Microsoft.VSTS.Common.ClosedDate",
                    Value = jira.ResolutionDate
                },
                new JsonPatchOperation
                {
                    Path  = "/fields/Microsoft.VSTS.Scheduling.FinishDate",
                    Value = jira.ResolutionDate
                },
                new JsonPatchOperation
                {
                    Path  = "/fields/Microsoft.VSTS.Common.ResolvedDate",
                    Value = jira.ResolutionDate
                },
                new JsonPatchOperation
                {
                    Path  = "/fields/Microsoft.VSTS.Common.ResolvedReason",
                    Value = jira.Resolution?.Name
                },
                new JsonPatchOperation
                {
                    Path  = "/fields/System.IterationPath",
                    Value = ResolveIteration(jira.CustomFields["Sprint"]?.Values, config["AzureDevOps:Project"])
                },
                new JsonPatchOperation
                {
                    Path  = "/fields/Microsoft.VSTS.Scheduling.StoryPoints",
                    Value = jira.CustomFields["Story Points"]?.Values[0]
                },
                new JsonPatchOperation
                {
                    Path  = "/fields/Microsoft.VSTS.Scheduling.Effort",
                    Value = jira.CustomFields["Story Points"]?.Values[0]
                },
                new JsonPatchOperation
                {
                    Path  = "/fields/System.AreaPath",
                    Value = ResolveAreaPath(jira.CustomFields["DC Team"]?.Values[0], config["AzureDevOps:Project"])
                },
                new JsonPatchOperation
                {
                    Path  = "/fields/System.AssignedTo",
                    Value = ResolveUser(jira.Assignee)
                }
            }
            ;

            if (parentKey != null)
            {
                vsts.Add(new JsonPatchOperation
                {
                    Path  = "/relations/-",
                    Value = new WorkItemRelation
                    {
                        Rel = "System.LinkTypes.Hierarchy-Reverse",
                        Url = $"https://{config["AzureDevOps:Url"]}/_apis/wit/workItems/{Migrated[parentKey]}"
                    }
                });
            }

            if (jira.Labels.Any())
            {
                vsts.Add(new JsonPatchOperation
                {
                    Path  = "/fields/System.Tags",
                    Value = jira.Labels.Aggregate("", (l, r) => $"{l};{r}").Trim(';', ' ')
                });
            }

            foreach (var attachment in await jira.GetAttachmentsAsync())
            {
                var path = Path.GetTempFileName();
                attachment.Download(path);

                await using var stream = new MemoryStream(await File.ReadAllBytesAsync(path));

                var uploaded = await client.CreateAttachmentAsync(stream, config["AzureDevOps:Project"], fileName : attachment.FileName);

                vsts.Add(new JsonPatchOperation
                {
                    Path  = "/relations/-",
                    Value = new WorkItemRelation
                    {
                        Rel = "AttachedFile",
                        Url = uploaded.Url
                    }
                });

                File.Delete(path);
            }

            var all = vsts.Concat(fields)
                      .Where(p => p.Value != null)
                      .ToList();

            vsts = new JsonPatchDocument();
            vsts.AddRange(all);
            var workItem = await client.CreateWorkItemAsync(vsts, config["AzureDevOps:Project"], type, bypassRules : true);

            AddMigrated(jira.Key.Value, workItem.Id.Value);

            await CreateComments(client, workItem.Id.Value, jira);

            Console.WriteLine($"Added {type}: {jira.Key}{title}");
        }
Ejemplo n.º 19
0
        static void Main(string[] args)
        {
            // provide collection url of tfs
            var            collectionUri = "http://*****:*****@"C: \Users\pankagar\Downloads\Canvas.png", FileMode.Open, FileAccess.Read);
            var        attachmentObject = _witClient.CreateAttachmentAsync(uploadStream, "Canvas.png", "Simple").Result;

            // create a patchdocument object
            JsonPatchDocument json = new JsonPatchDocument();

            // create a new patch operation for title field
            JsonPatchOperation patchDocument1 = new JsonPatchOperation();

            patchDocument1.Operation = Operation.Add;
            patchDocument1.Path      = "/fields/System.Title";
            patchDocument1.Value     = "Testing Rest Api";
            json.Add(patchDocument1);

            // create a new patch operation for priority field
            JsonPatchOperation patchDocument2 = new JsonPatchOperation();

            patchDocument2.Operation = Operation.Add;
            patchDocument2.Path      = "/fields/Microsoft.VSTS.Common.Priority";
            patchDocument2.Value     = "2";
            json.Add(patchDocument2);


            // create testbasehelper object
            TestBaseHelper helper = new TestBaseHelper();
            // create testbase object to utilize teststep helpers
            ITestBase tb = helper.Create();

            // create 2 test steps ts1 and ts2
            ITestStep ts1 = tb.CreateTestStep();
            ITestStep ts2 = tb.CreateTestStep();

            ts1.Title          = "title -> title1";
            ts2.Title          = "title -> title2";
            ts1.ExpectedResult = "expected1";
            ts2.ExpectedResult = "expected2";
            ts1.Description    = "description1";
            ts2.Description    = "description2";
            // adding attachment to step1
            ts1.Attachments.Add(ts1.CreateAttachment(attachmentObject.Url, "CanvasImage"));

            // add your steps actions to testbase object
            tb.Actions.Add(ts1);
            tb.Actions.Add(ts2);

            // update json based on all actions (including teststeps and teststep attachemnts)
            json = tb.SaveActions(json);

            var xml = "";

            /* getting xml for teststeps
             * xml = tb.GenerateXmlFromActions();
             */

            // create Test Case work item using all test steps: ts1 and ts2
            var testCaseObject = _witClient.CreateWorkItemAsync(json, projectName, "Test Case").Result;
            int testCaseId     = Convert.ToInt32(testCaseObject.Id);

            // get Test Case using all relations
            testCaseObject = _witClient.GetWorkItemAsync(testCaseId, null, null, WorkItemExpand.Relations).Result;

            // update Test Case
            if (testCaseObject.Fields.ContainsKey("Microsoft.VSTS.TCM.Steps"))
            {
                xml = testCaseObject.Fields["Microsoft.VSTS.TCM.Steps"].ToString();
                tb  = helper.Create();

                // create tcmattachemntlink object from workitem relation, teststep helper will use this
                IList <TestAttachmentLink> tcmlinks = new List <TestAttachmentLink>();
                foreach (WorkItemRelation rel in testCaseObject.Relations)
                {
                    TestAttachmentLink tcmlink = new TestAttachmentLink();
                    tcmlink.Url        = rel.Url;
                    tcmlink.Attributes = rel.Attributes;
                    tcmlink.Rel        = rel.Rel;
                    tcmlinks.Add(tcmlink);
                }

                // load teststep xml and attachemnt links
                tb.LoadActions(xml, tcmlinks);

                ITestStep ts;
                //updating 1st test step
                ts                = (ITestStep)tb.Actions[0];
                ts.Title          = "title -> title11";
                ts.ExpectedResult = "expected11";

                //removing 2ns test step
                tb.Actions.RemoveAt(1);

                //adding new test step
                ITestStep ts3 = tb.CreateTestStep();
                ts3.Title          = "title -> title3";
                ts3.ExpectedResult = "expected3";
                tb.Actions.Add(ts3);

                JsonPatchDocument json2 = new JsonPatchDocument();
                // update json based on all new changes ( updated step xml and attachments)
                json2 = tb.SaveActions(json2);

                // update testcase wit using new json
                testCaseObject = _witClient.UpdateWorkItemAsync(json2, testCaseId).Result;

                /* Note : If you want to remove attachment then create new patchOperation, details are available here :
                 *        https://www.visualstudio.com/en-us/docs/integrate/api/wit/work-items#remove-an-attachment
                 */
            }
        }
        public override async Task <IEnumerable <WorkItemModel> > FileWorkItems(IEnumerable <WorkItemModel> workItemModels)
        {
            foreach (WorkItemModel workItemModel in workItemModels)
            {
                //TODO: Provide helper that generates useful attachment name from filed bug.
                //      This helper should be common to both ADO and GH filers. The implementation
                //      should work like this: the filer should prefix the proposed file name with
                //      the account and project and number of the filed work item. So an attachment
                //      name of Scan.sarif would be converted tO
                //
                //         MyAcct_MyProject_WorkItem1000_Scan.sarif
                //
                //      The GH filer may prefer to use 'issue' instead:
                //
                //         myowner_my-repo_Issue1000_Scan.sarif
                //
                //      The common helper should preserve casing choices in the account/owner and
                //      project/repo information that's provided.
                //
                //      Obviously, this proposal requires a change below to first file the bug,
                //      then compute the file name and add the attachment.
                //
                //      https://github.com/microsoft/sarif-sdk/issues/1753

                AttachmentReference attachmentReference = null;
                string attachmentText = workItemModel.Attachment?.Text;
                if (!string.IsNullOrEmpty(attachmentText))
                {
                    using (var stream = new MemoryStream())
                        using (var writer = new StreamWriter(stream))
                        {
                            writer.Write(attachmentText);
                            writer.Flush();
                            stream.Position = 0;
                            try
                            {
                                attachmentReference = await _witClient.CreateAttachmentAsync(stream, fileName : workItemModel.Attachment.Name);
                            }
                            catch
                            {
                                // TBD error handling
                                throw;
                            }
                        }
                }

                var patchDocument = new JsonPatchDocument
                {
                    new JsonPatchOperation
                    {
                        Operation = Operation.Add,
                        Path      = $"/fields/{AzureDevOpsFieldNames.Title}",
                        Value     = workItemModel.Title
                    },
                    new JsonPatchOperation
                    {
                        Operation = Operation.Add,
                        Path      = $"/fields/{AzureDevOpsFieldNames.Area}",
                        Value     = workItemModel.Area ?? workItemModel.RepositoryOrProject
                    },
                    new JsonPatchOperation
                    {
                        Operation = Operation.Add,
                        Path      = $"/fields/{AzureDevOpsFieldNames.Tags}",
                        Value     = string.Join(",", workItemModel.LabelsOrTags)
                    }
                };

                if (workItemModel.CustomFields != null)
                {
                    foreach (KeyValuePair <string, string> customField in workItemModel.CustomFields)
                    {
                        patchDocument.Add(new JsonPatchOperation
                        {
                            Operation = Operation.Add,
                            Path      = $"/fields/{customField.Key}",
                            Value     = customField.Value
                        });
                    }
                }

                if (attachmentReference != null)
                {
                    patchDocument.Add(
                        new JsonPatchOperation
                    {
                        Operation = Operation.Add,
                        Path      = $"/relations/-",
                        Value     = new
                        {
                            rel = "AttachedFile",
                            attachmentReference.Url
                        }
                    });
                }

                WorkItem workItem = null;

                try
                {
                    // TODO: Make work item kind configurable for Azure DevOps filer
                    //
                    // https://github.com/microsoft/sarif-sdk/issues/1770
                    string workItemKind = "Bug";

                    Console.Write($"Creating work item: {workItemModel.Title}");
                    workItem = await _witClient.CreateWorkItemAsync(patchDocument, project : this.ProjectOrRepository, workItemKind);

                    Console.WriteLine($": {workItem.Id}: DONE");
                }
                catch (Exception e)
                {
                    Console.Error.WriteLine(e);

                    if (patchDocument != null)
                    {
                        string patchJson = JsonConvert.SerializeObject(patchDocument, Formatting.Indented);
                        Console.Error.WriteLine(patchJson);
                    }

                    continue;
                }

                const string HTML = "html";
                workItemModel.HtmlUri = new Uri(((ReferenceLink)workItem.Links.Links[HTML]).Href, UriKind.Absolute);

                // TODO: ADO work item filer should populate the raw URI (in addition to HtmlUri)
                //
                //       https://github.com/microsoft/sarif-sdk/issues/1773
            }

            return(workItemModels);
        }
Ejemplo n.º 21
0
        public async Task <IActionResult> UploadFilesAjax()
        {
            try
            {
                CurrentUser cUser = new CurrentUser(HttpContext, _configuration);

                var uriLookup = await lookupRepo.GetLookupConfigByName(0, "Y", "DevOps_Uri");

                Uri accountUri = new Uri(uriLookup.Lvalue);

                var tokenLookup = await lookupRepo.GetLookupConfigByName(0, "Y", "DevOps_AccessToken");

                String personalAccessToken = tokenLookup.Lvalue;

                var projectLookup = await lookupRepo.GetLookupConfigByName(0, "Y", "DevOps_Project");

                string Project = projectLookup.Lvalue;

                // Create a connection to the account
                VssConnection connection = new VssConnection(accountUri, new VssBasicCredential(string.Empty, personalAccessToken));

                // Get an instance of the work item tracking client
                WorkItemTrackingHttpClient witClient = connection.GetClient <WorkItemTrackingHttpClient>();

                JsonPatchDocument patchDocument = new JsonPatchDocument();

                var          files         = Request.Form.Files;
                var          customHeaders = Request.Headers;
                StringValues taskId        = "";
                if (customHeaders.ContainsKey("taskId"))
                {
                    customHeaders.TryGetValue("taskId", out taskId);
                }

                foreach (var file in files)
                {
                    ContentDispositionHeaderValue.TryParse(file.ContentDisposition, out ContentDispositionHeaderValue parsedContentDisposition);
                    var    fileName = parsedContentDisposition.Name.TrimStart('\"').TrimEnd('\"');
                    Stream ms       = file.OpenReadStream();

                    AttachmentReference attachment = witClient.CreateAttachmentAsync(ms, Project, fileName, null, null, null).Result;

                    patchDocument.Add(new JsonPatchOperation()
                    {
                        Operation = Operation.Add,
                        Path      = "/relations/-",
                        Value     = new
                        {
                            rel        = "AttachedFile",
                            url        = attachment.Url,
                            attributes = new { comment = "Emaintenance Attachment by " + cUser.Email }
                        }
                    });
                }
                WorkItem result = witClient.UpdateWorkItemAsync(patchDocument, Int32.Parse(taskId)).Result;
                return(Ok(result));
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
Ejemplo n.º 22
0
        private async Task CreateWorkItem(string type, Issue jiraIssue, string parentKey, string title, string description, string state, params JsonPatchOperation[] fields)
        {
            var patchDocument = new JsonPatchDocument
            {
                new JsonPatchOperation {
                    Path = "/fields/System.State", Value = state
                },
                new JsonPatchOperation {
                    Path = "/fields/System.CreatedBy", Value = MapUser(jiraIssue.ReporterUser.DisplayName)
                },
                new JsonPatchOperation {
                    Path = "/fields/System.CreatedDate", Value = jiraIssue.Created.Value.ToUniversalTime()
                },
                new JsonPatchOperation {
                    Path = "/fields/System.ChangedBy", Value = MapUser(jiraIssue.ReporterUser.DisplayName)
                },
                new JsonPatchOperation {
                    Path = "/fields/System.ChangedDate", Value = jiraIssue.Created.Value.ToUniversalTime()
                },
                new JsonPatchOperation {
                    Path = "/fields/System.Title", Value = title
                },
                new JsonPatchOperation {
                    Path = "/fields/System.Description", Value = description
                },
                new JsonPatchOperation {
                    Path = "/fields/Custom.JiraID", Value = jiraIssue.Key.Value
                },
                new JsonPatchOperation {
                    Path = "/fields/Microsoft.VSTS.Common.Priority", Value = MapPriority(jiraIssue.Priority)
                }
            };

            if (jiraIssue.AdditionalFields["customfield_10301"] != null)
            {
                patchDocument.Add(new JsonPatchOperation {
                    Path = "/fields/Custom.TestURL", Value = jiraIssue.AdditionalFields["customfield_10301"]?.ToString()
                });
            }

            if (parentKey != null)
            {
                patchDocument.Add(new JsonPatchOperation {
                    Path = "/relations/-", Value = new WorkItemRelation {
                        Rel = "System.LinkTypes.Hierarchy-Reverse", Url = $"https://ciappdev.visualstudio.com/_apis/wit/workItems/{parentKey}"
                    }
                });
            }

            if (jiraIssue.AssigneeUser != null)
            {
                patchDocument.Add(new JsonPatchOperation {
                    Path = "/fields/System.AssignedTo", Value = MapUser(jiraIssue.AssigneeUser.DisplayName)
                });
            }

            patchDocument.Add(new JsonPatchOperation {
                Path = "/fields/System.Tags", Value = _jiraProjectAbbrev
            });

            var attachments = await _jiraClient.Issues.GetAttachmentsAsync(jiraIssue.JiraIdentifier).ConfigureAwait(false);

            if (attachments != null)
            {
                foreach (var attachment in attachments)
                {
                    var bytes = attachment.DownloadData();

                    using var stream = new MemoryStream(bytes);
                    var uploaded = await _witClient.CreateAttachmentAsync(stream, _devOpsProjectName, fileName : attachment.FileName).ConfigureAwait(false);

                    patchDocument.Add(new JsonPatchOperation {
                        Path = "/relations/-", Value = new WorkItemRelation {
                            Rel = "AttachedFile", Url = uploaded.Url
                        }
                    });
                }
            }

            var all = patchDocument.Concat(fields).Where(p => p.Value != null).ToList();

            patchDocument = new JsonPatchDocument();

            patchDocument.AddRange(all);

            try
            {
                var workItem = await _witClient.CreateWorkItemAsync(patchDocument, _devOpsProjectName, type, bypassRules : true).ConfigureAwait(false);

                await CreateComments(workItem.Id.Value, jiraIssue).ConfigureAwait(false);

                Console.WriteLine($"Added {type}: {jiraIssue.Key} {title}");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
Ejemplo n.º 23
0
        public static async Task <JsonPatchDocument> GetChangesAsync(this Item item, QueryDb queryDb, WorkItemTrackingHttpClient itemClient, PodioAPI.Podio podio, PodioApp app, bool ignoreRequirements, string currentIterationName)
        {
            var patchDocument = new JsonPatchDocument();
            var podioType     = item.GetPodioType(app.PodioTypeExternalId);
            var appId         = item.App.AppId;

            var mappings = queryDb.TypeMappings
                           .Include(x => x.FieldMappings)
                           .ThenInclude(x => x.CategoryMappings)
                           .Where(x => x.PodioType == podioType)
                           .SelectMany(x => x.FieldMappings)
                           .ToList();

            if (!ignoreRequirements)
            {
                foreach (var categoryField in mappings.Where(x => x.FieldType == FieldType.Category))
                {
                    var requiredValue = categoryField.CategoryMappings.SingleOrDefault(x => x.Required);
                    if (requiredValue != null)
                    {
                        var field = item.Fields
                                    .SingleOrDefault(x => x.ExternalId == categoryField.PodioFieldName);
                        if (field == null)
                        {
                            throw new ArgumentException("Rules dictate this item should not be synced");
                        }
                        var podioValueField = field.Values.ToObject <PodioValue[]>();
                        var fieldValue      = podioValueField.FirstOrDefault()?.Value?.Text;
                        if (!requiredValue.PodioValue.Equals(fieldValue, StringComparison.InvariantCultureIgnoreCase))
                        {
                            throw new ArgumentException("Rules dictate this item should not be synced");
                        }
                    }
                }
            }
            var revision = queryDb.Links.SingleOrDefault(x => x.PodioId == item.ItemId)?.PodioRevision;
            var fieldIds = revision.HasValue ? (await podio.ItemService.GetItemRevisionDifference(item.ItemId, revision.Value, item.CurrentRevision.Revision)).Select(x => x.ExternalId) : item.Fields.Select(x => x.ExternalId);

            foreach (var field in item.Fields.Where(x => fieldIds.Contains(x.ExternalId)))
            {
                var mapping = mappings.SingleOrDefault(x => x.PodioFieldName == field.ExternalId);
                if (mapping == null || (string.IsNullOrWhiteSpace(mapping.AzureFieldName) && !(mapping.FieldType == FieldType.Image || mapping.FieldType == FieldType.User)))
                {
                    continue;
                }

                switch (mapping.FieldType)
                {
                case FieldType.Image:
                    foreach (var file in item.Field <ImageItemField>(field.ExternalId)?.Images.ToList())
                    {
                        FileResponse fileResponse = await podio.FileService.DownloadFile(file);

                        using (var stream = new MemoryStream(fileResponse.FileContents))
                        {
                            var imgReference = await itemClient.CreateAttachmentAsync(stream);

                            patchDocument.Add(
                                new JsonPatchOperation()
                            {
                                Operation = Operation.Add,
                                Path      = "/relations/-",
                                Value     = new
                                {
                                    rel        = "AttachedFile",
                                    url        = imgReference.Url,
                                    attributes = new { name = file.Name }
                                }
                            }
                                );
                        }
                    }
                    break;

                case FieldType.User:
                    var    userField   = item.Field <ContactItemField>(field.ExternalId);
                    var    contact     = userField.Contacts.FirstOrDefault();
                    string commentText = "";
                    if (!queryDb.Links.Any(x => x.PodioId == item.ItemId))
                    {
                        commentText = $"Created by {contact.Name}</br>Podio url: <a href=\"{item.Link}\" target=\"_blank\">{item.Link}</a>";
                        patchDocument.Add(
                            new JsonPatchOperation()
                        {
                            Operation = Operation.Add,
                            Path      = $"/fields/System.History",
                            Value     = commentText
                        }
                            );
                    }
                    break;

                case FieldType.Category:
                    var categoryValue = field.Values.ToObject <PodioValue[]>();
                    var mappedValue   = mapping.CategoryMappings.FirstOrDefault(x => x.PodioValue == categoryValue[0].Value.Text)?.AzureValue;
                    patchDocument.Add(
                        new JsonPatchOperation()
                    {
                        Operation = Operation.Add,
                        Path      = $"/fields/{mapping.AzureFieldName}",
                        Value     = mappedValue
                    }
                        );
                    break;

                case FieldType.Boolean:
                    break;

                case FieldType.Int:
                    var numberValue = field.Values.First().Value <string>("value");
                    patchDocument.Add(
                        new JsonPatchOperation()
                    {
                        Operation = Operation.Add,
                        Path      = $"/fields/{mapping.AzureFieldName}",
                        Value     = numberValue
                    }
                        );
                    break;

                case FieldType.String:
                    var stringValue = field.Values.First().Value <string>("value");
                    var existing    = patchDocument.SingleOrDefault(x => x.Path == $"/fields/{mapping.AzureFieldName}");
                    if (existing != null)
                    {
                        existing.Value += mapping.PrefixValue + stringValue;
                    }
                    else
                    {
                        patchDocument.Add(
                            new JsonPatchOperation()
                        {
                            Operation = Operation.Add,
                            Path      = $"/fields/{mapping.AzureFieldName}",
                            Value     = mapping.PrefixValue + stringValue
                        }
                            );
                    }
                    break;

                case FieldType.Date:
                    var dateField = item.Field <DateItemField>(field.ExternalId);
                    var dateValue = dateField.Start.HasValue ? dateField.Start.Value : dateField.End.HasValue ? dateField.End.Value : DateTime.UtcNow;
                    patchDocument.Add(
                        new JsonPatchOperation()
                    {
                        Operation = Operation.Add,
                        Path      = $"/fields/{mapping.AzureFieldName}",
                        Value     = dateValue
                    }
                        );
                    break;
                }
            }

            // TODO should only attach files if they are not allready attached to Azure item
            // Handle files
            foreach (var file in item.Files)
            {
                var podioFile = await podio.FileService.DownloadFile(file);

                using (var stream = new MemoryStream(podioFile.FileContents))
                {
                    var fileReference = await itemClient.CreateAttachmentAsync(stream);

                    patchDocument.Add(
                        new JsonPatchOperation()
                    {
                        Operation = Operation.Add,
                        Path      = "/relations/-",
                        Value     = new
                        {
                            rel        = "AttachedFile",
                            url        = fileReference.Url,
                            attributes = new { name = file.Name }
                        }
                    }
                        );
                }
            }

            // Set to current iteration if it's a bug and it has priority 1
            if (patchDocument.Any(x => x.Path == "/fields/Microsoft.VSTS.Common.Priority" && x.Value.ToString() == "1") &&
                string.Equals(item.GetAzureType(app), "bug", StringComparison.CurrentCultureIgnoreCase))
            {
                patchDocument.Add(
                    new JsonPatchOperation()
                {
                    Operation = Operation.Add,
                    Path      = $"/fields/System.IterationPath",
                    Value     = currentIterationName
                });
            }
            return(patchDocument);
        }
Ejemplo n.º 24
0
        public async Task <IActionResult> UpdateWorkItem([FromBody] WorkTask wt)
        {
            CurrentUser cUser = new CurrentUser(HttpContext, _configuration);

            var uriLookup = await lookupRepo.GetLookupConfigByName(0, "Y", "DevOps_Uri");

            Uri accountUri = new Uri(uriLookup.Lvalue);

            var tokenLookup = await lookupRepo.GetLookupConfigByName(0, "Y", "DevOps_AccessToken");

            String personalAccessToken = tokenLookup.Lvalue;

            var projectLookup = await lookupRepo.GetLookupConfigByName(0, "Y", "DevOps_Project");

            wt.Project = projectLookup.Lvalue;

            // Create a connection to the account
            VssConnection connection = new VssConnection(accountUri, new VssBasicCredential(string.Empty, personalAccessToken));

            // Get an instance of the work item tracking client
            WorkItemTrackingHttpClient witClient = connection.GetClient <WorkItemTrackingHttpClient>();

            JsonPatchDocument patchDocument = new JsonPatchDocument
            {
                new JsonPatchOperation()
                {
                    Operation = Operation.Add,
                    Path      = "/fields/System.History",
                    Value     = wt.Comment + "<p>By : " + cUser.Email + "</p>"
                }
            };

            if (wt.Priority != string.Empty && wt.Priority != null)
            {
                patchDocument.Add(new JsonPatchOperation()
                {
                    Operation = Operation.Replace,
                    Path      = "/fields/Microsoft.VSTS.Common.Priority",
                    Value     = wt.Priority
                });
            }

            try
            {
                if (wt.ScreenShot != string.Empty && wt.ScreenShot != null)
                {
                    string convert = wt.ScreenShot.Replace("data:image/png;base64,", String.Empty);
                    var    stream  = new MemoryStream(Convert.FromBase64String(convert));
                    AttachmentReference attachment = witClient.CreateAttachmentAsync(stream, wt.Project, "ScreenShot.jpg", null, null, null).Result;

                    patchDocument.Add(new JsonPatchOperation()
                    {
                        Operation = Operation.Add,
                        Path      = "/relations/-",
                        Value     = new
                        {
                            rel        = "AttachedFile",
                            url        = attachment.Url,
                            attributes = new { comment = "Emaintenance Attachment by " + cUser.Email }
                        }
                    });
                }
                WorkItem result = witClient.UpdateWorkItemAsync(patchDocument, Int32.Parse(wt.Id)).Result;
                return(Ok(result));
            }
            catch (AggregateException ex)
            {
                throw ex;
            }
        }
Ejemplo n.º 25
0
        /// <summary>
        /// Creates a new bugitem with the given <paramref name="details"/> and the <paramref name="pictureOfBug"/> in the repro steps
        /// </summary>
        public async Task CreateBug(BugDetails details, ImageData pictureOfBug)
        {
            const string        urlEncodedFilename = "bug-shooter-screenshot.jpeg";
            var                 bitmap             = (Bitmap)pictureOfBug.MergedImage;
            AttachmentReference attachment;

            using (var stream = ConvertBitmapToMaxQualityJpeg(bitmap))
            {
                attachment = await _workItemClient.CreateAttachmentAsync(stream, urlEncodedFilename, uploadType : "Simple",
                                                                         areaPath : null, userState : null, cancellationToken : default);
            }

            string reproAsHtml = details.ReproSteps.Replace("\n", "<br />");

            JsonPatchDocument doc = new JsonPatchDocument
            {
                new JsonPatchOperation
                {
                    Path      = TitleFieldPath,
                    Operation = Operation.Add,
                    Value     = details.Title
                },
                new JsonPatchOperation
                {
                    Path      = ReproStepsFieldPath,
                    Operation = Operation.Add,
                    Value     = $"{reproAsHtml}<br /><img src='{attachment.Url}' />"
                },
                new JsonPatchOperation
                {
                    Path      = RelationFieldPath,
                    Operation = Operation.Add,
                    Value     = new
                    {
                        rel = "AttachedFile",
                        url = attachment.Url
                    }
                }
            };

            if (!string.IsNullOrWhiteSpace(_output.IterationName))
            {
                doc.Add(new JsonPatchOperation
                {
                    Path      = IterationFieldPath,
                    Operation = Operation.Add,
                    Value     = _output.IterationName
                });
            }

            if (!string.IsNullOrEmpty(_output.BuildDefinitionName) && !string.IsNullOrEmpty(details.Build))
            {
                doc.Add(new JsonPatchOperation
                {
                    Path      = FoundInBuildFieldPath,
                    Operation = Operation.Add,
                    Value     = $"{details.Build}"
                });
            }

            await _workItemClient.CreateWorkItemAsync(doc, _output.ProjectName, WorkItemType);
        }