diff --git a/.github/workflows/ado-migration-process-full.yml b/.github/workflows/ado-migration-process-full.yml index 00a880c..8a9f685 100644 --- a/.github/workflows/ado-migration-process-full.yml +++ b/.github/workflows/ado-migration-process-full.yml @@ -46,11 +46,11 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 - - name: Clean Azure DevOps Migration Tools Log Directory + - name: Clean Azure DevOps Migration Tools Log and Attachments Directory shell: pwsh run: | Get-ChildItem "${{ vars.WorkItemMigratorDirectory }}/logs" -Recurse | Remove-Item -Recurse - + Get-ChildItem "${{ vars.WorkItemMigratorDirectory }}\\WorkItemAttachmentWorkingFolder" -Recurse | Remove-Item -Recurse - name: Set Migration Configuration shell: pwsh run: | diff --git a/.github/workflows/ado-migration-process-partial.yml b/.github/workflows/ado-migration-process-partial.yml index d15674b..7957286 100644 --- a/.github/workflows/ado-migration-process-partial.yml +++ b/.github/workflows/ado-migration-process-partial.yml @@ -74,10 +74,11 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 - - name: Clean Azure DevOps Migration Tools Log Directory + - name: Clean Azure DevOps Migration Tools Log and Attachments Directory shell: pwsh run: | Get-ChildItem "${{ vars.WorkItemMigratorDirectory }}/logs" -Recurse | Remove-Item -Recurse + Get-ChildItem "${{ vars.WorkItemMigratorDirectory }}\\WorkItemAttachmentWorkingFolder" -Recurse | Remove-Item -Recurse - name: Set Migration Configuration shell: pwsh @@ -166,7 +167,7 @@ jobs: } "Wikis" { & .\MigrateProject.ps1 -SkipMigrateWikis $WhatIf } - "Work Item Querys" + "Work Item Queries" { & .\MigrateProject.ps1 -SkipMigrateWorkItemQuerys $WhatIf } "Work-Items (Including 'Test Cases')" { & .\Step_3_Migrate_Project.ps1 -WhatIf $WhatIf} diff --git a/.github/workflows/ado-migration-process-workitem-backfill-between.yml b/.github/workflows/ado-migration-process-workitem-backfill-between.yml index a1458ce..68880c5 100644 --- a/.github/workflows/ado-migration-process-workitem-backfill-between.yml +++ b/.github/workflows/ado-migration-process-workitem-backfill-between.yml @@ -1,4 +1,4 @@ -name: sBetween Dates Work Item Backfill ADO Project Migration +name: Between Dates Work Item Backfill ADO Project Migration on: workflow_dispatch: # Allows manual triggering via the GitHub Actions UI @@ -83,10 +83,11 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 - - name: Clean Azure DevOps Migration Tools Log Directory + - name: Clean Azure DevOps Migration Tools Log and Attachments Directory shell: pwsh run: | Get-ChildItem "${{ vars.WorkItemMigratorDirectory }}/logs" -Recurse | Remove-Item -Recurse + Get-ChildItem "${{ vars.WorkItemMigratorDirectory }}\\WorkItemAttachmentWorkingFolder" -Recurse | Remove-Item -Recurse - name: Set Migration Configuration shell: pwsh @@ -157,6 +158,9 @@ jobs: $WhatIf = $whatIfDryRun -match "true" if($isDateStart -and $isDateEnd) { + if($startDate -eq $endDate){ + $startDate = $startDate.addDays(-1) + } $startDateString = $startDate.ToString($format) $endDateString = $endDate.ToString($format) & .\Work-Item-Backfill_Migrate_Project.ps1 -StartDate $startDateString -EndDate -endDateString -ItemType $selection -WhatIf $WhatIf diff --git a/.github/workflows/ado-migration-process-workitem-backfill.yml b/.github/workflows/ado-migration-process-workitem-backfill.yml index 1e38f2e..331c435 100644 --- a/.github/workflows/ado-migration-process-workitem-backfill.yml +++ b/.github/workflows/ado-migration-process-workitem-backfill.yml @@ -79,10 +79,11 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 - - name: Clean Azure DevOps Migration Tools Log Directory + - name: Clean Azure DevOps Migration Tools Log and Attachments Directory shell: pwsh run: | Get-ChildItem "${{ vars.WorkItemMigratorDirectory }}/logs" -Recurse | Remove-Item -Recurse + Get-ChildItem "${{ vars.WorkItemMigratorDirectory }}\\WorkItemAttachmentWorkingFolder" -Recurse | Remove-Item -Recurse - name: Set Migration Configuration shell: pwsh @@ -138,4 +139,4 @@ jobs: uses: actions/upload-artifact@v3 with: name: migration-run-logs - path: "./Projects" \ No newline at end of file + path: "./Projects" diff --git a/admin-tools/readme.md b/admin-tools/admin-tools-about.md similarity index 99% rename from admin-tools/readme.md rename to admin-tools/admin-tools-about.md index dfd68b4..22faf96 100644 --- a/admin-tools/readme.md +++ b/admin-tools/admin-tools-about.md @@ -1,4 +1,4 @@ -#Project and Process Tools +# Project and Process Tools PowerShell scripts used to list process templates, projects, retrieve custom fields and custom lists from an existing TFS XML based process definition diff --git a/configuration/migrator-configuration.json b/configuration/migrator-configuration.json index 3a8be6a..c3676d7 100644 --- a/configuration/migrator-configuration.json +++ b/configuration/migrator-configuration.json @@ -1,375 +1,387 @@ { - "Version": "0.0", - "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": "FieldSkipMapConfig", - "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" - }, - { - "$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}

Acceptance Criteria

