Version
Source Version
Azure DevOps Server 2022
Target Version
Azure DevOps Service
Relevant configuration
{
// …
"FieldMappingTool": {
"Enabled": true,
"FieldMaps": [
{
"FieldMapType": "FieldValueMap",
"ApplyTo": ["User Story"],
"sourceField": "System.State",
"targetField": "System.State",
"defaultValue": "New",
"valueMapping": {
"New": "New",
"Active": "Committed",
"Resolved": "Done",
"Closed": "Done",
"Removed": "Removed"
}
}
}
}
Relevant log output
[INF] [16.3.3] Start validation of work item type 'User Story'.
[INF] [16.3.3] Work item type 'User Story' is mapped to 'Product Backlog Item'.
[INF] [16.3.3] Validating source field 'System.State' (State).
[INF] [16.3.3] Missing values are: 'Active', 'Closed', 'Resolved'
[WRN] [16.3.3] Source field 'System.State' and target field 'System.State' have different allowed values.
[INF] [16.3.3] Source allowed values: 'Active', 'Closed', 'New', 'Removed', 'Resolved'
[INF] [16.3.3] Target allowed values: 'Approved', 'Committed', 'Done', 'New', 'Removed'
[INF] [16.3.3] Missing values in target are: 'Active', 'Closed', 'Resolved'
What happened?
I’m currently working on a migration where I’m moving from the agile process to the scrum process, so I have to change the work item type during the migration. While testing out my configuration, I noticed some inconsistent behavior in the field mapping that caused my migration to fail.
As you can see from the configuration, I have a field value mapping for System.State for the work item type User Story, which I map to the work item type Product Backlog Item.
This is the correct way to configure this, because the field mapping tool uses the work item type of the source element when looking up the field mappings:
|
public void ApplyFieldMappings(WorkItemData source, WorkItemData target) |
|
=> ProcessFieldMapList(source, target, GetFieldMappings(source.Fields["System.WorkItemType"].Value.ToString())); |
However, when running this, I still get an error that there are missing values in the target type. While browsing the source code to figure out what is wrong, I noticed the validator had been extended in #3010 to support the configured field value mappings but for some reason it was not respecting my configuration.
After going deeper into the code, I realized that while the field mapping itself uses the source work item type, the work item type validator uses the target work item type instead:
|
fieldResult = ValidateField(sourceField, fieldPair.TargetField, targetWit.Name, logLevel); |
|
Log.LogDebug(" Allowed values in target field do not match allowed values in source. Checking field value maps."); |
|
LogAllowedValues(" Missing values are: {missingValues}", missingValues); |
|
List<string> mappedValues = []; |
|
Dictionary<string, string> valueMaps = _commonTools.FieldMappingTool |
|
.GetFieldValueMappings(targetWitName, sourceFieldReferenceName, targetFieldReferenceName); |
|
foreach (string missingValue in missingValues) |
|
{ |
|
if (valueMaps.TryGetValue(missingValue, out string mappedValue)) |
|
{ |
After realizing that, I extended my field value map configuration to also apply to Product Backlog Item (in addition to User Story), and the validation and the migration works as expected.
In my case, this is not an issue since I have a limited set of data for which I do not need more control over the work item types. But I can imagine that this could be a problem where you do not want to have a single state mapping for the target type because you might have multiple source work item types map to the same target type, requiring you to use different mappings.
So I would suggest to unify this behavior and change the work item type validator to also respect the field mappings of the source type.
Debug in Visual Studio
Version
Source Version
Azure DevOps Server 2022
Target Version
Azure DevOps Service
Relevant configuration
{ // … "FieldMappingTool": { "Enabled": true, "FieldMaps": [ { "FieldMapType": "FieldValueMap", "ApplyTo": ["User Story"], "sourceField": "System.State", "targetField": "System.State", "defaultValue": "New", "valueMapping": { "New": "New", "Active": "Committed", "Resolved": "Done", "Closed": "Done", "Removed": "Removed" } } } }Relevant log output
What happened?
I’m currently working on a migration where I’m moving from the agile process to the scrum process, so I have to change the work item type during the migration. While testing out my configuration, I noticed some inconsistent behavior in the field mapping that caused my migration to fail.
As you can see from the configuration, I have a field value mapping for
System.Statefor the work item typeUser Story, which I map to the work item typeProduct Backlog Item.This is the correct way to configure this, because the field mapping tool uses the work item type of the source element when looking up the field mappings:
azure-devops-migration-tools/src/MigrationTools/Tools/FieldMappingTool.cs
Lines 88 to 89 in f0f1523
However, when running this, I still get an error that there are missing values in the target type. While browsing the source code to figure out what is wrong, I noticed the validator had been extended in #3010 to support the configured field value mappings but for some reason it was not respecting my configuration.
After going deeper into the code, I realized that while the field mapping itself uses the source work item type, the work item type validator uses the target work item type instead:
azure-devops-migration-tools/src/MigrationTools.Clients.TfsObjectModel/Tools/TfsWorkItemTypeValidatorTool.cs
Line 208 in f0f1523
azure-devops-migration-tools/src/MigrationTools.Clients.TfsObjectModel/Tools/TfsWorkItemTypeValidatorTool.cs
Lines 364 to 372 in f0f1523
After realizing that, I extended my field value map configuration to also apply to
Product Backlog Item(in addition toUser Story), and the validation and the migration works as expected.In my case, this is not an issue since I have a limited set of data for which I do not need more control over the work item types. But I can imagine that this could be a problem where you do not want to have a single state mapping for the target type because you might have multiple source work item types map to the same target type, requiring you to use different mappings.
So I would suggest to unify this behavior and change the work item type validator to also respect the field mappings of the source type.
Debug in Visual Studio