Skip to content

Commit 6b0e67d

Browse files
authored
Update TfsNodeStructureTool samples and docs for new NodeMapping array format (#2753)
The `TfsNodeStructureTool` has been updated to use a new mapping format where mappings are arrays of objects with `Match` and `Replacement` properties instead of dictionary key-value pairs. This PR updates all documentation samples, configuration files, and XML comments to reflect the new format. ## Changes Made ### Configuration Format Update **Old format:** ```json "Mappings": { "Foo\\\\AAA\\\\123\\\\(.+)": "FooDest\\AAA\\$1", "Foo\\\\(.+)": "FooDest\\$1" } ``` **New format:** ```json "Mappings": [ { "Match": "Foo\\\\AAA\\\\123\\\\(.+)", "Replacement": "FooDest\\AAA\\$1" }, { "Match": "Foo\\\\(.+)", "Replacement": "FooDest\\$1" } ] ``` ### Files Updated - **Configuration files**: Updated `configuration-default.json` and `appsettings.json` to use new array format - **Source code**: Fixed XML documentation comments in `TfsNodeStructureToolOptions.cs` to show new format and corrected copy-paste error - **Generated documentation**: Regenerated all documentation using `ConsoleDataGenerator` to update samples and parameter descriptions ### Validation - All configuration files remain valid JSON - All builds complete successfully - Existing tests already use the new format, confirming backward compatibility The new format provides better structure and type safety while maintaining the same functionality for area and iteration path mapping during migrations. Fixes #2751. <!-- START COPILOT CODING AGENT TIPS --> --- 💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more [Copilot coding agent tips](https://gh.io/copilot-coding-agent-tips) in the docs.
2 parents c9587bc + 005fd96 commit 6b0e67d

8 files changed

+176
-76
lines changed

appsettings.json

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -113,13 +113,11 @@
113113
"Enabled": true,
114114
"Areas": {
115115
"Filters": [],
116-
"Mappings": {
117-
}
116+
"Mappings": []
118117
},
119118
"Iterations": {
120119
"Filters": [],
121-
"Mappings": {
122-
}
120+
"Mappings": []
123121
},
124122
"ShouldCreateMissingRevisionPaths": true,
125123
"ReplicateAllExistingNodes": true
@@ -334,19 +332,37 @@
334332
"Enabled": true,
335333
"Areas": {
336334
"Filters": [ "*\\Team 1,*\\Team 1\\**" ],
337-
"Mappings": {
338-
"^migrationSource1([\\\\]?.*)$": "MigrationTest5$1",
339-
"^Skypoint Cloud([\\\\]?.*)$": "MigrationTest5$1",
340-
"^7473924d-c47f-4089-8f5c-077c728b576e([\\\\]?.*)$": "MigrationTest5$1"
341-
}
335+
"Mappings": [
336+
{
337+
"Match": "^migrationSource1([\\\\]?.*)$",
338+
"Replacement": "MigrationTest5$1"
339+
},
340+
{
341+
"Match": "^Skypoint Cloud([\\\\]?.*)$",
342+
"Replacement": "MigrationTest5$1"
343+
},
344+
{
345+
"Match": "^7473924d-c47f-4089-8f5c-077c728b576e([\\\\]?.*)$",
346+
"Replacement": "MigrationTest5$1"
347+
}
348+
]
342349
},
343350
"Iterations": {
344351
"Filters": [ "*\\Sprint*", "*\\Sprint*\\**" ],
345-
"Mappings": {
346-
"^migrationSource1([\\\\]?.*)$": "MigrationTest5$1",
347-
"^Skypoint Cloud([\\\\]?.*)$": "MigrationTest5$1",
348-
"^7473924d-c47f-4089-8f5c-077c728b576e([\\\\]?.*)$": "MigrationTest5$1"
349-
}
352+
"Mappings": [
353+
{
354+
"Match": "^migrationSource1([\\\\]?.*)$",
355+
"Replacement": "MigrationTest5$1"
356+
},
357+
{
358+
"Match": "^Skypoint Cloud([\\\\]?.*)$",
359+
"Replacement": "MigrationTest5$1"
360+
},
361+
{
362+
"Match": "^7473924d-c47f-4089-8f5c-077c728b576e([\\\\]?.*)$",
363+
"Replacement": "MigrationTest5$1"
364+
}
365+
]
350366
},
351367
"ShouldCreateMissingRevisionPaths": true,
352368
"ReplicateAllExistingNodes": true

configuration-default.json

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -106,17 +106,29 @@
106106
"Enabled": true,
107107
"Areas": {
108108
"Filters": [ " *\\Team 1,*\\Team 1\\**" ],
109-
"Mappings": {
110-
"^Skypoint Cloud([\\\\]?.*)$": "MigrationTest5$1",
111-
"^7473924d-c47f-4089-8f5c-077c728b576e([\\\\]?.*)$": "MigrationTest5$1"
112-
}
109+
"Mappings": [
110+
{
111+
"Match": "^Skypoint Cloud([\\\\]?.*)$",
112+
"Replacement": "MigrationTest5$1"
113+
},
114+
{
115+
"Match": "^7473924d-c47f-4089-8f5c-077c728b576e([\\\\]?.*)$",
116+
"Replacement": "MigrationTest5$1"
117+
}
118+
]
113119
},
114120
"Iterations": {
115121
"Filters": [],
116-
"Mappings": {
117-
"^Skypoint Cloud([\\\\]?.*)$": "MigrationTest5$1",
118-
"^7473924d-c47f-4089-8f5c-077c728b576e([\\\\]?.*)$": "MigrationTest5$1"
119-
}
122+
"Mappings": [
123+
{
124+
"Match": "^Skypoint Cloud([\\\\]?.*)$",
125+
"Replacement": "MigrationTest5$1"
126+
},
127+
{
128+
"Match": "^7473924d-c47f-4089-8f5c-077c728b576e([\\\\]?.*)$",
129+
"Replacement": "MigrationTest5$1"
130+
}
131+
]
120132
},
121133
"ShouldCreateMissingRevisionPaths": true,
122134
"ReplicateAllExistingNodes": true

docs/_data/reference.processors.keepoutboundlinktargetprocessor.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ configurationSamples:
2020
"Enabled": false,
2121
"WIQLQuery": "Select [System.Id] From WorkItems Where [System.TeamProject] = @project and not [System.WorkItemType] contains 'Test Suite, Test Plan,Shared Steps,Shared Parameter,Feedback Request'",
2222
"TargetLinksToKeepOrganization": "https://dev.azure.com/nkdagility",
23-
"TargetLinksToKeepProject": "df1a9cb1-115a-43f2-8034-d50128fee331",
23+
"TargetLinksToKeepProject": "361b5603-dcfd-4b87-a6ba-158b4a7adb95",
2424
"CleanupFileName": "c:/temp/OutboundLinkTargets.bat",
2525
"PrependCommand": "start",
2626
"DryRun": true,

docs/_data/reference.tools.tfsnodestructuretool.yaml

Lines changed: 60 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -39,23 +39,41 @@ configurationSamples:
3939
"Filters": [
4040
"*\\Team 1,*\\Team 1\\**"
4141
],
42-
"Mappings": {
43-
"^7473924d-c47f-4089-8f5c-077c728b576e([\\\\]?.*)$": "MigrationTest5$1",
44-
"^migrationSource1([\\\\]?.*)$": "MigrationTest5$1",
45-
"^Skypoint Cloud([\\\\]?.*)$": "MigrationTest5$1"
46-
}
42+
"Mappings": [
43+
{
44+
"Match": "^migrationSource1([\\\\]?.*)$",
45+
"Replacement": "MigrationTest5$1"
46+
},
47+
{
48+
"Match": "^Skypoint Cloud([\\\\]?.*)$",
49+
"Replacement": "MigrationTest5$1"
50+
},
51+
{
52+
"Match": "^7473924d-c47f-4089-8f5c-077c728b576e([\\\\]?.*)$",
53+
"Replacement": "MigrationTest5$1"
54+
}
55+
]
4756
},
4857
"Enabled": "True",
4958
"Iterations": {
5059
"Filters": [
5160
"*\\Sprint*",
5261
"*\\Sprint*\\**"
5362
],
54-
"Mappings": {
55-
"^7473924d-c47f-4089-8f5c-077c728b576e([\\\\]?.*)$": "MigrationTest5$1",
56-
"^migrationSource1([\\\\]?.*)$": "MigrationTest5$1",
57-
"^Skypoint Cloud([\\\\]?.*)$": "MigrationTest5$1"
58-
}
63+
"Mappings": [
64+
{
65+
"Match": "^migrationSource1([\\\\]?.*)$",
66+
"Replacement": "MigrationTest5$1"
67+
},
68+
{
69+
"Match": "^Skypoint Cloud([\\\\]?.*)$",
70+
"Replacement": "MigrationTest5$1"
71+
},
72+
{
73+
"Match": "^7473924d-c47f-4089-8f5c-077c728b576e([\\\\]?.*)$",
74+
"Replacement": "MigrationTest5$1"
75+
}
76+
]
5977
},
6078
"ReplicateAllExistingNodes": "True",
6179
"ShouldCreateMissingRevisionPaths": "True"
@@ -75,22 +93,40 @@ configurationSamples:
7593
"Filters": [
7694
"*\\Team 1,*\\Team 1\\**"
7795
],
78-
"Mappings": {
79-
"^7473924d-c47f-4089-8f5c-077c728b576e([\\\\]?.*)$": "MigrationTest5$1",
80-
"^migrationSource1([\\\\]?.*)$": "MigrationTest5$1",
81-
"^Skypoint Cloud([\\\\]?.*)$": "MigrationTest5$1"
82-
}
96+
"Mappings": [
97+
{
98+
"Match": "^migrationSource1([\\\\]?.*)$",
99+
"Replacement": "MigrationTest5$1"
100+
},
101+
{
102+
"Match": "^Skypoint Cloud([\\\\]?.*)$",
103+
"Replacement": "MigrationTest5$1"
104+
},
105+
{
106+
"Match": "^7473924d-c47f-4089-8f5c-077c728b576e([\\\\]?.*)$",
107+
"Replacement": "MigrationTest5$1"
108+
}
109+
]
83110
},
84111
"Iterations": {
85112
"Filters": [
86113
"*\\Sprint*",
87114
"*\\Sprint*\\**"
88115
],
89-
"Mappings": {
90-
"^7473924d-c47f-4089-8f5c-077c728b576e([\\\\]?.*)$": "MigrationTest5$1",
91-
"^migrationSource1([\\\\]?.*)$": "MigrationTest5$1",
92-
"^Skypoint Cloud([\\\\]?.*)$": "MigrationTest5$1"
93-
}
116+
"Mappings": [
117+
{
118+
"Match": "^migrationSource1([\\\\]?.*)$",
119+
"Replacement": "MigrationTest5$1"
120+
},
121+
{
122+
"Match": "^Skypoint Cloud([\\\\]?.*)$",
123+
"Replacement": "MigrationTest5$1"
124+
},
125+
{
126+
"Match": "^7473924d-c47f-4089-8f5c-077c728b576e([\\\\]?.*)$",
127+
"Replacement": "MigrationTest5$1"
128+
}
129+
]
94130
},
95131
"ShouldCreateMissingRevisionPaths": true,
96132
"ReplicateAllExistingNodes": true
@@ -103,16 +139,16 @@ architecture:
103139
options:
104140
- parameterName: Areas
105141
type: NodeOptions
106-
description: 'Rules to apply to the Area Path. Is an object of NodeOptions e.g. { "Filters": ["*/**"], "Mappings": { "^oldProjectName([\\\\]?.*)$": "targetProjectA$1", } }'
107-
defaultValue: '{"Filters": [], "Mappings": { "^migrationSource1([\\\\]?.*)$": "MigrationTest5$1" })'
142+
description: 'Rules to apply to the Area Path. Is an object of NodeOptions e.g. { "Filters": ["*/**"], "Mappings": [{"Match": "^oldProjectName([\\\\]?.*)$", "Replacement": "targetProjectA$1"}] }'
143+
defaultValue: '{"Filters": [], "Mappings": []}'
108144
- parameterName: Enabled
109145
type: Boolean
110146
description: If set to `true` then the tool will run. Set to `false` and the processor will not run.
111147
defaultValue: missing XML code comments
112148
- parameterName: Iterations
113149
type: NodeOptions
114-
description: 'Rules to apply to the Area Path. Is an object of NodeOptions e.g. { "Filters": ["*/**"], "Mappings": { "^oldProjectName([\\\\]?.*)$": "targetProjectA$1", } }'
115-
defaultValue: '{"Filters": [], "Mappings": { "^migrationSource1([\\\\]?.*)$": "MigrationTest5$1" })'
150+
description: 'Rules to apply to the Iteration Path. Is an object of NodeOptions e.g. { "Filters": ["*/**"], "Mappings": [{"Match": "^oldProjectName([\\\\]?.*)$", "Replacement": "targetProjectA$1"}] }'
151+
defaultValue: '{"Filters": [], "Mappings": []}'
116152
- parameterName: ReplicateAllExistingNodes
117153
type: Boolean
118154
description: missing XML code comments

