Getting Started
Article
5 minutes to read
2023-05-17 09:40:31 -0500
If you want to perform a bulk edit or a migration then you need to start here. This tool has been tested on updating from 100 to 250,000 work items by its users.
Watch the Video Overview to get you started in 30 minutes. This tool is complicated and it’s not always easy to discover what you need to do.
Install
In order to run the migration you will need to install the tools first.
- Install Chocolatey from https://chocolatey.org/install
- Run
choco install vsts-sync-migrator
to install the tools source
The tools are now installed. To run them you will need to switch to c:\tools\MigrationTools\
and run migration.exe
.
Upgrade
- Run
choco upgrade vsts-sync-migrator
to upgrade the tools source
Server configuration and setup
Follow the setup instructions to make sure that you can run the tool against your environments and importantly add the required custom field ‘ReflectedWorkItemId’
Create a default configuration file
- Open a command prompt or PowerShell window at
C:\tools\MigrationTools\
- Run
./migration.exe init
to create a default configuration - Open
configuration.json
from the current directory
You can now customise the configuration depending on what you need to do. However a basic config that you can use to migrate from one team project to another with the same process template is:
{
"ChangeSetMappingFile": null,
"Source": {
"$type": "TfsTeamProjectConfig",
"Collection": "https://dev.azure.com/nkdagility-preview/",
"Project": "myProjectName",
"ReflectedWorkItemIDFieldName": "Custom.ReflectedWorkItemId",
"AllowCrossProjectLinking": false,
"AuthenticationMode": "Prompt",
"PersonalAccessToken": "",
"PersonalAccessTokenVariableName": "",
"LanguageMaps": {
"AreaPath": "Area",
"IterationPath": "Iteration"
}
},
"Target": {
"$type": "TfsTeamProjectConfig",
"Collection": "https://dev.azure.com/nkdagility-preview/",
"Project": "myProjectName",
"ReflectedWorkItemIDFieldName": "Custom.ReflectedWorkItemId",
"AllowCrossProjectLinking": false,
"AuthenticationMode": "Prompt",
"PersonalAccessToken": "",
"PersonalAccessTokenVariableName": "",
"LanguageMaps": {
"AreaPath": "Area",
"IterationPath": "Iteration"
}
},
"FieldMaps": [
{
"$type": "MultiValueConditionalMapConfig",
"WorkItemTypeName": "*",
"sourceFieldsAndValues": {
"Field1": "Value1",
"Field2": "Value2"
},
"targetFieldsAndValues": {
"Field1": "Value1",
"Field2": "Value2"
}
},
{
"$type": "FieldBlankMapConfig",
"WorkItemTypeName": "*",
"targetField": "TfsMigrationTool.ReflectedWorkItemId"
},
{
"$type": "FieldValueMapConfig",
"WorkItemTypeName": "*",
"sourceField": "System.State",
"targetField": "System.State",
"defaultValue": "New",
"valueMapping": {
"Approved": "New",
"New": "New",
"Committed": "Active",
"In Progress": "Active",
"To Do": "New",
"Done": "Closed",
"Removed": "Removed"
}
},
{
"$type": "FieldtoFieldMapConfig",
"WorkItemTypeName": "*",
"sourceField": "Microsoft.VSTS.Common.BacklogPriority",
"targetField": "Microsoft.VSTS.Common.StackRank",
"defaultValue": null
},
{
"$type": "FieldtoFieldMultiMapConfig",
"WorkItemTypeName": "*",
"SourceToTargetMappings": {
"SourceField1": "TargetField1",
"SourceField2": "TargetField2"
}
},
{
"$type": "FieldtoTagMapConfig",
"WorkItemTypeName": "*",
"sourceField": "System.State",
"formatExpression": "ScrumState:{0}"
},
{
"$type": "FieldMergeMapConfig",
"WorkItemTypeName": "*",
"sourceFields": [
"System.Description",
"Microsoft.VSTS.Common.AcceptanceCriteria"
],
"targetField": "System.Description",
"formatExpression": "{0} <br/><br/><h3>Acceptance Criteria</h3>{1}",
"doneMatch": "##DONE##"
},
{
"$type": "RegexFieldMapConfig",
"WorkItemTypeName": "*",
"sourceField": "COMPANY.PRODUCT.Release",
"targetField": "COMPANY.DEVISION.MinorReleaseVersion",
"pattern": "PRODUCT \\d{4}.(\\d{1})",
"replacement": "$1"
},
{
"$type": "FieldValuetoTagMapConfig",
"WorkItemTypeName": "*",
"sourceField": "Microsoft.VSTS.CMMI.Blocked",
"pattern": "Yes",
"formatExpression": "{0}"
},
{
"$type": "TreeToTagMapConfig",
"WorkItemTypeName": "*",
"toSkip": 3,
"timeTravel": 1
}
],
"GitRepoMapping": null,
"LogLevel": "Information",
"CommonEnrichersConfig": null,
"Processors": [
{
"$type": "WorkItemMigrationConfig",
"Enabled": false,
"ReplayRevisions": true,
"PrefixProjectToNodes": false,
"UpdateCreatedDate": true,
"UpdateCreatedBy": true,
"WIQLQueryBit": "AND [Microsoft.VSTS.Common.ClosedDate] = '' AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan','Shared Steps','Shared Parameter','Feedback Request')",
"WIQLOrderBit": "[System.ChangedDate] desc",
"LinkMigration": true,
"AttachmentMigration": true,
"AttachmentWorkingPath": "c:\\temp\\WorkItemAttachmentWorkingFolder\\",
"FixHtmlAttachmentLinks": false,
"SkipToFinalRevisedWorkItemType": true,
"WorkItemCreateRetryLimit": 5,
"FilterWorkItemsThatAlreadyExistInTarget": true,
"PauseAfterEachWorkItem": false,
"AttachmentMaxSize": 480000000,
"AttachRevisionHistory": false,
"LinkMigrationSaveEachAsAdded": false,
"GenerateMigrationComment": true,
"WorkItemIDs": null,
"MaxRevisions": 0,
"NodeStructureEnricherEnabled": null,
"UseCommonNodeStructureEnricherConfig": false,
"StopMigrationOnMissingAreaIterationNodes": true,
"NodeBasePaths": [
"Product\\Area\\Path1",
"Product\\Area\\Path2"
],
"AreaMaps": {},
"IterationMaps": {},
"MaxGracefulFailures": 0,
"SkipRevisionWithInvalidIterationPath": false
}
],
"Version": "0.0",
"workaroundForQuerySOAPBugEnabled": false,
"WorkItemTypeDefinition": {
"sourceWorkItemTypeName": "targetWorkItemTypeName"
},
"Endpoints": {
"InMemoryWorkItemEndpoints": [
{
"Name": "Source",
"EndpointEnrichers": null
},
{
"Name": "Target",
"EndpointEnrichers": null
}
]
}
}
The default WorkItemMigrationConfig processor will perform the following operations:
- Migrate interations and sprints
- Attachments
- Links including for source code. Optionally clone the repositories before starting the migration to have links maintained on the initial pass.
How to execute configuration.json with minimal adjustments
Remember to add custom field ‘ReflectedWorkItemId’ to only the target team project before starting migration!
[NOTE!] In older version of the tool we updated the Source work items with a link back to the Target to make migration easier. This has been removed and replaced with the
FilterWorkItemsThatAlreadyExistInTarget
option insead. You do not need to add the reflected work item ID custom field to the Source environment.
- Adjust the value of the
Collection
attribute for Source and Target - Adjust the value of the
Project
attribute for Source and Target -
Set the
AuthenticationMode
(Prompt
orAccessToken
) for Source and TargetIf you set Authentication mode to
AccessToken
, enter a valid PAT as value for thePersonalAccessToken
attribute, or set thePersonalAccessTokenVariableName
to the name of an environment variable containing your PAT. -
Adjust the value of the
ReflectedWorkItemIDFieldName
attribute (field name of the migration tracking field) for Source and TargetFor example:
TfsMigrationTool.ReflectedWorkItemId
for TFS,ReflectedWorkItemId
for VSTS orCustom.ReflectedWorkItemId
for Azure DevOps - Enable the
WorkItemMigrationConfig
processor by settingEnabled
totrue
- [OPTIONAL] Modify the
WIQLQueryBit
to migrate only the work items you want. The default WIQL will migrate all open work items and revisions excluding test suites and plans - Adjust the
NodeBasePaths
or leave empty to migrate all nodes - From the
C:\tools\MigrationTools\
path run.\migration.exe execute --config .\configuration.json
Remember: if you want a processor to run, it’s Enabled
attribute must be set to true
.
Refer to the Reference Guide for more details.