diff --git a/configuration.json b/configuration.json index fd7b91cb1..0511490b3 100644 --- a/configuration.json +++ b/configuration.json @@ -6,7 +6,7 @@ "Project": "migrationSource1", "ReflectedWorkItemIDFieldName": "nkdScrum.ReflectedWorkItemId", "AllowCrossProjectLinking": false, - "AuthenticationMode": "Prompt", + "AuthenticationMode": "AccessToken", "PersonalAccessToken": "", "PersonalAccessTokenVariableName": "", "LanguageMaps": { @@ -20,8 +20,8 @@ "Project": "migrationTest5", "ReflectedWorkItemIDFieldName": "nkdScrum.ReflectedWorkItemId", "AllowCrossProjectLinking": false, - "AuthenticationMode": "Prompt", - "PersonalAccessToken": "njp3kcec4nbev63fmbepvdpn35drawmonk5qf5yqsw77dgfwnjda", + "AuthenticationMode": "AccessToken", + "PersonalAccessToken": "", "PersonalAccessTokenVariableName": "", "LanguageMaps": { "AreaPath": "Area", @@ -34,12 +34,15 @@ "CommonEnrichersConfig": [ { "$type": "TfsNodeStructureOptions", + "Enabled": false, "NodeBasePaths": [], "AreaMaps": { + "^migrationSource1([\\\\]?.*)$": "MigrationTest5$1", "^nkdProducts([\\\\]?.*)$": "MigrationTest5$1", "^Skypoint Cloud$": "MigrationTest5" }, "IterationMaps": { + "^migrationSource1([\\\\]?.*)$": "MigrationTest5$1", "^nkdProducts([\\\\]?.*)$": "MigrationTest5$1", "^Skypoint Cloud\\\\Sprint 1$": "MigrationTest5\\Sprint 1" }, @@ -98,7 +101,7 @@ "Enabled": true, "UpdateCreatedDate": true, "UpdateCreatedBy": true, - "WIQLQuery": "SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.WorkItemType] NOT IN ('Program', 'Portfolio', 'Test Suite', 'Test Plan','Shared Steps','Shared Parameter','Feedback Request') ORDER BY [System.ChangedDate] desc", + "WIQLQuery": "SELECT [System.Id] FROM WorkItems WHERE [System.Id] =137 AND [System.TeamProject] = @TeamProject AND [System.WorkItemType] NOT IN ('Program', 'Portfolio', 'Test Suite', 'Test Plan','Shared Steps','Shared Parameter','Feedback Request') ORDER BY [System.ChangedDate] desc", "LinkMigration": true, "FixHtmlAttachmentLinks": false, "SkipToFinalRevisedWorkItemType": false, @@ -123,7 +126,7 @@ "Version": "15.0", "workaroundForQuerySOAPBugEnabled": false, "WorkItemTypeDefinition": { - "sourceWorkItemTypeName": "targetWorkItemTypeName" + "User Story": "Product Backlog Item" }, "Endpoints": { "InMemoryWorkItemEndpoints": [ diff --git a/src/MigrationTools/ConfigException.cs b/src/MigrationTools/ConfigException.cs new file mode 100644 index 000000000..fe5eb5c5e --- /dev/null +++ b/src/MigrationTools/ConfigException.cs @@ -0,0 +1,25 @@ +using System; +using System.Runtime.Serialization; + +namespace MigrationTools +{ + [Serializable] + internal class ConfigException : Exception + { + public ConfigException() + { + } + + public ConfigException(string message) : base(message) + { + } + + public ConfigException(string message, Exception innerException) : base(message, innerException) + { + } + + protected ConfigException(SerializationInfo info, StreamingContext context) : base(info, context) + { + } + } +} \ No newline at end of file diff --git a/src/VstsSyncMigrator.Core/Execution/MigrationContext/ConfigException.cs b/src/VstsSyncMigrator.Core/Execution/MigrationContext/ConfigException.cs new file mode 100644 index 000000000..299bfb305 --- /dev/null +++ b/src/VstsSyncMigrator.Core/Execution/MigrationContext/ConfigException.cs @@ -0,0 +1,25 @@ +using System; +using System.Runtime.Serialization; + +namespace VstsSyncMigrator.Engine +{ + [Serializable] + internal class ConfigException : Exception + { + public ConfigException() + { + } + + public ConfigException(string message) : base(message) + { + } + + public ConfigException(string message, Exception innerException) : base(message, innerException) + { + } + + protected ConfigException(SerializationInfo info, StreamingContext context) : base(info, context) + { + } + } +} \ No newline at end of file diff --git a/src/VstsSyncMigrator.Core/Execution/MigrationContext/WorkItemMigrationContext.cs b/src/VstsSyncMigrator.Core/Execution/MigrationContext/WorkItemMigrationContext.cs index 9a778c936..df90b4449 100644 --- a/src/VstsSyncMigrator.Core/Execution/MigrationContext/WorkItemMigrationContext.cs +++ b/src/VstsSyncMigrator.Core/Execution/MigrationContext/WorkItemMigrationContext.cs @@ -155,8 +155,14 @@ protected override void InternalExecute() embededImagesEnricher = Services.GetRequiredService(); gitRepositoryEnricher = Services.GetRequiredService(); - - _nodeStructureEnricher.ProcessorExecutionBegin(null); + if (_nodeStructureEnricher.Options.Enabled) + { + _nodeStructureEnricher.ProcessorExecutionBegin(null); + } else + { + Log.LogWarning("WorkItemMigrationContext::InternalExecute: nodeStructureEnricher is disabled! This may cause work item migration errors! "); + } + var stopwatch = Stopwatch.StartNew(); _itemsInError = new List(); @@ -284,11 +290,21 @@ private void ValidateAllUsersExistOrAreMapped(List sourceWorkItems private void ValidateAllNodesExistOrAreMapped(List sourceWorkItems) { contextLog.Information("Validating::Check that all Area & Iteration paths from Source have a valid mapping on Target"); - List nodeStructureMissingItems = _nodeStructureEnricher.GetMissingRevisionNodes(sourceWorkItems); - if (_nodeStructureEnricher.ValidateTargetNodesExist(nodeStructureMissingItems)) + if (!_nodeStructureEnricher.Options.Enabled && Engine.Target.Config.AsTeamProjectConfig().Project != Engine.Source.Config.AsTeamProjectConfig().Project) { - throw new Exception("Missing Iterations in Target preventing progress, check log for list. To continue you MUST configure IterationMaps or AreaMaps that matches the missing paths.."); + throw new ConfigException("Source and Target projects have different names, but NodeStructureEnricher is not enabled. Cant continue... please enable nodeStructureEnricher in the config and restart."); } + if ( _nodeStructureEnricher.Options.Enabled) + { + List nodeStructureMissingItems = _nodeStructureEnricher.GetMissingRevisionNodes(sourceWorkItems); + if (_nodeStructureEnricher.ValidateTargetNodesExist(nodeStructureMissingItems)) + { + throw new Exception("Missing Iterations in Target preventing progress, check log for list. To continue you MUST configure IterationMaps or AreaMaps that matches the missing paths.."); + } + } else + { + contextLog.Error("nodeStructureEnricher is disabled! Please enable it in the config."); + } } private void ValidateAllWorkItemTypesHaveReflectedWorkItemIdField(List sourceWorkItems) @@ -477,9 +493,14 @@ private void PopulateWorkItem(WorkItemData oldWorkItemData, WorkItemData newWork if (_nodeStructureEnricher.Options.Enabled) { + newWorkItem.AreaPath = _nodeStructureEnricher.GetNewNodeName(oldWorkItem.AreaPath, TfsNodeStructureType.Area); newWorkItem.IterationPath = _nodeStructureEnricher.GetNewNodeName(oldWorkItem.IterationPath, TfsNodeStructureType.Iteration); } + else + { + Log.LogWarning("WorkItemMigrationContext::PopulateWorkItem::nodeStructureEnricher::Disabled! This needs to be set to true!"); + } switch (destType) { @@ -544,7 +565,7 @@ private async Task ProcessWorkItemAsync(WorkItemData sourceWorkItem, int retryLi { "sourceWorkItemRev", sourceWorkItem.Rev }, { "ReplayRevisions", _revisionManager.Options.ReplayRevisions }} ); - List revisionsToMigrate = _revisionManager.GetRevisionsToMigrate(sourceWorkItem.Revisions.Values.ToList(), targetWorkItem.Revisions.Values.ToList()); + List revisionsToMigrate = _revisionManager.GetRevisionsToMigrate(sourceWorkItem.Revisions.Values.ToList(), targetWorkItem?.Revisions.Values.ToList()); if (targetWorkItem == null) { targetWorkItem = ReplayRevisions(revisionsToMigrate, sourceWorkItem, null);