azure-devops-migration-tools

How to Configure Migrating Closed Work Items?


I'm attempting to migrate a project from our on-prem ADOS to ADO (cloud), and succeeded, partially. It seems the Closed work items did not migrate. I've checked my config file, and I don't have the qualifier to check for ClosedDate = ''. I even specifically added a check where ClosedDate != '' in the query bit, and it still did not find the closed Work Items when I tried re-running the script.

I'm running v11.9.29.0 of the tool.

Here's my configuration file:

    {
    "Version": "11.9",
    "LogLevel": "Verbose",
    "MappingTools": [
      {
        "$type": "WorkItemTypeMappingTool",
        "Enabled": true,
        "WorkItemTypeDefinition": {
          "sourceWorkItemTypeName": "targetWorkItemTypeName"
        }
      },
      {
        "$type": "WorkItemFieldMappingTool",
        "Enabled": true,
        "WorkItemFieldMaps": [
          {
            "$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"
          },
          {
            "$type": "FieldtoFieldMapConfig",
            "WorkItemTypeName": "*",
            "sourceField": "Microsoft.VSTS.Common.BacklogPriority",
            "targetField": "Microsoft.VSTS.Common.StackRank"
          },
          {
            "$type": "FieldtoFieldMultiMapConfig",
            "WorkItemTypeName": "*",
            "SourceToTargetMappings": {
              "SourceField1": "TargetField1",
              "SourceField2": "TargetField2"
            }
          },
          {
            "$type": "FieldtoTagMapConfig",
            "WorkItemTypeName": "*",
            "sourceField": "System.State",
            "formatExpression": "ScrumState:{0}"
          },
          {
            "$type": "FieldMergeMapConfig",
            "WorkItemTypeName": "*",
            "sourceField1": "System.Description",
            "sourceField2": "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
          }
        ]
      },
      {
        "$type": "WorkItemGitRepoMappingTool",
        "Enabled": true,
        "WorkItemGitRepos": {
          "sourceRepoName": "targetRepoName"
        }
      }
    ],
    "Source": {
      "$type": "TfsTeamProjectConfig",
      "Collection": "",
      "Project": "",
      "ReflectedWorkItemIDFieldName": "TfsMigrationTool.ReflectedWorkItemId",
      "AuthenticationMode": "Prompt",
      "AllowCrossProjectLinking": false,
      "PersonalAccessToken": "",
      "LanguageMaps": {
        "AreaPath": "Area",
        "IterationPath": "Iteration"
      }
    },
    "Target": {
      "$type": "TfsTeamProjectConfig",
      "Collection": "",
      "Project": "",
      "ReflectedWorkItemIDFieldName": "ReflectedWorkItemId",
      "AuthenticationMode": "Prompt",
      "AllowCrossProjectLinking": false,
      "PersonalAccessToken": "",
      "LanguageMaps": {
        "AreaPath": "Area",
        "IterationPath": "Iteration"
      }
    },
    "Processors": [
      {
        "$type": "WorkItemMigrationConfig",
        "ReplayRevisions": true,
        "PrefixProjectToNodes": false,
        "UpdateCreatedDate": true,
        "UpdateCreatedBy": true,
        "BuildFieldTable": false,
        "AppendMigrationToolSignatureFooter": false,
        "QueryBit": "AND [Microsoft.VSTS.Common.ClosedDate] != '' AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan')",
        //"QueryBit": "AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan')",
        "OrderBit": "[System.ChangedDate] desc",
        "Enabled": true,
        "LinkMigration": true,
        "AttachmentMigration": true,
        "AttachmentWorkingPath": "c:\\temp\\WorkItemAttachmentWorkingFolder\\",
        "FixHtmlAttachmentLinks": false,
        "SkipToFinalRevisedWorkItemType": false,
        "WorkItemCreateRetryLimit": 5,
        "FilterWorkItemsThatAlreadyExistInTarget": true,
        "PauseAfterEachWorkItem": false,
        "AttachmentMaxSize": 480000000,
        "CollapseRevisions": false,
        "LinkMigrationSaveEachAsAdded": false
      },
      {
        "$type": "WorkItemTrackingProcessorOptions",
        "Enabled": false,
        "ReplayRevisions": true,
        "PrefixProjectToNodes": false,
        "CollapseRevisions": false,
        "WorkItemCreateRetryLimit": 5,
        "Enrichers": [
          {
            "$type": "PauseAfterEachItemOptions",
            "Enabled": true
          },
          {
            "$type": "FilterWorkItemsThatAlreadyExistInTargetOptions",
            "Enabled": true,
            "Query": {
              "WhereBit": "AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan')",
              "OrderBit": "[System.ChangedDate] desc"
            }
          },
          {
            "$type": "AppendMigrationToolSignatureFooterOptions",
            "Enabled": false
          },
          {
            "$type": "SkipToFinalRevisedWorkItemTypeOptions",
            "Enabled": false
          }
        ],
        "Endpoints": [
          {
            "$type": "FileSystemWorkItemEndpointOptions",
            "Direction": "Source",
            "FileStore": ".\\Store\\Source\\",
            "Query": {
              "WhereBit": "AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan')",
              "OrderBit": "[System.ChangedDate] desc"
            },
            "Enrichers": [
              {
                "$type": "FileSystemWorkItemAttachmentEnricherOptions",
                "Enabled": true,
                "AttachmentWorkingPath": "c:\\temp\\WorkItemAttachmentWorkingFolder\\",
                "AttachmentMaxSize": 480000000
              }
            ]
          },
          {
            "$type": "TfsWorkItemEndPointOptions",
            "Direction": "Target",
            "AccessToken": "",
            "Query": {
              "Query": "SELECT [System.Id], [System.Tags] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan') ORDER BY [System.ChangedDate] desc"
            },
            "Enrichers": [
              {
                "$type": "TfsWorkItemAttachmentEnricherOptions",
                "Enabled": true,
                "AttachmentWorkingPath": "c:\\temp\\WorkItemAttachmentWorkingFolder\\",
                "AttachmentMaxSize": 480000000
              },
              {
                "$type": "TfsWorkItemEmbedEnricherOptions",
                "Enabled": true,
                "AttachmentWorkingPath": "c:\\temp\\WorkItemAttachmentWorkingFolder\\"
              },
              {
                "$type": "TfsWorkItemLinkEnricherOptions",
                "Enabled": true,
                "LinkMigrationSaveEachAsAdded": true
              },
              {
                "$type": "TfsWorkItemCreatedEnricherOptions",
                "Enabled": true,
                "UpdateCreatedDate": true,
                "UpdateCreatedBy": true
              },
              {
                "$type": "TfsWorkItemFieldTableEnricherOptions",
                "Enabled": true
              }
            ]
          }
        ]
      },
      {
        "$type": "TfsAreaAndIterationProcessorOptions",
        "Enabled": true,
        "PrefixProjectToNodes": false,
        "Source": {
          "$type": "TfsEndpointOptions",
          "Direction": "Source",
          "AccessToken": "",
          "Query": {
            "Query": "SELECT [System.Id], [System.Tags] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan') ORDER BY [System.ChangedDate] desc"
          },
          "Organisation": "",
          "Project": "",
          "ReflectedWorkItemIdField": "TfsMigrationTool.ReflectedWorkItemId",
          "AuthenticationMode": "Prompt",
          "AllowCrossProjectLinking": false,
          "PersonalAccessToken": "",
          "LanguageMaps": {
            "AreaPath": "Area",
            "IterationPath": "Iteration"
          }
        },
        "Target": {
          "$type": "TfsEndpointOptions",
          "Direction": "Target",
          "AccessToken": "",
          "Query": {
            "Query": "SELECT [System.Id], [System.Tags] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan') ORDER BY [System.ChangedDate] desc"
          },
          "Organisation": "",
          "Project": "",
          "ReflectedWorkItemIdField": "ReflectedWorkItemId",
          "AuthenticationMode": "Prompt",
          "AllowCrossProjectLinking": false,
          "LanguageMaps": {
            "AreaPath": "Area",
            "IterationPath": "Iteration"
          }
        }
  
      }
  
    ]
  }

