Skip to content

Commit 9e99ced

Browse files
committed
Validation of reflected work item ID is mandatory, even if the validator tool is disabled
1 parent 131fde8 commit 9e99ced

File tree

3 files changed

+91
-40
lines changed

3 files changed

+91
-40
lines changed

src/MigrationTools.Clients.TfsObjectModel/Processors/TfsWorkItemMigrationProcessor.cs

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -254,24 +254,25 @@ private void ValidateWorkItemTypes()
254254
Log.LogInformation("Starting Pre-Validation: Validating work item types and fields with `WorkItemTypeValidatorTool`.");
255255
Log.LogInformation("Refer to https://devopsmigration.io/TfsWorkItemTypeValidatorTool/ for configuration.");
256256
Log.LogInformation("------------------------------------");
257+
258+
var sourceWits = Source.WorkItems.Project
259+
.ToProject()
260+
.WorkItemTypes
261+
.Cast<WorkItemType>()
262+
.ToList();
263+
var targetWits = Target.WorkItems.Project
264+
.ToProject()
265+
.WorkItemTypes
266+
.Cast<WorkItemType>()
267+
.ToList();
268+
269+
// Reflected work item ID field is mandatory for migration, so it is validated even if the validator tool is disabled.
270+
bool containsReflectedWorkItemId = CommonTools.WorkItemTypeValidatorTool.ValidateReflectedWorkItemIdField(
271+
sourceWits, targetWits, Target.Options.ReflectedWorkItemIdField);
272+
bool validationResult = true;
257273
if (CommonTools.WorkItemTypeValidatorTool.Enabled)
258274
{
259-
var sourceWits = Source.WorkItems.Project
260-
.ToProject()
261-
.WorkItemTypes
262-
.Cast<WorkItemType>()
263-
.ToList();
264-
var targetWits = Target.WorkItems.Project
265-
.ToProject()
266-
.WorkItemTypes
267-
.Cast<WorkItemType>()
268-
.ToList();
269-
if (!CommonTools.WorkItemTypeValidatorTool.ValidateWorkItemTypes(
270-
sourceWits, targetWits, Target.Options.ReflectedWorkItemIdField))
271-
{
272-
Log.LogError("Validation of work item types failed.");
273-
Environment.Exit(-1);
274-
}
275+
validationResult = CommonTools.WorkItemTypeValidatorTool.ValidateWorkItemTypes(sourceWits, targetWits);
275276
}
276277
else
277278
{
@@ -281,6 +282,11 @@ private void ValidateWorkItemTypes()
281282
+ " or migration may not work at all.";
282283
Log.LogWarning(msg);
283284
}
285+
if (!containsReflectedWorkItemId || !validationResult)
286+
{
287+
Log.LogError("Validation of work item types failed.");
288+
Environment.Exit(-1);
289+
}
284290
Log.LogInformation("------------------------------------");
285291
Log.LogInformation("[/ValidateWorkItemTypes]");
286292
}

src/MigrationTools.Clients.TfsObjectModel/Processors/TfsWorkItemTypeValidatorProcessor.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,16 @@ protected override void InternalExecute()
4747
.WorkItemTypes
4848
.Cast<WorkItemType>()
4949
.ToList();
50+
bool containsReflectedWorkItemId = CommonTools.WorkItemTypeValidatorTool
51+
.ValidateReflectedWorkItemIdField(sourceWits, targetWits, Target.Options.ReflectedWorkItemIdField);
5052
bool validationResult = CommonTools.WorkItemTypeValidatorTool
51-
.ValidateWorkItemTypes(sourceWits, targetWits, Target.Options.ReflectedWorkItemIdField);
52-
if (Options.StopIfValidationFails && !validationResult)
53+
.ValidateWorkItemTypes(sourceWits, targetWits);
54+
if ((Options.StopIfValidationFails && !validationResult) || (!containsReflectedWorkItemId))
5355
{
54-
Log.LogInformation($"'{nameof(Options.StopIfValidationFails)}' is set to 'true', so migration process will stop now.");
56+
const string message =
57+
"Either the reflected work item type ID field '{ReflectedWorkItemIdField}' is missing in some of the target work item types"
58+
+ $" or '{nameof(Options.StopIfValidationFails)}' is set to 'true', so migration process will stop now.";
59+
Log.LogInformation(message, Target.Options.ReflectedWorkItemIdField);
5560
Environment.Exit(-1);
5661
}
5762
}

src/MigrationTools.Clients.TfsObjectModel/Tools/TfsWorkItemTypeValidatorTool.cs

Lines changed: 61 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,55 @@ public TfsWorkItemTypeValidatorTool(
3030
Options.Normalize();
3131
}
3232