docs/collections/_reference/reference.fieldmaps.fieldcalculationmap.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,11 @@ categories:
109109
-
110110
topics:
111111
- topic: notes
112-
path: /docs/Reference/FieldMaps/FieldCalculationMap-notes.md
112+
path: ../../docs/Reference/FieldMaps/FieldCalculationMap-notes.md
113113
exists: false
114114
markdown: ''
115115
- topic: introduction
116-
path: /docs/Reference/FieldMaps/FieldCalculationMap-introduction.md
116+
path: ../../docs/Reference/FieldMaps/FieldCalculationMap-introduction.md
117117
exists: false
118118
markdown: ''
119119

docs/collections/_reference/reference.processors.keepoutboundlinktargetprocessor.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ configurationSamples:
2121
"Enabled": false,
2222
"WIQLQuery": "Select [System.Id] From WorkItems Where [System.TeamProject] = @project and not [System.WorkItemType] contains 'Test Suite, Test Plan,Shared Steps,Shared Parameter,Feedback Request'",
2323
"TargetLinksToKeepOrganization": "https://dev.azure.com/nkdagility",
24-
"TargetLinksToKeepProject": "df1a9cb1-115a-43f2-8034-d50128fee331",
24+
"TargetLinksToKeepProject": "361b5603-dcfd-4b87-a6ba-158b4a7adb95",
2525
"CleanupFileName": "c:/temp/OutboundLinkTargets.bat",
2626
"PrependCommand": "start",
2727
"DryRun": true,

