private WitBatchRequest GenerateWitBatchRequestFromWorkItem(WorkItem sourceWorkItem)
        {
            Dictionary <string, string> headers = new Dictionary <string, string>();

            headers.Add("Content-Type", "application/json-patch+json");

            JsonPatchDocument jsonPatchDocument = CreateJsonPatchDocumentFromWorkItemFields(sourceWorkItem);

            JsonPatchOperation insertIdAddOperation = GetInsertBatchIdAddOperation();

            jsonPatchDocument.Add(insertIdAddOperation);

            // add hyperlink to source WorkItem
            string             sourceWorkItemApiEndpoint = ClientHelpers.GetWorkItemApiEndpoint(this.migrationContext.Config.SourceConnection.Account, sourceWorkItem.Id.Value);
            JsonPatchOperation addHyperlinkAddOperation  = MigrationHelpers.GetHyperlinkAddOperation(sourceWorkItemApiEndpoint, sourceWorkItem.Rev.ToString());

            jsonPatchDocument.Add(addHyperlinkAddOperation);

            string json = JsonConvert.SerializeObject(jsonPatchDocument);

            string workItemType = jsonPatchDocument.Find(a => a.Path.Contains(FieldNames.WorkItemType)).Value as string;

            var witBatchRequest = new WitBatchRequest();

            witBatchRequest.Method  = "PATCH";
            witBatchRequest.Headers = headers;
            witBatchRequest.Uri     = $"/{this.migrationContext.Config.TargetConnection.Project}/_apis/wit/workItems/${workItemType}?{this.QueryString}";
            witBatchRequest.Body    = json;

            return(witBatchRequest);
        }
        private WitBatchRequest GenerateWitBatchRequestFromWorkItem(WorkItem sourceWorkItem, int targetId)
        {
            Dictionary <string, string> headers = new Dictionary <string, string>();

            headers.Add("Content-Type", "application/json-patch+json");

            JsonPatchDocument jsonPatchDocument = CreateJsonPatchDocumentFromWorkItemFields(sourceWorkItem);

            string hyperlink   = this.migrationContext.WorkItemIdsUris[sourceWorkItem.Id.Value];
            object attributeId = migrationContext.TargetIdToSourceHyperlinkAttributeId[targetId];

            JsonPatchOperation addHyperlinkWithCommentOperation = MigrationHelpers.GetHyperlinkAddOperation(hyperlink, sourceWorkItem.Rev.ToString(), attributeId);

            jsonPatchDocument.Add(addHyperlinkWithCommentOperation);

            string json            = JsonConvert.SerializeObject(jsonPatchDocument);
            var    witBatchRequest = new WitBatchRequest();

            witBatchRequest.Method  = "PATCH";
            witBatchRequest.Headers = headers;
            witBatchRequest.Uri     = $"/_apis/wit/workItems/{targetId}?{this.QueryString}";
            witBatchRequest.Body    = json;

            return(witBatchRequest);
        }
        public async override Task Write()
        {
            var sourceIdToWitBatchRequests = new List <(int SourceId, WitBatchRequest WitBatchRequest)>();

            foreach (var targetIdToSourceWorkItem in this.batchContext.TargetIdToSourceWorkItemMapping)
            {
                int      targetId       = targetIdToSourceWorkItem.Key;
                WorkItem sourceWorkItem = targetIdToSourceWorkItem.Value;

                if (WorkItemHasFailureState(sourceWorkItem))
                {
                    continue;
                }

                WitBatchRequest witBatchRequest = GenerateWitBatchRequestFromWorkItem(sourceWorkItem, targetId);
                if (witBatchRequest != null)
                {
                    sourceIdToWitBatchRequests.Add((sourceWorkItem.Id.Value, witBatchRequest));
                }

                DecrementIdWithinBatch(sourceWorkItem.Id);
            }

            var phase1ApiWrapper = new Phase1ApiWrapper();
            await phase1ApiWrapper.ExecuteWitBatchRequests(sourceIdToWitBatchRequests, this.migrationContext, batchContext);
        }
