public void SyncToVsts(IEnumerable <Issue> issues, JiraConnector jiraConnector) { if (!issues.AsEmptyIfNull().Any()) { return; } foreach (var issue in issues) { var existingWorkItem = this.GetWorkItemByTitleAsync(issue.Key.ToString()); bool isNew = !(existingWorkItem != null && existingWorkItem.Id.HasValue); var doc = new JsonPatchDocument(); this.UpdateFieldsBasedOnIssueType(issue, doc, jiraConnector, existingWorkItem); AddField(doc, "Microsoft.Services.Custom.InScope", issue.GetCustomFieldValue("Team").ToLowerInvariant() == "msft engineering" ? "20 - In-SOW" : ""); AddField(doc, "System.Title", $"{issue.Key.ToString()} - {issue.Summary}"); AddField(doc, "System.Description", issue.Description == null ? string.Empty : WebUtility.HtmlEncode(issue.Description).Replace("\r\n", "<br>")); AddField(doc, "System.State", issue.Status.ToVsts()); AddField(doc, "Microsoft.VSTS.Common.Priority", issue.Priority()); AddField(doc, "System.IterationPath", this.vstsProjectName + "\\Solution Model Prep"); AddField(doc, "System.Tags", string.Join(";", issue.Labels)); AddField(doc, "Contoso.Custom.Components", issue.GetComponentName(true)); if (isNew) { AddField(doc, "System.CreatedDate", issue.Created); AddField(doc, "System.ChangedDate", issue.Updated); AddField(doc, "System.History", $"Imported from Jira {DateTime.Now} ({TimeZone.CurrentTimeZone.StandardName}). Original Jira ID: {issue.Key}"); } try { var workItem = isNew ? this.witClient.CreateWorkItemAsync(doc, this.vstsProjectName, issue.Type.ToVsts(), bypassRules: true, validateOnly: false).Result : this.witClient.UpdateWorkItemAsync(doc, existingWorkItem.Id.Value, bypassRules: true, validateOnly: false).Result; } catch (Exception ex) { Utility.ShowErrorMessage(ex); this.DisplayDetailedErrorMessage(doc); throw new Exception("Ignore"); } } }
public static void SyncJiraToVSTS(Configuration connectorConfig) { if (connectorConfig != null) { var vstsConnection = new VSTSConnector(connectorConfig.vstsConfig); var jiraConnection = new JiraConnector(connectorConfig.jiraConfig); foreach (string jiraQuery in connectorConfig.JiraQueries) { Console.WriteLine($"Executing query: {jiraQuery}"); int index = 0; var issues = jiraConnection.ExecuteQueryAsBatch(jiraQuery, index++); while (issues.Any()) { Console.WriteLine($"Retrieving Batch # {index} with row count of {issues.Count()}"); vstsConnection.SyncToVsts(issues, jiraConnection); issues = jiraConnection.ExecuteQueryAsBatch(jiraQuery, index++); } } } }
private void UpdateFieldsBasedOnIssueType(Issue issue, JsonPatchDocument doc, JiraConnector jiraConnector, WorkItem existingWorkItem) { switch (issue.Type.ToString()) { case "Epic": if (!string.IsNullOrEmpty(issue.GetParentLink())) { //var roadMapIssue = jiraConnector.RoadMapCollection.GetRoadMapByName(issue.GetParentLink()); //if (roadMapIssue != null) //{ // AddField(doc, "System.AreaPath", issue.GetAreaPath(this.vstsProjectName, roadMapIssue)); //} AddField(doc, "System.AreaPath", issue.GetAreaPath(this.vstsProjectName, issue)); } break; case "Story": IList <WorkItemRelation> relations = null; if (!string.IsNullOrEmpty(issue.GetEpicLink())) { var epicParent = this.GetWorkItemByTitleAsync(issue.GetEpicLink()); //if (epicParent != null) //{ // AddField(doc, "System.AreaPath", epicParent.GetFieldValue("System.AreaPath")); //} if (existingWorkItem != null && existingWorkItem.Id.HasValue) { relations = this.GetWorkItemRelations(existingWorkItem.Id.Value); if (relations == null) { AddRelationship(doc, "System.LinkTypes.Hierarchy-Reverse", epicParent); } else { var parentId = relations.GetParentId(); if (!(parentId == epicParent.Id.Value)) { if (relations.GetPositionId(epicParent.Id.Value) > -1) { RemoveRelationship(doc, relations.GetPositionId(epicParent.Id.Value)); } if (parentId > 0) { RemoveRelationship(doc, relations.GetPositionId(parentId)); } AddRelationship(doc, "System.LinkTypes.Hierarchy-Reverse", epicParent); } } } else { AddRelationship(doc, "System.LinkTypes.Hierarchy-Reverse", epicParent); } } else { //if (!string.IsNullOrEmpty(issue.GetComponentName(true))) //{ // AddField(doc, "System.AreaPath", $"{this.vstsProjectName}\\{issue.GetComponentName(true).EncodedAreaPathName()}"); //} if (existingWorkItem != null && existingWorkItem.Id.HasValue) { relations = this.GetWorkItemRelations(existingWorkItem.Id.Value); if (relations != null) { var parentId = relations.GetParentId(); if (parentId > 0) { RemoveRelationship(doc, relations.GetPositionId(parentId)); } } } } AddField(doc, "System.AreaPath", issue.GetAreaPath(this.vstsProjectName, issue)); AddField(doc, "Contoso.Custom.JiraDispositionType", issue.GetCustomFieldValue("Issue Category")); if (!string.IsNullOrEmpty(issue.GetCustomFieldValue("Team"))) { AddField(doc, "Contoso.Custom.Team", issue.GetCustomFieldValue("Team")); } if (string.IsNullOrEmpty(existingWorkItem.GetFieldValue("Microsoft.Services.Custom.TypeofRequirement"))) { AddField(doc, "Microsoft.Services.Custom.TypeofRequirement", issue.GetCustomFieldValue("Issue Category")); } break; } if (existingWorkItem != null && existingWorkItem.GetFieldValue("System.WorkItemType") != String.Empty) { if (issue.Type.ToVsts() != existingWorkItem.GetFieldValue("System.WorkItemType")) { ChangeWorkItemType(doc, issue.Type.ToVsts()); } } }