Skip to content

Commit 97de284

Browse files
authored
Update to check for missing pat! (#1731)
* Update to check for missing pat! * prevent executution against ADO if not providing a PAT * Update to funcation * Update to fix defaults
1 parent e09eca9 commit 97de284

File tree

9 files changed

+75
-24
lines changed

9 files changed

+75
-24
lines changed

docs/Reference/Generated/MigrationTools.Host.xml

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/MigrationTools.ConsoleFull/Properties/launchSettings.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22
"profiles": {
33
"execute": {
44
"commandName": "Project",
5-
"commandLineArgs": "execute -c configuration.json"
5+
"commandLineArgs": "execute -c \"C:\\temp\\configuration.json\""
66
},
77
"executepipe": {
88
"commandName": "Project",
99
"commandLineArgs": "execute -c configuration2-pipeline.json"
1010
},
1111
"init": {
1212
"commandName": "Project",
13-
"commandLineArgs": "init --options Full"
13+
"commandLineArgs": "init --options Basic"
1414
},
1515
"execute2": {
1616
"commandName": "Project",

src/MigrationTools.Host/CommandLine/InitOptions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ public class InitOptions
88
[Option('c', "config", Required = false, HelpText = "Configuration file to be processed.")]
99
public string ConfigFile { get; set; }
1010

11-
[Option('o', "options", Required = false, Default = OptionsMode.WorkItemTracking, HelpText = "Configuration file to be processed.")]
11+
[Option('o', "options", Required = false, Default = OptionsMode.Basic, HelpText = "Configuration file to be generated: Basic, Reference, WorkItemTracking, Fullv2, WorkItemTrackingv2")]
1212
public OptionsMode Options { get; set; }
1313
}
1414
}

src/MigrationTools.Host/CommandLine/OptionsMode.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
{
33
public enum OptionsMode
44
{
5-
Full = 0,
5+
Reference = 0,
66
WorkItemTracking = 1,
77
Fullv2 = 2,
8-
WorkItemTrackingv2 = 3
8+
WorkItemTrackingv2 = 3,
9+
Basic = 4
910
}
1011
}

src/MigrationTools.Host/InitHostedService.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,11 @@ public Task StartAsync(CancellationToken cancellationToken)
6363
EngineConfiguration config;
6464
switch (_initOptions.Options)
6565
{
66-
case OptionsMode.Full:
67-
config = _configurationBuilder.BuildDefault();
66+
case OptionsMode.Reference:
67+
config = _configurationBuilder.BuildReference();
68+
break;
69+
case OptionsMode.Basic:
70+
config = _configurationBuilder.BuildGettingStarted();
6871
break;
6972

7073
case OptionsMode.WorkItemTracking:
@@ -80,7 +83,7 @@ public Task StartAsync(CancellationToken cancellationToken)
8083
break;
8184

8285
default:
83-
config = _configurationBuilder.BuildDefault();
86+
config = _configurationBuilder.BuildGettingStarted();
8487
break;
8588
}
8689
_settingWriter.WriteSettings(config, configFile);

src/MigrationTools/_EngineV1/Configuration/EngineConfigurationBuilder.cs

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,30 @@ public EngineConfiguration BuildDefault()
106106
return ec;
107107
}
108108

109+
public EngineConfiguration BuildReference()
110+
{
111+
EngineConfiguration ec = CreateEmptyConfig();
112+
AddExampleFieldMapps(ec);
113+
AddWorkItemMigrationDefault(ec);
114+
AddTestPlansMigrationDefault(ec);
115+
ec.Processors.Add(new ImportProfilePictureConfig());
116+
ec.Processors.Add(new ExportProfilePictureFromADConfig());
117+
ec.Processors.Add(new FixGitCommitLinksConfig() { TargetRepository = "targetProjectName" });
118+
ec.Processors.Add(new WorkItemUpdateConfig());
119+
ec.Processors.Add(new WorkItemPostProcessingConfig() { WorkItemIDs = new List<int> { 1, 2, 3 } });
120+
ec.Processors.Add(new WorkItemDeleteConfig());
121+
ec.Processors.Add(new WorkItemQueryMigrationConfig() { SourceToTargetFieldMappings = new Dictionary<string, string>() { { "SourceFieldRef", "TargetFieldRef" } } });
122+
ec.Processors.Add(new TeamMigrationConfig());
123+
return ec;
124+
}
125+
126+
public EngineConfiguration BuildGettingStarted()
127+
{
128+
EngineConfiguration ec = CreateEmptyConfig();
129+
AddWorkItemMigrationDefault(ec);
130+
return ec;
131+
}
132+
109133
public EngineConfiguration BuildWorkItemMigration()
110134
{
111135
EngineConfiguration ec = CreateEmptyConfig();
@@ -116,10 +140,7 @@ public EngineConfiguration BuildWorkItemMigration()
116140

117141
private void AddWorkItemMigrationDefault(EngineConfiguration ec)
118142
{
119-
var config = new WorkItemMigrationConfig
120-
{
121-
NodeBasePaths = new[] { "Product\\Area\\Path1", "Product\\Area\\Path2" }
122-
};
143+
var config = new WorkItemMigrationConfig();
123144
ec.Processors.Add(config);
124145
}
125146

@@ -337,5 +358,7 @@ public void WriteSettings(EngineConfiguration engineConfiguration, string settin
337358

338359
File.WriteAllText(settingsFileName, json);
339360
}
361+
362+
340363
}
341364
}