{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}" + "Serilog": { + "MinimumLevel": "Debug" + }, + "MigrationTools": { + "Version": "16.0", + "Endpoints": { + "ProjectSource": { + "EndpointType": "TfsTeamProjectEndpoint", + "Collection": "https://dev.azure.com/AIZ-GL/", + "Project": "GL.CL-Elita", + "Authentication": { + "AccessToken": "", + "AuthenticationMode": "AccessToken" }, - { - "$type": "TreeToTagMapConfig", - "WorkItemTypeName": "*", - "toSkip": 3, - "timeTravel": 1 + + "ReflectedWorkItemIdField": "Custom.ReflectedWorkItemId", + "LanguageMaps": { + "AreaPath": "Area", + "IterationPath": "Iteration" } - ] - }, - { - "$type": "WorkItemGitRepoMappingTool", - "Enabled": true, - "WorkItemGitRepos": { - "sourceRepoName": "targetRepoName" - } - } - ], - "Endpoints": { - "TfsWorkItemEndpoints": [ - { - "Name": "WorkItemSource", - "AccessToken": null, - "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", - "Parameters": { - "TeamProject": "Sample-Project" - } + }, + "ProjectTarget": { + "EndpointType": "TfsTeamProjectEndpoint", + "Collection": "https://dev.azure.com/AIZ-Global/", + "Project": "GL.CL-Elita-migrated", + "Authentication": { + "AccessToken": "", + "AuthenticationMode": "AccessToken" }, - "Organisation": "https://dev.azure.com/Source-Org/", - "Project": "Sample-Project", "ReflectedWorkItemIdField": "Custom.ReflectedWorkItemId", - "AllowCrossProjectLinking": false, - "PersonalAccessToken": null, "LanguageMaps": { "AreaPath": "Area", "IterationPath": "Iteration" } }, - { - "Name": "WorkItemTarget", - "AccessToken": null, - "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" + "WorkItemSource": { + "EndpointType": "TfsWorkItemEndpoint", + "Collection": "https://dev.azure.com/AIZ-GL/", + "Project": "GL.CL-Elita", + "Authentication": { + "AccessToken": "", + "AuthenticationMode": "AccessToken" }, - "Organisation": "https://dev.azure.com/Target-Org/", - "Project": "Sample-Project-migrated", + "ReflectedWorkItemIdField": "Custom.ReflectedWorkItemId", - "AllowCrossProjectLinking": false, - "PersonalAccessToken": null, "LanguageMaps": { "AreaPath": "Area", "IterationPath": "Iteration" } - } - ], - "TfsTeamSettingsEndpoints": [ - { - "$type": "TfsTeamSettingsEndpointOptions", - "Name": "TeamSettingsSource", - "Direction": "Source", - "Organisation": "https://dev.azure.com/Source-Org/", - "Project": "Sample-Project", - "AccessToken": null, - "ReflectedWorkItemIdField": "Custom.ReflectedItemId", + }, + "WorkItemTarget": { + "EndpointType": "TfsWorkItemEndpoint", + "Collection": "https://dev.azure.com/AIZ-Global/", + "Project": "GL.CL-Elita-migrated", + "Authentication": { + "AccessToken": "", + "AuthenticationMode": "AccessToken" + }, + "ReflectedWorkItemIdField": "Custom.ReflectedWorkItemId", "LanguageMaps": { - "$type": "TfsLanguageMapOptions", "AreaPath": "Area", "IterationPath": "Iteration" - }, - "EndpointEnrichers": null + } }, - { - "$type": "TfsTeamSettingsEndpointOptions", - "Name": "TeamSettingsTarget", - "Direction": "Target", - "Organisation": "https://dev.azure.com/Target-Org/", - "Project": "Sample-Project-migrated", - "AccessToken": null, - "ReflectedWorkItemIdField": "Custom.ReflectedItemId", + "TeamSettingsSource": { + "EndpointType": "TfsTeamSettingsEndpoint", + "Collection": "https://dev.azure.com/AIZ-GL/", + "Project": "GL.CL-Elita", + "Authentication": { + "AccessToken": "", + "AuthenticationMode": "AccessToken" + }, + + "ReflectedWorkItemIdField": "Custom.ReflectedWorkItemId", "LanguageMaps": { - "$type": "TfsLanguageMapOptions", "AreaPath": "Area", "IterationPath": "Iteration" + } + }, + "TeamSettingsTarget": { + "EndpointType": "TfsTeamSettingsEndpoint", + "Collection": "https://dev.azure.com/AIZ-Global/", + "Project": "GL.CL-Elita-migrated", + "Authentication": { + "AccessToken": "", + "AuthenticationMode": "AccessToken" }, - "EndpointEnrichers": null - } - ], - "TfsEndpoints": [ - { - "Name": "tfsSource", - "Organisation": "https://dev.azure.com/Source-Org/", - "Project": "Sample-Project", - "AuthenticationMode": "AccessToken", - "AccessToken": null, "ReflectedWorkItemIdField": "Custom.ReflectedWorkItemId", "LanguageMaps": { "AreaPath": "Area", "IterationPath": "Iteration" + } + }, + "TfsSource":{ + "EndpointType": "TfsEndpoint", + "Collection": "https://dev.azure.com/AIZ-GL/", + "Project": "GL.CL-Elita", + "Authentication": { + "AccessToken": "", + "AuthenticationMode": "AccessToken" }, - "EndpointEnrichers": null + + "ReflectedWorkItemIdField": "Custom.ReflectedWorkItemId", + "LanguageMaps": { + "AreaPath": "Area", + "IterationPath": "Iteration" + } }, - { - "Name": "tfsTarget", - "Organisation": "https://dev.azure.com/Target-Org/", - "Project": "Sample-Project-migrated", - "AuthenticationMode": "AccessToken", - "AccessToken": null, + "TfsTarget":{ + "EndpointType": "TfsEndpoint", + "Collection": "https://dev.azure.com/AIZ-Global/", + "Project": "GL.CL-Elita-migrated", + "Authentication": { + "AccessToken": "", + "AuthenticationMode": "AccessToken" + }, "ReflectedWorkItemIdField": "Custom.ReflectedWorkItemId", "LanguageMaps": { "AreaPath": "Area", "IterationPath": "Iteration" + } + }, + "PipelineSource":{ + "EndpointType": "AzureDevOpsEndpoint", + "Collection": "https://dev.azure.com/AIZ-GL/", + "Project": "GL.CL-Elita", + "Authentication": { + "AccessToken": "", + "AuthenticationMode": "AccessToken" }, - "EndpointEnrichers": null + + "ReflectedWorkItemIdField": null, + "LanguageMaps": { + "AreaPath": "Area", + "IterationPath": "Iteration" + } + }, + "PipelineTarget":{ + "EndpointType": "AzureDevOpsEndpoint", + "Collection": "https://dev.azure.com/AIZ-Global/", + "Project": "GL.CL-Elita-migrated", + "Authentication": { + "AccessToken": "", + "AuthenticationMode": "AccessToken" + }, + "ReflectedWorkItemIdField": null, + "LanguageMaps": { + "AreaPath": "Area", + "IterationPath": "Iteration" + } } - ], - "AzureDevOpsEndpoints": [ + }, + "Processors": [ + { + "ProcessorType": "TfsTeamSettingsProcessor", + "Enabled": false, + "MigrateTeamSettings": true, + "UpdateTeamSettings": false, + "PrefixProjectToNodes": false, + "MigrateTeamCapacities": false, + "Teams": null, + "UseUserMapping": false, + "SourceName": "TeamSettingsSource", + "TargetName": "TeamSettingsTarget" + }, { - "name": "PipelineSource", - "$type": "AzureDevOpsEndpointOptions", - "Organisation": "https://dev.azure.com/Source-Org/", - "Project": "Sample-Project", - "AuthenticationMode": "AccessToken", - "AccessToken": null, - "EndpointEnrichers": null + "ProcessorType": "TfsTestVariablesMigrationProcessor", + "Enabled": false, + "Processor": "TestVariablesMigrationContext", + "SourceName": "ProjectSource", + "TargetName": "ProjectTarget" }, { - "Name": "PipelineTarget", - "$type": "AzureDevOpsEndpointOptions", - "Organisation": "https://dev.azure.com/Target-Org/", - "Project": "Sample-Project-migrated", - "AuthenticationMode": "AccessToken", - "AccessToken": null, - "EndpointEnrichers": null + "ProcessorType": "TfsTestConfigurationsMigrationProcessor", + "Enabled": false, + "SourceName": "ProjectSource", + "TargetName": "ProjectTarget" + }, + { + "ProcessorType": "TfsTestPlansAndSuitesMigrationProcessor", + "Enabled": false, + "OnlyElementsWithTag": "", + "TestPlanQuery": null, + "RemoveAllLinks": false, + "MigrationDelay": 0, + "RemoveInvalidTestSuiteLinks": false, + "FilterCompleted": false, + "SourceName": "ProjectSource", + "TargetName": "ProjectTarget" + }, + { + "ProcessorType": "TfsSharedQueryProcessor", + "Enabled": false, + "PrefixProjectToNodes": false, + "SharedFolderName": "Shared Queries", + "SourceToTargetFieldMappings": null, + "SourceName": "TfsSource", + "TargetName": "TfsTarget" + }, + { + "ProcessorType": "AzureDevOpsPipelineProcessor", + "Enabled": false, + "MigrateBuildPipelines": false, + "MigrateReleasePipelines": false, + "MigrateTaskGroups": false, + "MigrateVariableGroups": false, + "MigrateServiceConnections": false, + "BuildPipelines": null, + "ReleasePipelines": null, + "RepositoryNameMaps": {}, + "SourceName": "PipelineSource", + "TargetName": "PipelineTarget" + }, + { + "ProcessorType": "TfsWorkItemMigrationProcessor", + "Enabled": false, + "UpdateCreatedDate": true, + "UpdateCreatedBy": true, + "AttachRevisionHistory": true, + "WIQLQuery": "SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') ORDER BY [System.ChangedDate] DESC", + "FixHtmlAttachmentLinks": true, + "WorkItemCreateRetryLimit": 5, + "FilterWorkItemsThatAlreadyExistInTarget": false, + "GenerateMigrationComment": true, + "SkipRevisionWithInvalidIterationPath": true, + "SkipRevisionWithInvalidAreaPath": true, + "MaxGracefulFailures": 0, + "PauseAfterEachWorkItem": false, + "WorkItemIDs": null, + "SourceName": "ProjectSource", + "TargetName": "ProjectTarget" } - ] - }, - "Source": { - "$type": "TfsTeamProjectConfig", - "Collection": "https://dev.azure.com/Source-Org/", - "Project": "Sample-Project", - "ReflectedWorkItemIDFieldName": "Custom.ReflectedWorkItemId", - "AuthenticationMode": "AccessToken", - "AllowCrossProjectLinking": false, - "PersonalAccessToken": null, - "LanguageMaps": { - "AreaPath": "Area", - "IterationPath": "Iteration" - } - }, - "Target": { - "$type": "TfsTeamProjectConfig", - "Collection": "https://dev.azure.com/Target-Org/", - "Project": "Sample-Project-migrated", - "ReflectedWorkItemIDFieldName": "Custom.ReflectedWorkItemId", - "AuthenticationMode": "AccessToken", - "AllowCrossProjectLinking": false, - "PersonalAccessToken": null, - "LanguageMaps": { - "AreaPath": "Area", - "IterationPath": "Iteration" - } - }, - "CommonEnrichersConfig": [ - { - "$type": "TfsNodeStructureOptions", - "Enabled": true, - "PrefixProjectToNodes": false, - "NodeBasePaths": [], - "AreaMaps": {}, - "IterationMaps": {}, - "ShouldCreateMissingRevisionPaths": true - } - ], - "Processors": [ - { - "$type": "TfsAreaAndIterationProcessorOptions", - "Enabled": false, - "PrefixProjectToNodes": false, - "NodeBasePaths": null, - "AreaMaps": {}, - "IterationMaps": {}, - "ProcessorEnrichers": null, - "SourceName": "WorkItemSource", - "TargetName": "WorkItemTarget" - }, - { - "$type": "TfsTeamSettingsProcessorOptions", - "Enabled": false, - "MigrateTeamSettings": true, - "UpdateTeamSettings": false, - "PrefixProjectToNodes": false, - "MigrateTeamCapacities": false, - "Teams": null, - "ProcessorEnrichers": null, - "SourceName": "TeamSettingsSource", - "TargetName": "TeamSettingsTarget" - }, - { - "$type": "TestVariablesMigrationConfig", - "Enabled": false - }, - { - "$type": "TestConfigurationsMigrationConfig", - "Enabled": false - }, - { - "$type": "TestPlansAndSuitesMigrationConfig", - "Enabled": false, - "PrefixProjectToNodes": false, - "OnlyElementsWithTag": null, - "TestPlanQueryBit": null, - "RemoveAllLinks": false, - "MigrationDelay": 0, - "UseCommonNodeStructureEnricherConfig": true, - "NodeBasePaths": [], - "AreaMaps": {}, - "IterationMaps": {}, - "RemoveInvalidTestSuiteLinks": false, - "FilterCompleted": false - }, - { - "$type": "TfsSharedQueryProcessorOptions", - "Enabled": false, - "PrefixProjectToNodes": false, - "SharedFolderName": "Shared Queries", - "SourceToTargetFieldMappings": null, - "ProcessorEnrichers": null, - "SourceName": "tfsSource", - "TargetName": "tfsTarget" - }, - { - "$type": "AzureDevOpsPipelineProcessorOptions", - "Enabled": false, - "MigrateBuildPipelines": false, - "MigrateReleasePipelines": false, - "MigrateTaskGroups": false, - "MigrateVariableGroups": false, - "MigrateServiceConnections": false, - "BuildPipelines": null, - "ReleasePipelines": null, - "RepositoryNameMaps": null, - "ProcessorEnrichers": null, - "SourceName": "PipelineSource", - "TargetName": "PipelineTarget" - }, - { - "$type": "WorkItemMigrationConfig", - "Enabled": false, - "ReplayRevisions": false, - "PrefixProjectToNodes": false, - "UpdateCreatedDate": true, - "UpdateCreatedBy": true, - "BuildFieldTable": true, - "WIQLQueryBit": "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": true, - "SkipToFinalRevisedWorkItemType": true, - "WorkItemCreateRetryLimit": 5, - "FilterWorkItemsThatAlreadyExistInTarget": false, - "PauseAfterEachWorkItem": false, - "AttachmentMaxSize": 480000000, - "AttachRevisionHistory": true, - "LinkMigrationSaveEachAsAdded": false, - "GenerateMigrationComment": true, - "WorkItemIDs": null, - "MaxRevisions": 0, - "UseCommonNodeStructureEnricherConfig": true, - "StopMigrationOnMissingAreaIterationNodes": false, - "NodeBasePaths": [], - "AreaMaps": { - "Sample-project": "Sample-Project-migrated" + ], + "CommonTools": { + "TfsChangeSetMappingTool": { + "Enabled": true, + "ChangeSetMappingFile": null + }, + "TfsGitRepositoryTool": { + "Enabled": true, + "Mappings": null + }, + "FieldMappingTool": { + "Enabled": true, + "FieldSkipMap": { + "ApplyTo": [ + "*" + ], + "targetField": "TfsMigrationTool.ReflectedWorkItemId" + }, + "MultiValueConditionalMap": { + "ApplyTo": [ + "*" + ], + "sourceFieldsAndValues": { + "Field1": "Value1", + "Field2": "Value2" + }, + "targetFieldsAndValues": { + "Field1": "Value1", + "Field2": "Value2" + } + }, + "FieldMaps": [ + { + "ApplyTo": [ + "*" + ], + "defaultValue": "New", + "FieldMapType": "FieldValueMap", + "sourceField": "System.State", + "targetField": "System.State", + "valueMapping": { + "Approved": "New", + "New": "New", + "Committed": "Active", + "In Progress": "Active", + "To Do": "New", + "Done": "Closed", + "Removed": "Removed" + } + } + ], + "FieldToFieldMap": { + "ApplyTo": [ + "*" + ], + "sourceField": "Microsoft.VSTS.Common.BacklogPriority", + "targetField": "Microsoft.VSTS.Common.StackRank" + }, + "FieldToFieldMultiMap": { + "ApplyTo": [ + "*" + ], + "SourceToTargetMappings": { + "SourceField1": "TargetField1", + "SourceField2": "TargetField2" + } + }, + "FieldToTagMap": { + "ApplyTo": [ + "*" + ], + "formatExpression": "ScrumState:{0}", + "sourceField": "System.State" + }, + "FieldMergeMap": { + "ApplyTo": [ + "*" + ], + "formatExpression": "{0}