33-
public bool ValidateWorkItemTypes(
33+
public bool ValidateReflectedWorkItemIdField(
3434
List<WorkItemType> sourceWits,
3535
List<WorkItemType> targetWits,
3636
string reflectedWorkItemIdField)
37+
{
38+
Log.LogInformation("Validating presence of reflected work item ID field '{reflectedWorkItemIdField}'"
39+
+ " in target work item types.", reflectedWorkItemIdField);
40+
bool isValid = true;
41+
List<WorkItemType> wits = GetTargetWitsToValidate(sourceWits, targetWits);
42+
foreach (WorkItemType targetWit in wits)
43+
{
44+
if (targetWit.FieldDefinitions.Contains(reflectedWorkItemIdField))
45+
{
46+
Log.LogDebug(" '{targetWit}' contains reflected work item ID field '{fieldName}'.",
47+
targetWit.Name, reflectedWorkItemIdField);
48+
}
49+
else
50+
{
51+
Log.LogError(" '{targetWit}' does not contain reflected work item ID field '{fieldName}'.",
52+
targetWit.Name, reflectedWorkItemIdField);
53+
isValid = false;
54+
}
55+
}
56+
LogReflectedWorkItemIdValidationResult(isValid, reflectedWorkItemIdField);
57+
return isValid;
58+
}
59+
60+
private List<WorkItemType> GetTargetWitsToValidate(List<WorkItemType> sourceWits, List<WorkItemType> targetWits)
61+
{
62+
List<WorkItemType> targetWitsToValidate = [];
63+
foreach (WorkItemType sourceWit in sourceWits)
64+
{
65+
string sourceWitName = sourceWit.Name;
66+
if (!ShouldValidateWorkItemType(sourceWitName))
67+
{
68+
continue;
69+
}
70+
string targetWitName = GetTargetWorkItemType(sourceWitName);
71+
WorkItemType targetWit = targetWits
72+
.FirstOrDefault(wit => wit.Name.Equals(targetWitName, StringComparison.OrdinalIgnoreCase));
73+
if (targetWit is not null)
74+
{
75+
targetWitsToValidate.Add(targetWit);
76+
}
77+
}
78+
return targetWitsToValidate;
79+
}
80+
81+
public bool ValidateWorkItemTypes(List<WorkItemType> sourceWits, List<WorkItemType> targetWits)
3782
{
3883
LogWorkItemTypes(sourceWits, targetWits);
3984

@@ -61,10 +106,6 @@ public bool ValidateWorkItemTypes(
61106
}
62107
else
63108
{
64-
if (!ValidateReflectedWorkItemIdField(targetWit, reflectedWorkItemIdField))
65-
{
66-
isValid = false;
67-
}
68109
if (!ValidateWorkItemTypeFields(sourceWit, targetWit))
69110
{
70111
isValid = false;
@@ -75,22 +116,6 @@ public bool ValidateWorkItemTypes(
75116
return isValid;
76117
}
77118

78-
private bool ValidateReflectedWorkItemIdField(WorkItemType targetWit, string reflectedWorkItemIdField)
79-
{
80-
if (targetWit.FieldDefinitions.Contains(reflectedWorkItemIdField))
81-
{
82-
Log.LogDebug(" '{targetWit}' contains reflected work item ID field '{fieldName}'.",
83-
targetWit.Name, reflectedWorkItemIdField);
84-
}
85-
else
86-
{
87-
Log.LogWarning(" '{targetWit}' does not contain reflected work item ID field '{fieldName}'.",
88-
targetWit.Name, reflectedWorkItemIdField);
89-
return false;
90-
}
91-
return true;
92-
}
93-
94119
private bool ValidateWorkItemTypeFields(WorkItemType sourceWit, WorkItemType targetWit)
95120
{
96121
bool result = true;
@@ -266,6 +291,21 @@ private void LogWorkItemTypes(ICollection<WorkItemType> sourceWits, ICollection<
266291
string.Join(", ", targetWits.Select(wit => wit.Name)));
267292
}
268293

294+
private void LogReflectedWorkItemIdValidationResult(bool isValid, string reflectedWorkItemIdField)
295+
{
296+
if (isValid)
297+
{
298+
Log.LogInformation("All work item types have reflected work item ID field '{reflectedWorkItemIdField}'.",
299+
reflectedWorkItemIdField);
300+
return;
301+
}
302+
303+
const string message = "Reflected work item ID field is mandatory for work item migration."
304+
+ " You can configure name of this field in target TFS endpoint settings as 'ReflectedWorkItemIdField' property."
305+
+ " Your current configured name of the field is '{reflectedWorkItemIdField}'.";
306+
Log.LogError(message, reflectedWorkItemIdField);
307+
}
308+
269309
private void LogValidationResult(bool isValid)
270310
{
271311
if (isValid)

0 commit comments

Comments
 (0)