src/MigrationTools/_EngineV1/Configuration/IEngineConfigurationBuilder.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ public interface IEngineConfigurationBuilder
55
EngineConfiguration BuildDefault();
66

77
EngineConfiguration BuildDefault2();
8-
8+
EngineConfiguration BuildGettingStarted();
9+
EngineConfiguration BuildReference();
910
EngineConfiguration BuildWorkItemMigration();
1011

1112
EngineConfiguration BuildWorkItemMigration2();

src/MigrationTools/_EngineV1/Configuration/Processing/WorkItemMigrationConfig.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ public WorkItemMigrationConfig()
221221
UpdateCreatedBy = true;
222222
PrefixProjectToNodes = false;
223223
UpdateCreatedDate = true;
224-
SkipToFinalRevisedWorkItemType = true;
224+
SkipToFinalRevisedWorkItemType = false;
225225
LinkMigrationSaveEachAsAdded = false;
226226
GenerateMigrationComment = true;
227227
WIQLQueryBit = @"AND [Microsoft.VSTS.Common.ClosedDate] = '' AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan','Shared Steps','Shared Parameter','Feedback Request')";

src/VstsSyncMigrator.Core/Execution/MigrationContext/WorkItemMigrationContext.cs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
using Microsoft.Extensions.DependencyInjection;
1313
using Microsoft.Extensions.Logging;
1414
using Microsoft.Extensions.Options;
15+
using Microsoft.TeamFoundation.Common;
1516
using Microsoft.TeamFoundation.WorkItemTracking.Client;
1617
using Microsoft.TeamFoundation.WorkItemTracking.Proxy;
1718
using Microsoft.TeamFoundation.WorkItemTracking.WebApi;
@@ -29,6 +30,7 @@
2930
using MigrationTools.DataContracts;
3031
using MigrationTools.Enrichers;
3132
using MigrationTools.ProcessorEnrichers;
33+
using Newtonsoft.Json.Linq;
3234
using Serilog.Context;
3335
using Serilog.Events;
3436
using ILogger = Serilog.ILogger;
@@ -140,7 +142,9 @@ protected override void InternalExecute()
140142
{
141143
throw new Exception("You must call Configure() first");
142144
}
143-
145+
//////////////////////////////////////////////////
146+
ValidatePatTokenRequirement();
147+
//////////////////////////////////////////////////
144148
var workItemServer = Engine.Source.GetService<WorkItemServer>();
145149
attachmentEnricher = new TfsAttachmentEnricher(workItemServer, _config.AttachmentWorkingPath, _config.AttachmentMaxSize);
146150
embededImagesEnricher = Services.GetRequiredService<TfsEmbededImagesEnricher>();
@@ -167,12 +171,14 @@ protected override void InternalExecute()
167171
contextLog.Information("Replay all revisions of {sourceWorkItemsCount} work items?",
168172
sourceWorkItems.Count);
169173

174+
175+
170176
//////////////////////////////////////////////////
171177
contextLog.Information("ValidateTargetNodesExist::Checking all Nodes on Work items");
172178
List<NodeStructureMissingItem> nodeStructureMissingItems = _nodeStructureEnricher.GetMissingRevisionNodes(sourceWorkItems);
173179
if (_nodeStructureEnricher.ValidateTargetNodesExist(nodeStructureMissingItems))
174180
{
175-
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..");
181+
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..");
176182
}
177183

178184
//////////////////////////////////////////////////
@@ -271,6 +277,21 @@ protected override void InternalExecute()
271277
}
272278
}
273279

280+
private void ValidatePatTokenRequirement()
281+
{
282+
string collUrl = Engine.Target.Config.AsTeamProjectConfig().Collection.ToString();
283+
if (collUrl.Contains("dev.azure.com") || collUrl.Contains(".visualstudio.com"))
284+
{
285+
// Test that
286+
if (Engine.Target.Config.AsTeamProjectConfig().PersonalAccessToken.IsNullOrEmpty())
287+
{
288+
var ex = new InvalidOperationException("Missing PersonalAccessToken from Target");
289+
Log.LogError(ex, "When you are migrating to Azure DevOps you MUST provide an PAT so that we can call the REST API for certain actions. For example we would be unable to deal with a Work item Type change.");
290+
throw ex;
291+
}
292+
}
293+
}
294+
274295
internal string FixAreaPathAndIterationPathForTargetQuery(string sourceWIQLQueryBit, string sourceProject, string targetProject, ILogger? contextLog)
275296
{
276297

@@ -668,8 +689,10 @@ private WorkItemData ReplayRevisions(List<RevisionItem> revisionsToMigrate, Work
668689
destType = Engine.TypeDefinitionMaps.Items[destType].Map();
669690
}
670691
bool typeChange = (destType != targetWorkItem.Type);
692+
671693
if (typeChange)
672694
{
695+
ValidatePatTokenRequirement();
673696
Uri collectionUri = Engine.Target.Config.AsTeamProjectConfig().Collection;
674697
string token = Engine.Target.Config.AsTeamProjectConfig().PersonalAccessToken;
675698
VssConnection connection = new VssConnection(collectionUri, new VssBasicCredential(string.Empty, token));

0 commit comments

Comments
 (0)