However, when running the script, I see this query in the logs:

[11:49:53 DBG] WorkItemQuery: ===========GetWorkItems=============
[11:49:53 DBG] WorkItemQuery: TeamProjectCollection: 
[11:49:53 DBG] WorkItemQuery: Query: SELECT [System.Id], [System.Tags] FROM WorkItems WHERE [System.TeamProject] = 'PROJECTNAME' AND  [Microsoft.VSTS.Common.ClosedDate] = '' AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan') ORDER BY [System.ChangedDate] desc
[11:49:53 DBG] WorkItemQuery: Paramiters: {"TeamProject": ""}
[11:49:53 DBG] WorkItemQuery: TeamProject: 
[11:50:02 INF] Replay all revisions of 96 work items?
[11:50:02 INF] Found target project as 
[11:50:02 INF] [FilterWorkItemsThatAlreadyExistInTarget] is enabled. Searching for work items that have already been migrated to the target...
[11:50:02 DBG] FilterExistingWorkItems: START |
[11:50:02 DBG] FilterByTarget: Query Execute...
[11:50:02 DBG] WorkItemQuery: ===========GetWorkItems=============
[11:50:02 DBG] WorkItemQuery: TeamProjectCollection: 
[11:50:02 DBG] WorkItemQuery: Query: SELECT [System.Id], [ReflectedWorkItemId] FROM WorkItems WHERE [System.TeamProject] = 'PROJECTNAME' AND  [Microsoft.VSTS.Common.ClosedDate] = '' AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan') ORDER BY [System.ChangedDate] desc
[11:50:02 DBG] WorkItemQuery: Paramiters: {"TeamProject": ""}
[11:50:02 DBG] WorkItemQuery: TeamProject: 
[11:51:19 DBG] FilterByTarget: ... query complete.
[11:51:19 DBG] FilterByTarget: Found 650 based on the WIQLQueryBit in the target system.

...

[11:51:20 DBG] FilterByTarget: After removing all found work items there are 0 remaining to be migrated.
[11:51:20 DBG] FilterByTarget: END
[11:51:20 INF] !! After removing all found work items there are 0 remaining to be migrated.

What do I have wrong in my config file?


Solution

  • Seems that I had the parameter name in the JSON config file wrong. It's supposed to be "WIQLQueryBit" and not just "QueryBit". I was sure I took my config from a sample documentation set, but after regenerating with the tool, it had the correct parameter name.

    In addition to that, as of v11.9.37.0 of the tool, I had to add additional mappings in the FieldValueMapConfig for System.State.

    "valueMapping": {
        "Approved": "New",
        "New": "New",
        "Committed": "Active",
        "In Progress": "Active",
        "Active": "Active",
        "To Do": "New",
        "Done": "Closed",
        "Resolved": "Resolved",
        "Closed": "Closed",
        "Removed": "Removed"
      }