Acceptance Criteria

{1}", + "sourceFields": [ + "System.Description", + "Microsoft.VSTS.Common.AcceptanceCriteria" + ], + "targetField": "System.Description" + }, + "RegexFieldMap": { + "ApplyTo": [ + "*" + ], + "pattern": "PRODUCT \\d{4}.(\\d{1})", + "replacement": "$1", + "sourceField": "COMPANY.PRODUCT.Release", + "targetField": "COMPANY.DEVISION.MinorReleaseVersion" + }, + "FieldValueToTagMap": { + "ApplyTo": [ + "*" + ], + "formatExpression": "{0}", + "pattern": "Yes", + "sourceField": "Microsoft.VSTS.CMMI.Blocked" + }, + "TreeToTagMap": { + "ApplyTo": [ + "*" + ], + "timeTravel": "1", + "toSkip": "3" + } + }, + "TfsNodeStructureTool": { + "Enabled": true, + "Areas": { + "Filters": [], + "Mappings": {} + }, + "Iterations": { + "Filters": [], + "Mappings": {} + }, + "ShouldCreateMissingRevisionPaths": true, + "ReplicateAllExistingNodes": false + }, + "WorkItemTypeMappingTool": { + "Enabled": "True", + "Mappings": { + "Source Work Item Type Name": "Target Work Item Type Name" + } + }, + "TfsAttachmentTool": { + "Enabled": "True", + "ExportBasePath": "", + "MaxAttachmentSize": "480000000", + "RefName": "TfsAttachmentTool" }, - "IterationMaps": { - "Sample-project": "Sample-Project-migrated" + "TfsWorkItemLinkTool": { + "Enabled": "True", + "FilterIfLinkCountMatches": "True", + "SaveAfterEachLinkIsAdded": "False" }, - "MaxGracefulFailures": 0, - "SkipRevisionWithInvalidIterationPath": true, - "SkipRevisionWithInvalidAreaPath": true + "TfsRevisionManagerTool": { + "Enabled": "True", + "MaxRevisions": "1000", + "ReplayRevisions": "True" + }, + "TfsEmbededImagesTool": { + "Enabled": "True" + }, + "TfsWorkItemEmbededLinkTool": { + "Enabled": "True" + } } - ] -} + } +} \ No newline at end of file diff --git a/documentation/Migration steps list.md b/documentation/Migration steps list.md deleted file mode 100644 index 9c62c6d..0000000 --- a/documentation/Migration steps list.md +++ /dev/null @@ -1,56 +0,0 @@ - -Migration script steps -- [ ] Migrate Teams -- [ ] Migrate Area And Iterations -- [ ] Migrate Groups -- [ ] Migrate Test Variables -- [ ] Migrate Test Configurations -- [ ] Migrate Test Plans And Suites -- [ ] Migrate Work Item Querys -- [ ] Shared Queries -- [ ] Migrate Repos -- [ ] Migrate Wikis -- [ ] Migrate Task Groups -- [ ] Migrate Variable Groups -- [ ] Migrate Service Connections -- [ ] Migrate Build Queues (Agent Pools in UI) -- [ ] Migrate Build Pipelines -- [ ] Migrate Release Pipelines -- [ ] Migrate Service Hookss -- [ ] Migrate Policies -- [ ] Migrate Dashboards -- [ ] Migrate WorkItems - - - -Migration Step Order --------------------- -Teams -Area And Iterations -Groups -Test Variables -Test Configurations -Test Plans And Suites -Work Item Queries -Shared Queries -Repos -Wikis -Task Groups -Variable Groups -Service Connections -Build Queues -Build Pipelines -Release Pipelines -Service Hooks -Policies -Dashboards -Custom Field For Work Item Migration -WorkItems - - - - - - - - diff --git a/documentation/devops/git.md b/documentation/devops/git.md deleted file mode 100644 index 0c35de5..0000000 --- a/documentation/devops/git.md +++ /dev/null @@ -1,11 +0,0 @@ -# git tips hints and tricks - -Contains references and notes on encountered issues and common scenarios - -## Issues - -- [error on pull/push](https://stackoverflow.com/questions/57592530/latest-update-brings-github-error-on-pull-push-or-sync) -- [VS Refresh](https://developercommunity.visualstudio.com/content/problem/126925/git-in-team-explorer-branches-refresh-button-does.html) -- [Syncing branches](https://stackoverflow.com/questions/56553960/syncing-branches-from-github-to-local-repo-in-vs2019) -- [git lost history](https://docs.microsoft.com/en-us/azure/devops/repos/git/git-log-history-simplification?view=azure-devops) - diff --git a/documentation/migrating-project-source-code.md b/documentation/devops/manual-source-code-migration.md similarity index 100% rename from documentation/migrating-project-source-code.md rename to documentation/devops/manual-source-code-migration.md diff --git a/documentation/devops/migrating-wikis.md b/documentation/devops/manual-wiki-migration.md similarity index 100% rename from documentation/devops/migrating-wikis.md rename to documentation/devops/manual-wiki-migration.md diff --git a/documentation/devops/work-item-migrator.md b/documentation/devops/manual-work-item-migration.md similarity index 100% rename from documentation/devops/work-item-migrator.md rename to documentation/devops/manual-work-item-migration.md diff --git a/documentation/migrate-modules.md b/documentation/devops/migration-modules.md similarity index 100% rename from documentation/migrate-modules.md rename to documentation/devops/migration-modules.md diff --git a/documentation/devops/overview.md b/documentation/devops/overview.md deleted file mode 100644 index b5031fa..0000000 --- a/documentation/devops/overview.md +++ /dev/null @@ -1,12 +0,0 @@ -# Introduction -Azure DevOps references, tools, how-tos - -## DevOps Related Links and References - -- [IntelliTect's Kevin Bost on GitKracken](https://www.youtube.com/watch?time_continue=2&v=4UvCz4BQnW0) - -- [MS Build Parameters](https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-command-line-reference?view=vs-2015&redirectedfrom=MSDN) - - - - diff --git a/documentation/devops/project-migration-process.md b/documentation/devops/project-migration-process.md index 2a0f095..610ee02 100644 --- a/documentation/devops/project-migration-process.md +++ b/documentation/devops/project-migration-process.md @@ -7,24 +7,24 @@ # Project Migration Process Step by step for migrating a single Project's work items using the [Azure DevOps Migration Tools](https://dev.azure.com/nkdagility/migration-tools) (aka Martin's Tool) to an existing Azure DevOps account +- Source is *not* migrated with this tool, but is done using a custom powershell module. -Source is *not* migrated with this tool. See [migrating source code](migrating-project-source-code) for more information. +See project-migration-setup.md for instractions on setting up this repository withing another GitHub Organization The migration process copies work items and related data from one project to another. The tool used expects the target project to be created prior to execution. It will not create the project. -If the source project has custom fields, the target project must have the same fields, or be mapped to existing fields, or the custom data will not be copied. +If the source project has custom fields, the target project must have the same fields, or be mapped to existing fields, or the custom data will not be copied. This mapping of custom fields can be defined in migrator-configuration.json -Process customization in newly created Azure DevOps is different than proces customization in on premise Team Foundation Server (TFS) installations. +Process customization in newly created Azure DevOps is different than process customization in on premise Team Foundation Server (TFS) installations. ## Process Overview 1. Fill out project [Survey Spreadsheet]() for the project 2. Determine if an existing Azure DevOps Process Template will work for the project -3. If a new Process Template is Required, create a new process Template -4. Migrate source code -5. Configure and run the migration tool +3. If a new Process Template is Required, create a new process Template (see pre-migration step 1 below) +5. Configure and run the migration tool (see steps below) 6. Validate results 7. User testing and verification @@ -32,17 +32,37 @@ Process customization in newly created Azure DevOps is different than proces cus - For new projects, peform test migrations to a test organization or project. - If the source project has work items that link to source code, source code must be migrated prior to creating the links. Additionally, the source path must match so be sure when migrating to leave same structure in place. -## Creating a New Process Template for Migration +### Pre Migration Steps +1. The target project needs to be created using a process template that mirrors the source process template. If needed the source template can be migrated to the target organization. + 1. Copy an existing inherited template used for migration + - We use the Microsoft Process Migrator (https://github.com/microsoft/process-migrator) to migrate the process template by exporting, editing if needing and importing the template in json format. Install this tool using 'npm install process-migrator -g' and fill out the required configuration json file according to the repository documentation. + Example command: process-migrator --mode=export --config="C:\Users\JohnEvans\Working\Process_Migrate\configuration.json" + 2. Review any custom fields in the source process template. Custom fields will be need to be specially defined on the target account and added to the process prior to migration. + 2. Review work items for state changes. Non default states need to either be added or re-mapped to standard states in configuration/migrator-configuration.json dirong migration. + 3. Import the process template + Example command: process-migrator --mode=import --config="C:\Users\JohnEvans\Working\Process_Migrate\configuration.json" + 4. (Optional) Commit the project specific process template in the event it's needed for reference, or, to use it as a template for similar projects + +2. Users in source organization that are not also in the target organization need to be migrated. This is included in the migration if running a full migration (ado-migration-process-full.yml workflow). Otherwise use Migrate-ADO-Users.psm1 to migrate users. + +3. Verify that the service account with its token set as the AZURE_DEVOPS_MIGRATION_PAT secret has access to both source and target organizations and has "Basic + Test Plans" licensing access. + +4. Install any extensions etc used in Source that are not installed already in the target organization. + +5. Delete any unneeded/unused Service Connections, Agent Pools, Teams, Groups, Pipelines, Dashboards etc. so that they are not migrated minimizing chances for failures. +6. Azure RM Service Connection must be created prior to project migration. Service Connection credentials cannot be migrated. -1. Copy an existing inherited template used for migration -2. Review any custom fields in the source process. Custom fields will be need to be specially defined on the target account and added to the process prior to migration. -2. Review work items for state changes. Non default states need to either be added or re-mapped to standard states in configuration. - -## Adding Custom Fields to your Azure DevOps Process Template +## Configure and Run the migration tool - +1. Verify configuration/migrator-configuration.json is set up correctly regarding area maps and iteration maps. Commit any changes necessary. +2. Execute the desired migration workflow. + - Execute 'Full ADO Project Migration' workflow to migrate an entire project -## Configure and Run the migration tool +## Post Migration Steps +1. Set source to read only: set each repository's isDisabled flag to true (manually via UI) +2. Move all members of Contributors to Readers. Members of groups such as Project Admins, Build Admins, project Collection admins are not affected. Additionally, any specific user assignments will still be valid +3. Wikis get migrated as repositories and need to be re-connected to wiki after migration: https://learn.microsoft.com/en-us/azure/devops/project/wiki/provisioned-vs-published-wiki?view=azure-devops +4. Dashboard Widgets will need to be re-tied to Work-Item queries +5. Set default iteration path for each team as needed. Default iteration path is not set for teams automatically. +6. Set default area path for each team as needed. Default area path is not set for teams automatically. -Use an existing configuration template from *** as existing configuration can be leveraged -Commit the project specific configuration in the event it's needed for reference, or, to use it as a template for similar projects \ No newline at end of file diff --git a/documentation/devops/project-migration-setup.md b/documentation/devops/project-migration-setup.md new file mode 100644 index 0000000..22b19d1 --- /dev/null +++ b/documentation/devops/project-migration-setup.md @@ -0,0 +1,20 @@ +# Introduction +This page describe how to set up this repository within your GitHub organization for executing GitHub Actions workflows. + +## Migration Tool Setup + +### Set Up Custom Agent that the Migration will Run On +1. Set up a GitHub Actions agent pool +2. Configure virtual machine to run as a GitHub Actions agent within the agent pool +3. Modify the "runs-on" argument to use your agent pool + +### How to Set Up this Repository to Run in Another GitHub Organization +1. Clone this repository +2. Add a new remote +3. Push to the new remote +4. Set a GitHub repository secret + - AZURE_DEVOPS_MIGRATION_PAT: This is the Personal Access Token that the process will use to make calls to the Azure DevOps REST API. The Token name is AZURE_DEVOPS_MIGRATION_PAT and should contain a token that has access to both Source and Target projects and has "Basic + Test Plans" licensing access. +5. Set 3 GitHub repository variables + - DevopsMigrationToolConfigurationFile: The name of the configuration file for the Azure DevOps Migration Tool (Martin's Tool). The default value is "migrator-configuration.json". + - WorkItemMigratorDirectory: The file path on the agent where the GitHub Actions Workflow runner can find the Azure DevOps Migration Tool (Martin's Tool) executable. + - ArtifactFeedPackageVersionLimit: An integer value representing the maximum number of Artifact Feed Package versions to migrate. Default is -1 which tells the migration script to migrate all package versions. diff --git a/documentation/devops/project-migration-workflows-about.md b/documentation/devops/project-migration-workflows-about.md new file mode 100644 index 0000000..bd9cacd --- /dev/null +++ b/documentation/devops/project-migration-workflows-about.md @@ -0,0 +1,50 @@ +# Migration through GitHub Action Workflows +There are five GitHub Action Workflows for ADO project migration using the Project Migration scripts outlined in the "README - Project Migration.md" file within the project-migration folder. + +These Workflows are outlined below: + +## "Run ADO Organization User Migration" +Use this Action Workflow in order to migrate Azure DevOps organization level users from a Source organization to a Target organization. +Fill in the input boxes with the Source and target information and run the workflow. + +***Please Note:***
+On all of the workflows there is a "Whatif" checkbox input option which allows you to run a Dry Run to test connectivity to the powershell scripts. +No data will actually be migrated if the WhatIf checkbox is checked. + +## "Run Full ADO Project Migration" +The Full Run Action Workflow is used to process a FULL ADO project to Project migration. This will perform all of the migrations scripts described in the "README - Project Migration.md" file. +The process is run in consecutive steps which provide the correct sequence for dependencies. + +## "Run Partial ADO Project Migration" + +The Partial ADO Project Migration Workflow is the Partial migration. Use this to re-run sections of a full migration. This workflow will be used to do delta-backflow migrations in areas such as work-items and also for testing and correcting any migration issues. Each of the areas of migration are contained in a drop-down selection box labeled "Migration Selection". Use this input option to select the area that you would like to migrate separately. + +## "Work Item Backfill ADO Project Migration" +The Work Item Backfill ADO Project Migration Workflow can be run to apply all work item changes from the source project to the target project for the specified number of days in the past from the current date. For example, if 0 is provided, the work item backfill will be applied for changes from midnight on current date. For any other number, the work item backfill will be applied for x number of days previously from midnight on the starting date. + +## "Between Dates Work Item Backfill ADO Project Migration" +The Between Dates Work Item Backfill ADO Project Migration Workflow can be run to apply all work item changes from the source project to the target project between (inclusive) the specified dates. + +Migration Step Execution Order +-------------------- +Teams +Area And Iterations +Groups +Test Variables +Test Configurations +Test Plans And Suites +Work Item Queries +Shared Queries +Repos +Wikis +Task Groups +Variable Groups +Service Connections +Build Queues +Build Pipelines +Release Pipelines +Service Hooks +Policies +Dashboards +Custom Field For Work Item Migration +WorkItems \ No newline at end of file diff --git a/documentation/git/git-helpers.md b/documentation/git/git-helpers.md index bf6ee1c..ff0587b 100644 --- a/documentation/git/git-helpers.md +++ b/documentation/git/git-helpers.md @@ -36,4 +36,15 @@ git config --global core.editor "'C:\Program Files\Microsoft VS Code\Code.exe'" to list all global configuraiton values: ``` git config --global --list -``` \ No newline at end of file +``` + +# git tips hints and tricks + +Contains references and notes on encountered issues and common scenarios + +## Issues + +- [error on pull/push](https://stackoverflow.com/questions/57592530/latest-update-brings-github-error-on-pull-push-or-sync) +- [VS Refresh](https://developercommunity.visualstudio.com/content/problem/126925/git-in-team-explorer-branches-refresh-button-does.html) +- [Syncing branches](https://stackoverflow.com/questions/56553960/syncing-branches-from-github-to-local-repo-in-vs2019) +- [git lost history](https://docs.microsoft.com/en-us/azure/devops/repos/git/git-log-history-simplification?view=azure-devops) \ No newline at end of file diff --git a/documentation/migrating-wikis.md b/documentation/migrating-wikis.md deleted file mode 100644 index d1c2f27..0000000 --- a/documentation/migrating-wikis.md +++ /dev/null @@ -1,29 +0,0 @@ -# How to migrate a project wiki - -Wikis can be easily migrated from one project to another, or, from one organization to another. - -1. Clone the wiki repo from the source -2. Add to an existing repo, or add a wiki repo as the target -3. Set the remote of the cloned repo -4. Push wiki to the remote - -## Clone the wiki from the source - -A project wiki clone URL is availle from the wiki context menu -![Clone Wiki](.images\clone-wiki-annotation.jpg) - -## Add to an existing repo - -Get the clone address of an existing - -## Set the remote of an existing repo - -``` -git remote add origin -``` - -## Push the wiki to the remote - -``` -git push -``` diff --git a/documentation/using-the-azure-devops-cli-extension.md b/documentation/using-the-azure-devops-cli-extension.md deleted file mode 100644 index 27d44f0..0000000 --- a/documentation/using-the-azure-devops-cli-extension.md +++ /dev/null @@ -1,83 +0,0 @@ -[[_TOC_]] - -## Using the Azure CLI Azure DevOps Extension - -The Azure CLI will work just fine within PowerShell. However, if you want to pipe and process results, some additional steps must be taken as by default, the CLI returns results in JSON. - -## Adding users to a team using the Azure CLI Azure DevOps extension and PowerShell -Basic process as follows -1. Get a list of users into a CSV -2. Get the team's security group -3. Add the users from the list to that group - -### Get a list of users with their descriptors ("member id") to a CSV -We can add users to a project Using the Azure CLI and Azure DevOps extension. - -Get a list of users into a PowerShell variable. -``` -$u = az devops user list | ConvertFrom-Json -``` - -Export users and their desciptor to a CSV. A CSV isn't strictly required but may be useful. -``` -$u.items | ForEach-Object { $_.user | select displayName, descriptor } | export-csv users.csv -NoTypeInformation -``` - -### Get the default team security group for a project - -Get a list of all of the security groups for a given project into a PowerShell variable - -``` -$groups = az devops security group list --project "" | ConvertFrom-Json -``` - -Filter the list for the team we care about and get its descriptor/Group ID and set to $team - -``` -$team = $groups.graphGroups | Where-Object {$_.displayName -like "*team*"} -``` - -### Add a list of users to a security group - -For readability, and to veriy the list is correct, import the csv into a PowerShell variable -``` -$users = Import-CSV users.csv -``` - -You can filter or remove users you don't want added. - -Add users by piping to a the membership add command -``` -$users | ForEach-Object {az devops security group membership add --group-id $team.descriptor --member-id $_.descriptor} -``` - -Users will be added to the group. - -## get a list of Projects - -``` -$projects = az devops project list | ConvertFrom-Json -``` - -## List all projects Area Paths to a table - -Uses the list of projects to then display all area paths for each table. - -Uses the ```--output table``` format for easy reading. - - -``` -$projects | ForEach-Object {az boards area project list --depth 5 -p $_.Name -o table} -``` - -### List all projects iteration paths - -Uses the list of projects to then display all iteration paths. - -Uses the ```--output table``` format for easy reading. - -``` -$projects | ForEach-Object {az boards iteration project list -p $_.Name --depth 5 --output table } -``` - - diff --git a/documentation/work-item-migrator.md b/documentation/work-item-migrator.md deleted file mode 100644 index 96a3356..0000000 --- a/documentation/work-item-migrator.md +++ /dev/null @@ -1,41 +0,0 @@ -# Work Item Project Migration - -Using the [Microsoft Work Item Migration Tool](https://github.com/microsoft/vsts-work-item-migrator) - -## Pre-requisites -- Requires .NET Core to run -- Download the latest code from the repo to get started - -## Process - -Create a configuration json for each of the target projects -The configuration is created from the sample provided by the project -Unless defaults are provided, Areas and Iterations must match in order for an item to be migrated -Rather than attempting to map these, we have elected to only use a single Area Path per project, and, to assign all work to the project's default Iteration Path - -## Configure Area Path and Iteration Path -An Area Path has already been created for each project have already been created. - -A default iteration path that is equal to "Applications\" should be configured for each project prior to migrating work items for that project. - -## Configuring the migration - -Key settings include: -- PATs for the Source and Target project -- Source and target accounts -- source and target project names -- Shared Query that includes all work items to be included in the migration - -The same PAT and source and target accounts will be used for each migation -The target project name, Applications, will also be the saeme for each migration - -## Step by step -1. Copy a new json file from the default -2. Set the source project name in the json -3. Create a query (named "allitems") in the source project, be sure to save in Shared Queries -4. Set the the area path as follows: "default-area-path": "Applications\\", -5. Set the iteration path as follows: "default-iteration-path": "contoso-project\\", -6. run a migration valiation using ```dotnet run --validate .json``` -7. Run the migration using ```dotnet run --migrate .json``` - - diff --git a/github-tools/README.md b/github-tools/README.md index 657d9aa..09491f5 100644 --- a/github-tools/README.md +++ b/github-tools/README.md @@ -3,9 +3,6 @@ Uses existing ADO migration PowerShell modules to pull relevant information from Uses ado2gh tool from [GitHub Enterprise Importer CLI](https://github.com/github/gh-gei) -orgs.json -Add source organizations and ADO Pipelines service connections to - ## Tooling Setup 1. Clone repo 1. Download and unzip the latest ado2gh migratin tool from [Enterprise Importer Releases](https://github.com/github/gh-gei/releases) @@ -21,6 +18,6 @@ New-Alias ado2gh ## GitHub and ADO Organization Setup - Install the ADO Boards app in the target GitHub org - Install the ADO Pipelines app in the target GitHub org -- Configure one Pipelines Service Connection in the source ADO org and note its object id -- update orgs.json with ADO org name and pipeline id +- Configure one Pipelines Service Connection in the source ADO org and note its object ID +- Update orgs.json with ADO org name and corresponding service connection ID diff --git a/modules/Migrate-ADO-Project.psm1 b/modules/Migrate-ADO-Project.psm1 index ee89000..b9f21b6 100644 --- a/modules/Migrate-ADO-Project.psm1 +++ b/modules/Migrate-ADO-Project.psm1 @@ -175,7 +175,7 @@ function Start-ADOProjectMigration { $arguments = "execute --config `"$MartinsToolConfigurationFile`"" - Start-Process -NoNewWindow -Wait -FilePath .\migration.exe -ArgumentList $arguments + Start-Process -NoNewWindow -Wait -FilePath .\devopsmigration.exe -ArgumentList $arguments Set-Location -Path $savedpath } else { diff --git a/project-migration/MigrateProject.ps1 b/project-migration/MigrateProject.ps1 index 0d68449..a6a1b4d 100644 --- a/project-migration/MigrateProject.ps1 +++ b/project-migration/MigrateProject.ps1 @@ -34,7 +34,7 @@ Param ( # Step 3 [parameter(Mandatory=$FALSE)] [Boolean]$SkipMigrateWorkItems = $TRUE, - [parameter(Mandatory=$FALSE)] [String]$WorkItemQueryBit = "AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') " + [parameter(Mandatory=$FALSE)] [String]$WorkItemQueryBit = "SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') ORDER BY [System.ChangedDate] DESC" ) @@ -152,138 +152,61 @@ Write-Host "Configure Azure DevOps Migration Tool (Martin's Tool).." $martinConfigPath = "$($ProjectDirectory)\$($configPath)$DevOpsMigrationToolConfigurationFile" $martinConfiguration = [Object](Get-Content $martinConfigPath | Out-String | ConvertFrom-Json -Depth 100) $martinPreviousConfiguration = [Object](Get-Content $martinConfigPath | Out-String | ConvertFrom-Json -Depth 100) -$martinConfigFileChanged = $FALSE - -# ------------------ -# ----- Source ----- -# ------------------ -# Organization -if($martinConfiguration.Source.Collection -ne $SourceProject.Organization) { - $martinConfiguration.Source.Collection = $SourceProject.Organization - $martinConfigFileChanged = $TRUE -} -# project -if($martinConfiguration.Source.Project -ne $SourceProject.ProjectName) { - $martinConfiguration.Source.Project = $SourceProject.ProjectName - $martinConfigFileChanged = $TRUE -} -# personal access token -if($martinConfiguration.Source.PersonalAccessToken -ne $sourcePat) { - $martinConfiguration.Source.PersonalAccessToken = $sourcePat - $martinConfigFileChanged = $TRUE -} -# ------------------ -# ----- Target ----- -# ------------------ -# Organization -if($martinConfiguration.Target.Collection -ne $TargetProject.Organization) { - $martinConfiguration.Target.Collection = $TargetProject.Organization - $martinConfigFileChanged = $TRUE -} -# project -if($martinConfiguration.Target.Project -ne $TargetProject.ProjectName) { - $martinConfiguration.Target.Project = $TargetProject.ProjectName - $martinConfigFileChanged = $TRUE -} -# personal access token -if($martinConfiguration.Target.PersonalAccessToken -ne $targetPat) { - $martinConfiguration.Target.PersonalAccessToken = $targetPat - $martinConfigFileChanged = $TRUE -} +# --------------------------------------- +# -- Atttachment Temporary Directory -- +# --------------------------------------- +$tools = $martinConfiguration.MigrationTools.CommonTools.PSObject.Properties +$attachmentTool = $tools | Where-Object {$_.Name -eq "TfsAttachmentTool"} +$attachmentTool.Value.ExportBasePath = "$WorkItemMigratorDirectory\\WorkItemAttachmentWorkingFolder" # --------------------------------------- # -- End Point Source/Target settings -- # --------------------------------------- -$endpointConfigs = @("AzureDevOpsEndpoints", "TfsTeamSettingsEndpoints", "TfsWorkItemEndpoints", "TfsEndpoints") - -foreach($endpointConfig in $martinConfiguration.Endpoints.PSObject.Properties) { - if($endpointConfigs.Contains($endpointConfig.Name)) { - # Source Organization - if($endpointConfig.Value[0].Organisation -ne $SourceProject.Organization) { - $endpointConfig.Value[0].Organisation = $SourceProject.Organization - $martinConfigFileChanged = $TRUE - } - # Source project - if($endpointConfig.Value[0].Project -ne $SourceProject.ProjectName) { - $endpointConfig.Value[0].Project = $SourceProject.ProjectName - $martinConfigFileChanged = $TRUE - } - # Source personal access token - if($endpointConfig.Value[0].AccessToken -ne $sourcePat) { - $endpointConfig.Value[0].AccessToken = $sourcePat - $martinConfigFileChanged = $TRUE - } - if($endpointConfig.Name -eq "TfsWorkItemEndpoints") { - # Source personal access token - if($endpointConfig.Value[0].PersonalAccessToken -ne $sourcePat) { - $endpointConfig.Value[0].PersonalAccessToken = $sourcePat - $martinConfigFileChanged = $TRUE - } - } - # Target Organization - if($endpointConfig.Value[1].Organisation -ne $TargetProject.Organization) { - $endpointConfig.Value[1].Organisation = $TargetProject.Organization - $martinConfigFileChanged = $TRUE - } - # Target project - if($endpointConfig.Value[1].Project -ne $TargetProject.ProjectName) { - $endpointConfig.Value[1].Project = $TargetProject.ProjectName - $martinConfigFileChanged = $TRUE - } - # Target personal access token - if($endpointConfig.Value[1].AccessToken -ne $targetPat) { - $endpointConfig.Value[1].AccessToken = $targetPat - $martinConfigFileChanged = $TRUE - } - if($endpointConfig.Name -eq "TfsWorkItemEndpoints") { - # Source personal access token - if($endpointConfig.Value[1].PersonalAccessToken -ne $targetPat) { - $endpointConfig.Value[1].PersonalAccessToken = $targetPat - $martinConfigFileChanged = $TRUE - } - } - } +foreach($endpoint in $martinConfiguration.MigrationTools.Endpoints.PSObject.Properties) { + + Write-Host "Name: $($endpoint.Name)" + + if($endpoint.Name -like "*Source"){ + $endpoint.Value.Collection = $SourceProject.Organization + $endpoint.Value.Project = $SourceProject.ProjectName + $endpoint.Value.Authentication.AccessToken = $sourcePat + Write-Host "Pat set to $sourcePat" + } elseif($endpoint.Name -like "*Target"){ + $endpoint.Value.Collection = $TargetProject.Organization + $endpoint.Value.Project = $TargetProject.ProjectName + $endpoint.Value.Authentication.AccessToken = $targetPat + } } # -------------------------------------------------- # ----- Azure DevOps Migration Tool Processors ----- # - enable which processors we execute - # -------------------------------------------------- -foreach($processor in $martinConfiguration.Processors) +foreach($processor in $martinConfiguration.MigrationTools.Processors) { - if($processor.'$type' -eq "TfsAreaAndIterationProcessorOptions") { - if(($processor.Enabled -ne !$SkipMigrateTfsAreaAndIterations)){ - $processor.Enabled = !$SkipMigrateTfsAreaAndIterations - $martinConfigFileChanged = $TRUE - } - } elseif($processor.'$type' -eq "TfsTeamSettingsProcessorOptions") { + if($processor.ProcessorType -eq "TfsTeamSettingsProcessor") { if(($processor.Enabled -ne !$SkipMigrateTeams)){ - $processor.Enabled = !$SkipMigrateTeams - $martinConfigFileChanged = $TRUE + $processor.Enabled = !$SkipMigrateTeams } - } elseif($processor.'$type' -eq "TestVariablesMigrationConfig") { + } elseif($processor.ProcessorType -eq "TfsTestVariablesMigrationProcessor") { if(($processor.Enabled -ne !$SkipMigrateTestVariables)){ - $processor.Enabled = !$SkipMigrateTestVariables - $martinConfigFileChanged = $TRUE + $processor.Enabled = !$SkipMigrateTestVariables } - } elseif($processor.'$type' -eq "TestConfigurationsMigrationConfig") { + } elseif($processor.ProcessorType -eq "TfsTestConfigurationsMigrationProcessor") { if(($processor.Enabled -ne !$SkipMigrateTestConfigurations)){ - $processor.Enabled = !$SkipMigrateTestConfigurations - $martinConfigFileChanged = $TRUE + $processor.Enabled = !$SkipMigrateTestConfigurations } - } elseif($processor.'$type' -eq "TestPlansAndSuitesMigrationConfig") { + } elseif($processor.ProcessorType -eq "TfsTestPlansAndSuitesMigrationProcessor") { if(($processor.Enabled -ne !$SkipMigrateTestPlansAndSuites)){ - $processor.Enabled = !$SkipMigrateTestPlansAndSuites - $martinConfigFileChanged = $TRUE + $processor.Enabled = !$SkipMigrateTestPlansAndSuites } - } elseif($processor.'$type' -eq "TfsSharedQueryProcessorOptions") { + } elseif($processor.ProcessorType -eq "TfsSharedQueryProcessor") { if(($processor.Enabled -ne !$SkipMigrateWorkItemQuerys)){ - $processor.Enabled = !$SkipMigrateWorkItemQuerys - $martinConfigFileChanged = $TRUE + $processor.Enabled = !$SkipMigrateWorkItemQuerys } - } elseif($processor.'$type' -eq "AzureDevOpsPipelineProcessorOptions") { + } elseif($processor.ProcessorType -eq "AzureDevOpsPipelineProcessor") { # MigrateBuildPipelines $migratingPipeline = $FALSE if(($processor.MigrateBuildPipelines -ne !$SkipMigrateBuildPipelines)){ @@ -336,13 +259,13 @@ foreach($processor in $martinConfiguration.Processors) $processor.RepositoryNameMaps = $NULL } - $martinConfigFileChanged = $TRUE + } - } elseif(($processor.'$type' -eq "WorkItemMigrationConfig") -or ($processor.'$type' -eq "WorkItemTrackingProcessorOptions")) { - if(($processor.Enabled -ne !$SkipMigrateWorkItems) -or ($processor.WIQLQueryBit -ne $WorkItemQueryBit)){ + } elseif(($processor.ProcessorType -eq "TfsWorkItemMigrationProcessor") -or ($processor.ProcessorType -eq "WorkItemTrackingProcessorOptions")) { + if(($processor.Enabled -ne !$SkipMigrateWorkItems) -or ($processor.WIQLQuery -ne $WorkItemQueryBit)){ $processor.Enabled = !$SkipMigrateWorkItems - $processor.WIQLQueryBit = $WorkItemQueryBit - $martinConfigFileChanged = $TRUE + $processor.WIQLQuery = $WorkItemQueryBit + } } } @@ -362,9 +285,10 @@ $SkipAzureDevOpsMigrationTool = ( ` ) -if($martinConfigFileChanged) { - $martinConfiguration | ConvertTo-Json -Depth 100 | Set-Content $martinConfigPath -} +$martinConfiguration | ConvertTo-Json -Depth 100 | Set-Content $martinConfigPath +$configString = $martinConfiguration | ConvertTo-Json -Depth 100 +Write-Host "Configuration after substitution:" +Write-Host $configString #endregion @@ -409,6 +333,6 @@ Start-ADOProjectMigration ` # Clean up old martin's tool Configuration Write-Host "Clean up Configuration file for Azure DevOps Migration Tool (Martin's Tool).." -if($martinConfigFileChanged) { - $martinPreviousConfiguration | ConvertTo-Json -Depth 100 | Set-Content $martinConfigPath -} + +$martinPreviousConfiguration | ConvertTo-Json -Depth 100 | Set-Content $martinConfigPath + diff --git a/project-migration/README - Github Action Workflow migration.md b/project-migration/README - Github Action Workflow migration.md deleted file mode 100644 index dd7d2e2..0000000 --- a/project-migration/README - Github Action Workflow migration.md +++ /dev/null @@ -1,47 +0,0 @@ -# Migration through GitHub Action Workflows -There are three GitHub Action Workflows to for ADO project migration using the Project Migration scripts outlined in the "README - Project Migration.md" file. - -These Workflows are outlined below: - -## "Run ADO Organization User Migration" -Use this Action Workflow in order to migrate Azure DevOps organization level users from a Source organization to a Target organization. -Fill in the input boxes with the Source and target information and run the workflow. - -***Please Note:***
-On all of the workflows there is a "Whatif" checkbox input option which allows you to run a Dry Run to test connectivity to the powershell scripts. -No data will actually be migrated if the WhatIf checkbox is checked. - -![Alt text](.images/user-migration-workflow.png) - -## "Run Full ADO Project Migration" -The Full Run Action Workflow is used to process a FULL ADO project to Project migration. This will perform all of the migrations scripts described in the "README - Project Migration.md" file. -The process is run in consecutive steps which provide the correct sequence for dependencies. - -![Alt text](.images/user-migration-workflow.png) - -## "Run Partial ADO Project Migration" - -The last Action Workflow is the Partial migration. Use this to re-run sections of a full migration. This workflow will be used to do delta-backflow migrations in areas such as work-items and also for testing and correcting any migration issues. Each of the areas of migration are contained in a drop-down selection box labeled "Migration Selection". Use this input option to select the area that you would like to migrate separately. - -![Alt text](.images/partial-migration-workflow.png) - -## Settings for the GitHub Action Workflows - -### Variables -There are a few variables that each of the workflows share. These variables are define under the Settings tab for the repository. -![Alt text](.images/settings.png) - -Under "Secrets and Varables" for Actions there are bth Variables and Secrets defined. - -The following three variables need to be defined here for the migration process to function. -- DEVOPSMIGRATIONTOOLCONFIGURATIONFILE = The name of the configuration file for the Azure DevOps Migration Tool (Martin's Tool). The default value is "migrator-configuration.json". -- WORKITEMMIGRATORDIRECTORY = The file path on the server where the GitHub Action Workflow runner can fine the Azure DevOps Migration Tool (Martin's Tool) executable. -- ARTIFACTFEEDPACKAGEVERSIONLIMIT = An integer value representing the maximum number of Artifact Feed Package versions to migrate. Default is -1 which tells the migration script to migrate all package versions. - -![Alt text](.images/variables.png) - -### Secrets -There is one required secret that needs to be defined here for the migration process to run. This is the Personal Access Token that the process will use to make calls to the Azure DevOps REST API. -The Token name is AZURE_DEVOPS_MIGRATION_PAT and should contain a token that has access to both Source and Target projects and has "Basic + Test Plans" licensing access. - -![Alt text](.images/secret.png) diff --git a/project-migration/README - Project Migration.md b/project-migration/README - Project Migration.md index a2511ad..76c16d6 100644 --- a/project-migration/README - Project Migration.md +++ b/project-migration/README - Project Migration.md @@ -1,28 +1,12 @@ # Azure DevOps Project Migration -## prerequisites to migration -- The target project needs to be created using a process process template that mirrors the source process template. If needed the source template can be migrated to the target organization. - - - We use the Microsoft Process Migrator (https://github.com/microsoft/process-migrator) to migrate the process template by exporting, editing if needing and importing the template in json format. - - process-migrator --mode=export --config="C:\Users\JohnEvans\Working\Process_Migrate\configuration.json" - - process-migrator --mode=import --config="C:\Users\JohnEvans\Working\Process_Migrate\configuration.json" - -- Users in source organization that are not also in the target organization need to be migrated - - There is a script to perform this user migration. - -- Token needs to be created that can access both source and target organizations and has "Basic + Test Plans" licensing access. - -- Install any extensions etc used in Source that are not installed already in the target organization. - -- Delete any unneeded/unused Service Connections, Agent Pools, Teams, Groups, Pipelines, Dashboards etc. so that they are not migrated minimizing chances for failures. - This tool is used for migrating an Azure DevOps (ADO) project to another project location either within the same organization or to another. -It consists of a set of PowerShell and an external .NET application that handles to migration of various components of the ADO project. +It consists of a set of PowerShell and an external .NET application (Martin's Tool) that handles to migration of various components of the ADO project. The PowerShell scripts are comprised of a set of modules and a set of helper scripts that each perform various tasks. -An external migration tool is also utilized called "Azure DevOps Migration Tools" by Naked Agility, also known as Martin's Tool (https://nkdagility.com/learn/azure-devops-migration-tools/) after the auther Martin Hinshelwood. This tool performs the majority of the ADP migration tasks while the PowerShell Scripts picks up where this migration lacks. +An external migration tool is also utilized called "Azure DevOps Migration Tools" by Naked Agility, also known as Martin's Tool (https://nkdagility.com/learn/azure-devops-migration-tools/) after the author Martin Hinshelwood. This tool performs the majority of the ADP migration tasks while the PowerShell Scripts picks up where this migration lacks. * Follow the installation instructions here https://nkdagility.com/learn/azure-devops-migration-tools/getting-started/ to install this tool locally. ## "modules" Directory @@ -101,9 +85,9 @@ The `Configuration.json` file is used to set up file locations for logging, an ## Migration Steps PowerShell Scripts The entire process is initiated through PowerShell Scripts. Use of "Martin's Tool" is done through the PowerShell migration scripts. The entire process is set up in steps which are executed sequentially. -There is also a script that will esecute the entire process by calling the step scripts in the proper sequence. +There is also a script that will execute the entire process by calling the step scripts in the proper sequence. -**Note:** The follwoing scripts may require editing depending on project requirements, Work Item counts per ChangedDate period used or other cases where errors occur due to project specifics. +**Note:** The following scripts may require editing depending on project requirements, Work Item counts per ChangedDate period used or other cases where errors occur due to project specifics. #### Step_X_Migrate_Org_Level_Users.ps1 - will execute all other steps sequentially #### Step_1_Migrate_Project.ps1 @@ -244,19 +228,5 @@ The `MigrateProject.ps1` script is the starting point for preforming a full migr

