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); }
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); }
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); }); }
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); }