Example #4
0
        private async Task <IList <(int SourceId, WitBatchRequest WitBatchRequest)> > GenerateWitBatchRequestsForPhase2Batch(IBatchMigrationContext batchContext, int batchId, IList <WorkItemMigrationState> workItemMigrationState, IList <WorkItem> sourceWorkItems, IList <WorkItem> targetWorkItems)
        {
            IList <(int SourceId, WitBatchRequest WitBatchRequest)> result = new List <(int SourceId, WitBatchRequest WitBatchRequest)>();
            IEnumerable <IPhase2Processor> phase2Processors = ClientHelpers.GetProcessorInstances <IPhase2Processor>(context.Config);

            foreach (IPhase2Processor processor in phase2Processors)
            {
                Logger.LogInformation(LogDestination.File, $"Starting preprocessing of phase 2 step {processor.Name} for batch {batchId}");
                await processor.Preprocess(context, batchContext, sourceWorkItems, targetWorkItems);

                Logger.LogInformation(LogDestination.File, $"Completed preprocessing of phase 2 step {processor.Name} for batch {batchId}");
            }

            foreach (var sourceToTarget in batchContext.SourceWorkItemIdToTargetWorkItemIdMapping)
            {
                int sourceId = sourceToTarget.Key;
                int targetId = sourceToTarget.Value;

                WorkItem sourceWorkItem = sourceWorkItems.First(a => a.Id == sourceId);
                WorkItem targetWorkItem = targetWorkItems.First(a => a.Id == targetId);

                IList <JsonPatchOperation> jsonPatchOperations = new List <JsonPatchOperation>();

                WorkItemMigrationState state = workItemMigrationState.First(a => a.SourceId == sourceId);
                state.RevAndPhaseStatus = GetRevAndPhaseStatus(targetWorkItem, sourceId);
                ISet <string> enabledPhaseStatuses = System.Linq.Enumerable.ToHashSet(phase2Processors.Where(a => a.IsEnabled(context.Config)).Select(b => b.Name));
                enabledPhaseStatuses.Remove(Constants.RelationPhaseClearAllRelations);

                foreach (IPhase2Processor processor in phase2Processors)
                {
                    IEnumerable <JsonPatchOperation> processorJsonPatchOperations = await processor.Process(context, batchContext, sourceWorkItem, targetWorkItem);

                    jsonPatchOperations.AddRange(processorJsonPatchOperations);
                }

                jsonPatchOperations.Add(GetAddHyperlinkWithCommentOperation(targetWorkItems, state, sourceId, targetId, sourceWorkItem, enabledPhaseStatuses));

                if (this.context.Config.IncludeWebLink)
                {
                    var link = (ReferenceLink)sourceWorkItem.Links.Links["html"];
                    var addWebLinkOperation = MigrationHelpers.GetHyperlinkAddOperation(link.Href);
                    jsonPatchOperations.Add(addWebLinkOperation);
                }

                if (jsonPatchOperations.Any())
                {
                    WitBatchRequest witBatchRequest = GenerateWitBatchRequestFromJsonPatchOperations(jsonPatchOperations, targetId);
                    result.Add((sourceId, witBatchRequest));
                }
            }

            return(result);
        }
Example #5
0
        private async Task MigratePhase3()
        {
            IEnumerable <IPhase3Processor> phase3Processors = ClientHelpers.GetProcessorInstances <IPhase3Processor>(context.Config);

            if (phase3Processors != null && !phase3Processors.Any())
            {
                // nothing to do if no phase 3 processors are enabled
                return;
            }

            // Phase1 or Phase2 have completed, and FailureReason == None
            IEnumerable <WorkItemMigrationState> successfullyMigratedWorkItemMigrationStates = context.WorkItemsMigrationState.Where(w => (w.MigrationCompleted.HasFlag(WorkItemMigrationState.MigrationCompletionStatus.Phase1) || w.MigrationCompleted.HasFlag(WorkItemMigrationState.MigrationCompletionStatus.Phase2)) && w.FailureReason == FailureReason.None);
            var phase3WorkItemsToUpdateCount = successfullyMigratedWorkItemMigrationStates.Count();
            var totalNumberOfBatches         = ClientHelpers.GetBatchCount(phase3WorkItemsToUpdateCount, Constants.BatchSize);

            if (phase3WorkItemsToUpdateCount == 0)
            {
                return;
            }

            await successfullyMigratedWorkItemMigrationStates.Batch(Constants.BatchSize).ForEachAsync(context.Config.Parallelism, async(workItemMigrationStateBatch, batchId) =>
            {
                IBatchMigrationContext batchContext = new BatchMigrationContext(batchId, workItemMigrationStateBatch);
                IList <(int SourceId, WitBatchRequest WitBatchRequest)> sourceIdToWitBatchRequests = new List <(int SourceId, WitBatchRequest WitBatchRequest)>();
                IList <WorkItem> sourceWorkItemsInBatch = await WorkItemTrackingHelpers.GetWorkItemsAsync(context.SourceClient.WorkItemTrackingHttpClient, workItemMigrationStateBatch.Select(a => a.SourceId).ToList(), expand: WorkItemExpand.All);

                foreach (WorkItem sourceWorkItem in sourceWorkItemsInBatch)
                {
                    IList <JsonPatchOperation> jsonPatchOperations = new List <JsonPatchOperation>();
                    foreach (IPhase3Processor processor in phase3Processors)
                    {
                        IEnumerable <JsonPatchOperation> processorJsonPatchOperations = await processor.Process(context, null, sourceWorkItem, null);
                        jsonPatchOperations.AddRange(processorJsonPatchOperations);
                    }

                    if (jsonPatchOperations.Any())
                    {
                        WitBatchRequest witBatchRequest = GenerateWitBatchRequestFromJsonPatchOperations(jsonPatchOperations, sourceWorkItem.Id.Value);
                        sourceIdToWitBatchRequests.Add((sourceWorkItem.Id.Value, witBatchRequest));
                    }
                }

                var phase3ApiWrapper = new Phase3ApiWrapper();
                await phase3ApiWrapper.ExecuteWitBatchRequests(sourceIdToWitBatchRequests, context, batchContext);
            });
        }
Example #6
0
        private WitBatchRequest GenerateWitBatchRequestFromJsonPatchOperations(IList <JsonPatchOperation> jsonPatchOperations, int workItemId)
        {
            Dictionary <string, string> headers = new Dictionary <string, string>();

            headers.Add("Content-Type", "application/json-patch+json");

            JsonPatchDocument jsonPatchDocument = new JsonPatchDocument();

            jsonPatchDocument.AddRange(jsonPatchOperations);

            WitBatchRequest witBatchRequest = null;

            if (jsonPatchDocument.Any())
            {
                witBatchRequest = new WitBatchRequest();
                string json = JsonConvert.SerializeObject(jsonPatchDocument);
                witBatchRequest.Method  = "PATCH";
                witBatchRequest.Headers = headers;
                witBatchRequest.Uri     = $"/_apis/wit/workItems/{workItemId}?{this.queryString}";
                witBatchRequest.Body    = json;
            }

            return(witBatchRequest);
        }