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");
                }
            }
        }
Пример #2
0
        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());
                }
            }
        }