Version
Source Version
Azure DevOps Service
Target Version
Azure DevOps Service
Relevant configuration
Relevant log output
What happened?
While troubleshooting user mappings I found what appears to be a discrepancy between the documented mapping formats, the data contracts defined in the codebase, and the format actually consumed by TfsUserMappingTool.
After tracing the execution path and reviewing both the documentation and the source code, I found at least three different mapping models being described, while the implementation appears to expect something else entirely.
1. Tool Reference Documentation
The reference documentation for TfsUserMappingTool describes a Source/Target mapping structure and indicates that the user mapping file should contain an array of mappings:
user-mapping-file-format
This suggests a structure conceptually similar to:
[
{
"source": "...",
"target": "..."
}
]
2. User Mapping How-To
The mapping How-To documents a different and richer format:
https://devopsmigration.io/docs/how-to/user-mappings/
Example:
[
{
"Source": {
"FriendlyName": "...",
"AccountName": "..."
},
"Target": {
"FriendlyName": "...",
"AccountName": "..."
}
}
]
This is also an array, but the payload structure is significantly different from the one described in the tool reference.
3. Identity Data Contract
The codebase contains an identity contract which appears to describe yet another model:
https://github.com/nkdAgility/azure-devops-migration-tools/blob/main/src/MigrationTools/DataContracts/IdentityItemData.cs
Notably, the contract appears to use fields such as DisplayName instead of FriendlyName, and contains additional properties that are not documented in either of the previous examples.
4. Actual Implementation
After tracing the execution path into the tool implementation:
https://github.com/nkdAgility/azure-devops-migration-tools/blob/main/src/MigrationTools.Clients.TfsObjectModel/Tools/TfsUserMappingTool.cs#L55
it appears that the mapping file is ultimately deserialized into a structure compatible with:
Dictionary<string,string>
As a result, none of the documented examples above appear to be consumed correctly.
In my testing, the implementation only worked when the mapping file was represented as a single dictionary object.
Conceptually:
{
"sourceUser@old.com": "targetUser@new.com"
}
rather than any of the documented array-based formats.
Expected Behavior
Documentation, data contracts, examples and implementation should describe and process the same mapping format.
At minimum, the expected format should be clearly documented and accepted by the implementation.
Actual Behavior
Currently there appear to be four different representations of user mappings:
- Tool Reference Documentation
- User Mapping How-To
- IdentityItemData
- TfsUserMappingTool implementation
and they do not appear to be compatible with each other.
This makes troubleshooting user mappings unnecessarily difficult and can easily lead users to generate mapping files that look correct according to the documentation but are silently ignored or interpreted incorrectly by the tool.
Debug in Visual Studio
Version
Source Version
Azure DevOps Service
Target Version
Azure DevOps Service
Relevant configuration
Relevant log output
What happened?
While troubleshooting user mappings I found what appears to be a discrepancy between the documented mapping formats, the data contracts defined in the codebase, and the format actually consumed by TfsUserMappingTool.
After tracing the execution path and reviewing both the documentation and the source code, I found at least three different mapping models being described, while the implementation appears to expect something else entirely.
1. Tool Reference Documentation
The reference documentation for TfsUserMappingTool describes a Source/Target mapping structure and indicates that the user mapping file should contain an array of mappings:
user-mapping-file-format
This suggests a structure conceptually similar to:
2. User Mapping How-To
The mapping How-To documents a different and richer format:
https://devopsmigration.io/docs/how-to/user-mappings/
Example:
This is also an array, but the payload structure is significantly different from the one described in the tool reference.
3. Identity Data Contract
The codebase contains an identity contract which appears to describe yet another model:
https://github.com/nkdAgility/azure-devops-migration-tools/blob/main/src/MigrationTools/DataContracts/IdentityItemData.cs
Notably, the contract appears to use fields such as
DisplayNameinstead ofFriendlyName, and contains additional properties that are not documented in either of the previous examples.4. Actual Implementation
After tracing the execution path into the tool implementation:
https://github.com/nkdAgility/azure-devops-migration-tools/blob/main/src/MigrationTools.Clients.TfsObjectModel/Tools/TfsUserMappingTool.cs#L55
it appears that the mapping file is ultimately deserialized into a structure compatible with:
Dictionary<string,string>As a result, none of the documented examples above appear to be consumed correctly.
In my testing, the implementation only worked when the mapping file was represented as a single dictionary object.
Conceptually:
rather than any of the documented array-based formats.
Expected Behavior
Documentation, data contracts, examples and implementation should describe and process the same mapping format.
At minimum, the expected format should be clearly documented and accepted by the implementation.
Actual Behavior
Currently there appear to be four different representations of user mappings:
and they do not appear to be compatible with each other.
This makes troubleshooting user mappings unnecessarily difficult and can easily lead users to generate mapping files that look correct according to the documentation but are silently ignored or interpreted incorrectly by the tool.
Debug in Visual Studio