docs/collections/_reference/reference.tools.tfsnodestructuretool.md

Lines changed: 60 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -40,23 +40,41 @@ configurationSamples:
4040
"Filters": [
4141
"*\\Team 1,*\\Team 1\\**"
4242
],
43-
"Mappings": {
44-
"^7473924d-c47f-4089-8f5c-077c728b576e([\\\\]?.*)$": "MigrationTest5$1",
45-
"^migrationSource1([\\\\]?.*)$": "MigrationTest5$1",
46-
"^Skypoint Cloud([\\\\]?.*)$": "MigrationTest5$1"
47-
}
43+
"Mappings": [
44+
{
45+
"Match": "^migrationSource1([\\\\]?.*)$",
46+
"Replacement": "MigrationTest5$1"
47+
},
48+
{
49+
"Match": "^Skypoint Cloud([\\\\]?.*)$",
50+
"Replacement": "MigrationTest5$1"
51+
},
52+
{
53+
"Match": "^7473924d-c47f-4089-8f5c-077c728b576e([\\\\]?.*)$",
54+
"Replacement": "MigrationTest5$1"
55+
}
56+
]
4857
},
4958
"Enabled": "True",
5059
"Iterations": {
5160
"Filters": [
5261
"*\\Sprint*",
5362
"*\\Sprint*\\**"
5463
],
55-
"Mappings": {
56-
"^7473924d-c47f-4089-8f5c-077c728b576e([\\\\]?.*)$": "MigrationTest5$1",
57-
"^migrationSource1([\\\\]?.*)$": "MigrationTest5$1",
58-
"^Skypoint Cloud([\\\\]?.*)$": "MigrationTest5$1"
59-
}
64+
"Mappings": [
65+
{
66+
"Match": "^migrationSource1([\\\\]?.*)$",
67+
"Replacement": "MigrationTest5$1"
68+
},
69+
{
70+
"Match": "^Skypoint Cloud([\\\\]?.*)$",
71+
"Replacement": "MigrationTest5$1"
72+
},
73+
{
74+
"Match": "^7473924d-c47f-4089-8f5c-077c728b576e([\\\\]?.*)$",
75+
"Replacement": "MigrationTest5$1"
76+
}
77+
]
6078
},
6179
"ReplicateAllExistingNodes": "True",
6280
"ShouldCreateMissingRevisionPaths": "True"
@@ -76,22 +94,40 @@ configurationSamples:
7694
"Filters": [
7795
"*\\Team 1,*\\Team 1\\**"
7896
],
79-
"Mappings": {
80-
"^7473924d-c47f-4089-8f5c-077c728b576e([\\\\]?.*)$": "MigrationTest5$1",
81-
"^migrationSource1([\\\\]?.*)$": "MigrationTest5$1",
82-
"^Skypoint Cloud([\\\\]?.*)$": "MigrationTest5$1"
83-
}
97+
"Mappings": [
98+
{
99+
"Match": "^migrationSource1([\\\\]?.*)$",
100+
"Replacement": "MigrationTest5$1"
101+
},
102+
{
103+
"Match": "^Skypoint Cloud([\\\\]?.*)$",
104+
"Replacement": "MigrationTest5$1"
105+
},
106+
{
107+
"Match": "^7473924d-c47f-4089-8f5c-077c728b576e([\\\\]?.*)$",
108+
"Replacement": "MigrationTest5$1"
109+
}
110+
]
84111
},
85112
"Iterations": {
86113
"Filters": [
87114
"*\\Sprint*",
88115
"*\\Sprint*\\**"
89116
],
90-
"Mappings": {
91-
"^7473924d-c47f-4089-8f5c-077c728b576e([\\\\]?.*)$": "MigrationTest5$1",
92-
"^migrationSource1([\\\\]?.*)$": "MigrationTest5$1",
93-
"^Skypoint Cloud([\\\\]?.*)$": "MigrationTest5$1"
94-
}
117+
"Mappings": [
118+
{
119+
"Match": "^migrationSource1([\\\\]?.*)$",
120+
"Replacement": "MigrationTest5$1"
121+
},
122+
{
123+
"Match": "^Skypoint Cloud([\\\\]?.*)$",
124+
"Replacement": "MigrationTest5$1"
125+
},
126+
{
127+
"Match": "^7473924d-c47f-4089-8f5c-077c728b576e([\\\\]?.*)$",
128+
"Replacement": "MigrationTest5$1"
129+
}
130+
]
95131
},
96132
"ShouldCreateMissingRevisionPaths": true,
97133
"ReplicateAllExistingNodes": true
@@ -104,16 +140,16 @@ architecture:
104140
options:
105141
- parameterName: Areas
106142
type: NodeOptions
107-
description: 'Rules to apply to the Area Path. Is an object of NodeOptions e.g. { "Filters": ["*/**"], "Mappings": { "^oldProjectName([\\\\]?.*)$": "targetProjectA$1", } }'
108-
defaultValue: '{"Filters": [], "Mappings": { "^migrationSource1([\\\\]?.*)$": "MigrationTest5$1" })'
143+
description: 'Rules to apply to the Area Path. Is an object of NodeOptions e.g. { "Filters": ["*/**"], "Mappings": [{"Match": "^oldProjectName([\\\\]?.*)$", "Replacement": "targetProjectA$1"}] }'
144+
defaultValue: '{"Filters": [], "Mappings": []}'
109145
- parameterName: Enabled
110146
type: Boolean
111147
description: If set to `true` then the tool will run. Set to `false` and the processor will not run.
112148
defaultValue: missing XML code comments
113149
- parameterName: Iterations
114150
type: NodeOptions
115-
description: 'Rules to apply to the Area Path. Is an object of NodeOptions e.g. { "Filters": ["*/**"], "Mappings": { "^oldProjectName([\\\\]?.*)$": "targetProjectA$1", } }'
116-
defaultValue: '{"Filters": [], "Mappings": { "^migrationSource1([\\\\]?.*)$": "MigrationTest5$1" })'
151+
description: 'Rules to apply to the Iteration Path. Is an object of NodeOptions e.g. { "Filters": ["*/**"], "Mappings": [{"Match": "^oldProjectName([\\\\]?.*)$", "Replacement": "targetProjectA$1"}] }'
152+
defaultValue: '{"Filters": [], "Mappings": []}'
117153
- parameterName: ReplicateAllExistingNodes
118154
type: Boolean
119155
description: missing XML code comments

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ namespace MigrationTools.Tools
1414
public sealed class TfsNodeStructureToolOptions : ToolOptions, ITfsNodeStructureToolOptions
1515
{
1616
/// <summary>
17-
/// Rules to apply to the Area Path. Is an object of NodeOptions e.g. { "Filters": ["*/**"], "Mappings": { "^oldProjectName([\\\\]?.*)$": "targetProjectA$1", } }
17+
/// Rules to apply to the Area Path. Is an object of NodeOptions e.g. { "Filters": ["*/**"], "Mappings": [{"Match": "^oldProjectName([\\\\]?.*)$", "Replacement": "targetProjectA$1"}] }
1818
/// </summary>
1919
/// <default>{"Filters": [], "Mappings": []}</default>
2020
public NodeOptions Areas { get; set; } = new NodeOptions();
2121

2222
/// <summary>
23-
/// Rules to apply to the Area Path. Is an object of NodeOptions e.g. { "Filters": ["*/**"], "Mappings": { "^oldProjectName([\\\\]?.*)$": "targetProjectA$1", } }
23+
/// Rules to apply to the Iteration Path. Is an object of NodeOptions e.g. { "Filters": ["*/**"], "Mappings": [{"Match": "^oldProjectName([\\\\]?.*)$", "Replacement": "targetProjectA$1"}] }
2424
/// </summary>
2525
/// <default>{"Filters": [], "Mappings": []}</default>
2626
public NodeOptions Iterations { get; set; } = new NodeOptions();

0 commit comments

Comments
 (0)