----------- -# Migration Notes -- Default iteration path is not set for a team -- Default area path is not set for a team -- Wikis get migrated as repositories and need to be re-connected to wiki after migration - - https://learn.microsoft.com/en-us/azure/devops/project/wiki/provisioned-vs-published-wiki?view=azure-devops -- Dashboard Widgets will need to be re-tied to Work-Item queries - -# Set source to read only -- set repos isDisabled flag to true (manually via UI this pass) -- Move all members of Contributors to Readers. members of groups such as Project Admins, Build Admins, project Collection admins are not affected. Additionally, any specific user assignments will still be valid - -# Prior to Project Migration -- If migrating from one organization to another, it is recommended that all User Identities in the Source organization be migrated to the target migration. This allows any ADO components assigned to that user, such as Work Items and Test Plans etc., to be nigrated without error. The user can then be changed after migration. -- Azure RM Service Connection must be created prior to project migration. Service Connection credentials cannot be migrated. -- Target organization must have a new enherited Process Template created and a custom field named xxxxx added to all of the Work-Item types. See this documentation for more details: https://nkdagility.com/learn/azure-devops-migration-tools/server-configuration/ + diff --git a/project-migration/Step_3_Migrate_Project.ps1 b/project-migration/Step_3_Migrate_Project.ps1 index 4b12269..079e06b 100644 --- a/project-migration/Step_3_Migrate_Project.ps1 +++ b/project-migration/Step_3_Migrate_Project.ps1 @@ -39,7 +39,7 @@ Write-Host "Migrate Work Items with Created Date between 0 days ago and 100 days Write-Host " " & .\MigrateProject.ps1 ` -SkipMigrateWorkItems $WhatIf ` --WorkItemQueryBit "AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') AND [System.CreatedDate] > @Today - 100 AND [System.CreatedDate] <= @Today - 0 " +-WorkItemQueryBit "SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') AND [System.CreatedDate] > @Today - 100 AND [System.CreatedDate] <= @Today - 0 " Write-Host " " @@ -47,7 +47,7 @@ Write-Host "Migrate Work Items with Created Date between 100 days ago and 200 da Write-Host " " & .\MigrateProject.ps1 ` -SkipMigrateWorkItems $WhatIf ` --WorkItemQueryBit "AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') AND [System.CreatedDate] > @Today - 200 AND [System.CreatedDate] <= @Today - 100 " +-WorkItemQueryBit "SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') AND [System.CreatedDate] > @Today - 200 AND [System.CreatedDate] <= @Today - 100 " Write-Host " " @@ -55,7 +55,7 @@ Write-Host "Migrate Work Items with Created Date between 200 days ago and 300 da Write-Host " " & .\MigrateProject.ps1 ` -SkipMigrateWorkItems $WhatIf ` --WorkItemQueryBit "AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') AND [System.CreatedDate] > @Today - 300 AND [System.CreatedDate] <= @Today - 200 " +-WorkItemQueryBit "SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') AND [System.CreatedDate] > @Today - 300 AND [System.CreatedDate] <= @Today - 200 " Write-Host " " @@ -63,7 +63,7 @@ Write-Host "Migrate Work Items with Created Date between 300 days ago and 400 da Write-Host " " & .\MigrateProject.ps1 ` -SkipMigrateWorkItems $WhatIf ` --WorkItemQueryBit "AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') AND [System.CreatedDate] > @Today - 400 AND [System.CreatedDate] <= @Today - 300 " +-WorkItemQueryBit "SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') AND [System.CreatedDate] > @Today - 400 AND [System.CreatedDate] <= @Today - 300 " Write-Host " " @@ -71,7 +71,7 @@ Write-Host "Migrate Work Items with Created Date between 400 days ago and 500 da Write-Host " " & .\MigrateProject.ps1 ` -SkipMigrateWorkItems $WhatIf ` --WorkItemQueryBit "AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') AND [System.CreatedDate] > @Today - 500 AND [System.CreatedDate] <= @Today - 400 " +-WorkItemQueryBit "SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') AND [System.CreatedDate] > @Today - 500 AND [System.CreatedDate] <= @Today - 400 " Write-Host " " @@ -79,7 +79,7 @@ Write-Host "Migrate Work Items with Created Date between 500 days ago and 600 da Write-Host " " & .\MigrateProject.ps1 ` -SkipMigrateWorkItems $WhatIf ` --WorkItemQueryBit "AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') AND [System.CreatedDate] > @Today - 600 AND [System.CreatedDate] <= @Today - 500 " +-WorkItemQueryBit "SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') AND [System.CreatedDate] > @Today - 600 AND [System.CreatedDate] <= @Today - 500 " Write-Host " " @@ -87,7 +87,7 @@ Write-Host "Migrate Work Items with Created Date between 600 days ago and 700 da Write-Host " " & .\MigrateProject.ps1 ` -SkipMigrateWorkItems $WhatIf ` --WorkItemQueryBit "AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') AND [System.CreatedDate] > @Today - 700 AND [System.CreatedDate] <= @Today - 600 " +-WorkItemQueryBit "SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') AND [System.CreatedDate] > @Today - 700 AND [System.CreatedDate] <= @Today - 600 " Write-Host " " @@ -95,7 +95,7 @@ Write-Host "Migrate Work Items with Created Date between 700 days ago and 800 da Write-Host " " & .\MigrateProject.ps1 ` -SkipMigrateWorkItems $WhatIf ` --WorkItemQueryBit "AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') AND [System.CreatedDate] > @Today - 800 AND [System.CreatedDate] <= @Today - 700 " +-WorkItemQueryBit "SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') AND [System.CreatedDate] > @Today - 800 AND [System.CreatedDate] <= @Today - 700 " Write-Host " " @@ -103,7 +103,7 @@ Write-Host "Migrate Work Items with Created Date between 800 days ago and 900 da Write-Host " " & .\MigrateProject.ps1 ` -SkipMigrateWorkItems $WhatIf ` --WorkItemQueryBit "AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') AND [System.CreatedDate] > @Today - 900 AND [System.CreatedDate] <= @Today - 800 " +-WorkItemQueryBit "SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') AND [System.CreatedDate] > @Today - 900 AND [System.CreatedDate] <= @Today - 800 " Write-Host " " @@ -111,7 +111,7 @@ Write-Host "Migrate Work Items with Created Date between 900 days ago and 1000 d Write-Host " " & .\MigrateProject.ps1 ` -SkipMigrateWorkItems $WhatIf ` --WorkItemQueryBit "AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') AND [System.CreatedDate] > @Today - 1000 AND [System.CreatedDate] <= @Today - 900 " +-WorkItemQueryBit "SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') AND [System.CreatedDate] > @Today - 1000 AND [System.CreatedDate] <= @Today - 900 " Write-Host " " @@ -119,7 +119,7 @@ Write-Host "Migrate Work Items with Created Date between 1000 days ago and 1100 Write-Host " " & .\MigrateProject.ps1 ` -SkipMigrateWorkItems $WhatIf ` --WorkItemQueryBit "AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') AND [System.CreatedDate] > @Today - 1100 AND [System.CreatedDate] <= @Today - 1000 " +-WorkItemQueryBit "SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') AND [System.CreatedDate] > @Today - 1100 AND [System.CreatedDate] <= @Today - 1000 " Write-Host " " @@ -127,7 +127,7 @@ Write-Host "Migrate Work Items with Created Date between 1100 days ago and 1200 Write-Host " " & .\MigrateProject.ps1 ` -SkipMigrateWorkItems $WhatIf ` --WorkItemQueryBit "AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') AND [System.CreatedDate] > @Today - 1200 AND [System.CreatedDate] <= @Today - 1100 " +-WorkItemQueryBit "SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') AND [System.CreatedDate] > @Today - 1200 AND [System.CreatedDate] <= @Today - 1100 " Write-Host " " @@ -135,7 +135,7 @@ Write-Host "Migrate Work Items with Created Date between 1200 days ago and 1300 Write-Host " " & .\MigrateProject.ps1 ` -SkipMigrateWorkItems $WhatIf ` --WorkItemQueryBit "AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') AND [System.CreatedDate] > @Today - 1300 AND [System.CreatedDate] <= @Today - 1200 " +-WorkItemQueryBit "SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') AND [System.CreatedDate] > @Today - 1300 AND [System.CreatedDate] <= @Today - 1200 " Write-Host " " @@ -143,21 +143,21 @@ Write-Host "Migrate Work Items with Created Date between 1300 days ago and 1500 Write-Host " " & .\MigrateProject.ps1 ` -SkipMigrateWorkItems $WhatIf ` --WorkItemQueryBit "AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') AND [System.CreatedDate] > @Today - 1500 AND [System.CreatedDate] <= @Today - 1300 " +-WorkItemQueryBit "SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') AND [System.CreatedDate] > @Today - 1500 AND [System.CreatedDate] <= @Today - 1300 " Write-Host " " Write-Host "Migrate Work Items with Created Date between 1500 days ago and 3000 days ago" Write-Host " " & .\MigrateProject.ps1 ` -SkipMigrateWorkItems $WhatIf ` --WorkItemQueryBit "AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') AND [System.CreatedDate] > @Today - 3000 AND [System.CreatedDate] <= @Today - 1500 " +-WorkItemQueryBit "SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') AND [System.CreatedDate] > @Today - 3000 AND [System.CreatedDate] <= @Today - 1500 " Write-Host " " Write-Host "Migrate Work Items with Created Date less than 3000 days ago" Write-Host " " & .\MigrateProject.ps1 ` -SkipMigrateWorkItems $WhatIf ` --WorkItemQueryBit "AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') AND [System.CreatedDate] <= @Today - 3000 " +-WorkItemQueryBit "SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') AND [System.CreatedDate] <= @Today - 3000 " diff --git a/project-migration/Work-Item-Backfill_MIgrate_Project.ps1 b/project-migration/Work-Item-Backfill_MIgrate_Project.ps1 index 0a3e6e7..af87f90 100644 --- a/project-migration/Work-Item-Backfill_MIgrate_Project.ps1 +++ b/project-migration/Work-Item-Backfill_MIgrate_Project.ps1 @@ -19,7 +19,7 @@ Write-Host " " Write-Host "Migrate Work Items with Changed Date between 0 days Today and 'Number of Days Changed' ago" Write-Host " " -$queryBit = "AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') " +$queryBit = "SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = @TeamProject AND [System.WorkItemType] NOT IN ('Test Suite','Test Plan','Shared Steps','Shared Parameter','Feedback Request') " if($NumberOfDays -ne "") { $queryBit += "AND [System.ChangedDate] > @Today - $($NumberOfDays) " @@ -32,6 +32,7 @@ if($NumberOfDays -ne "") { if($ItemType -ne "") { $queryBit += "AND [System.WorkItemType] = '$($ItemType)' " } +$queryBit += "ORDER BY [System.ChangedDate] DESC" & .\MigrateProject.ps1 -SkipMigrateWorkItems $WhatIf -WorkItemQueryBit $queryBit diff --git a/tool-scripts/README - Tool-Scripts.md b/tool-scripts/README - Tool-Scripts.md index 7f51250..357a061 100644 --- a/tool-scripts/README - Tool-Scripts.md +++ b/tool-scripts/README - Tool-Scripts.md @@ -2,7 +2,6 @@ This directory contains helpful PowerShell scripts that can be used to perform specific actions outside of an ADO project migration or in aiding in the testing, validating and troubleshooting during an ADO project migration. - ## Files ### Clone-All-Project-Repos.ps1