nkdAgility / azure-devops-migration-tools

Azure DevOps Migration Tools allow you to migrate Teams, Backlogs, Work Items, Tasks, Test Cases, and Plans & Suits from one Project to another in Azure DevOps / TFS both within the same Organisation, and between Organisations.
https://nkdagility.com/learn/azure-devops-migration-tools/
GNU Affero General Public License v3.0
498 stars 330 forks source link

WorkItemUpdate seem to use a hardcoded ReflectedWorkItemIDFieldName #445

Closed cbezenco closed 4 years ago

cbezenco commented 4 years ago

Context : VSTS to VSTS project migration [Info]: SessionID: 5312f9d4-da5d-4d5d-80ef-3cc52bea1f13

WorkItemUpdate processor is not using the ReflectedWorkItemIDFieldName configured in my Target project. We can see in the log below that WorkItemMigration found the proper field but it looks like WorkItemUpdate is looking for TFS based field and not using the config.

Is WorkItemUpdate only working with TFS ?

Extract of logs below.

DONE in 0 hours 0 minutes 0:348 seconds migration.exe Information: 0 : Migration Context Complete TeamMigrationContext migration.exe Information: 0 : Migration Context Start WorkItemMigration WorkItemMigration: Replay all revisions of 139 work items? WorkItemMigration: Found target project as CS Found 'Custom.ReflectedWorkItemId' in this project, proceeding. DONE in 0 hours 0 minutes 1:225 seconds migration.exe Information: 0 : Migration Context Complete WorkItemMigration migration.exe Information: 0 : ProcessingContext Start WorkItemUpdate migration.exe Warning: 0 : [EXCEPTION] Microsoft.TeamFoundation.WorkItemTracking.Client.ValidationException: TF51005: The query references a field that does not exist. The error is caused by «[TfsMigrationTool.ReflectedWorkItemId]». at Microsoft.TeamFoundation.WorkItemTracking.Client.Query.Initialize(WorkItemStore store, String wiql, IDictionary context, Int32[] ids, Int32[] revs, Boolean dayPrecision) at Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItemStore.Query(String wiql, IDictionary context) at VstsSyncMigrator.Engine.TfsQueryContext.Execute() in d:\a\1\s\src\VstsSyncMigrator.Core\Execution\ComponentContext\TfsQueryContext.cs:line 70

gocoelho commented 4 years ago

Could you share your config.json the sessions you configured ReflectedWorkItemId fields

cbezenco commented 4 years ago

I edited Source / Target's Project/Collection for privacy reason. Thanks for feedback

{ "Version": "8.7", "TelemetryEnableTrace": false, "workaroundForQuerySOAPBugEnabled": false, "Source": { "Collection": "https://dev.azure.com/demo/", "Project": "Srouce", "AllowCrossProjectLinking": false, "PersonalAccessToken": "" }, "Target": { "Collection": "https://dev.azure.com/demo/", "Project": "Destination", "ReflectedWorkItemIDFieldName": "Custom.ReflectedWorkItemId", "AllowCrossProjectLinking": false, "PersonalAccessToken": "" }, "FieldMaps": [], "WorkItemTypeDefinition": { "Activity": "Activity", "Issue": "Issue" }, "GitRepoMapping": null, "Processors": [ { "ObjectType": "VstsSyncMigrator.Engine.Configuration.Processing.NodeStructuresMigrationConfig", "PrefixProjectToNodes": false, "Enabled" : true }, { "ObjectType": "VstsSyncMigrator.Engine.Configuration.Processing.TeamMigrationConfig", "Enabled": true, "EnableTeamSettingsMigration": true, "PrefixProjectToNodes": false }, { "ObjectType": "VstsSyncMigrator.Engine.Configuration.Processing.WorkItemMigrationConfig", "ReplayRevisions": true, "PrefixProjectToNodes": false, "UpdateCreatedDate": true, "UpdateCreatedBy": true, "UpdateSourceReflectedId": true, "BuildFieldTable": false, "AppendMigrationToolSignatureFooter": false, "QueryBit": "AND [Microsoft.VSTS.Common.ClosedDate] = '' 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, "WorkItemCreateRetryLimit": 5, "FilterWorkItemsThatAlreadyExistInTarget": true, "PauseAfterEachWorkItem": false, "AttachmentMazSize": 480000000 }, { "ObjectType": "VstsSyncMigrator.Engine.Configuration.Processing.WorkItemMigrationConfig", "QueryBit":"AND ([System.ExternalLinkCount] > 0 OR [System.RelatedLinkCount] > 0)" }, { "ObjectType": "VstsSyncMigrator.Engine.Configuration.Processing.WorkItemUpdateConfig", "Enabled": true } ] }

cbezenco commented 4 years ago

I just realized that I had 2 entries for WorkItemMigrationConfig. I removed the second one and I still get the same error (I did a successful full sync of 139 items in a previous session):

WorkItemMigration: Replay all revisions of 139 work items? WorkItemMigration: Found target project as CS Found 'Custom.ReflectedWorkItemId' in this project, proceeding. DONE in 0 hours 0 minutes 2:532 seconds migration.exe Information: 0 : Migration Context Complete WorkItemMigration migration.exe Information: 0 : ProcessingContext Start WorkItemUpdate migration.exe Warning: 0 : [EXCEPTION] Microsoft.TeamFoundation.WorkItemTracking.Client.ValidationException: TF51005: The query references a field that does not exist. The error is caused by «[TfsMigrationTool.ReflectedWorkItemId]». at Microsoft.TeamFoundation.WorkItemTracking.Client.Query.Initialize(WorkItemStore store, String wiql, IDictionary context, Int32[] ids, Int32[] revs, Boolean dayPrecision) at Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItemStore.Query(String wiql, IDictionary context) at VstsSyncMigrator.Engine.TfsQueryContext.Execute() in d:\a\1\s\src\VstsSyncMigrator.Core\Execution\ComponentContext\TfsQueryContext.cs:line 70 migration.exe Warning: 0 : [EXCEPTION] Microsoft.TeamFoundation.WorkItemTracking.Client.ValidationException: TF51005: The query references a field that does not exist. The error is caused by «[TfsMigrationTool.ReflectedWorkItemId]». at Microsoft.TeamFoundation.WorkItemTracking.Client.Query.Initialize(WorkItemStore store, String wiql, IDictionary context, Int32[] ids, Int32[] revs, Boolean dayPrecision) at Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItemStore.Query(String wiql, IDictionary context) at VstsSyncMigrator.Engine.TfsQueryContext.Execute() in d:\a\1\s\src\VstsSyncMigrator.Core\Execution\ComponentContext\TfsQueryContext.cs:line 97 at VstsSyncMigrator.Engine.WorkItemUpdate.InternalExecute() in d:\a\1\s\src\VstsSyncMigrator.Core\Execution\ProcessingContext\WorkItemUpdate.cs:line 42 at VstsSyncMigrator.Engine.ProcessingContextBase.Execute() in d:\a\1\s\src\VstsSyncMigrator.Core\Execution\ProcessingContext\ProcessingContextBase.cs:line 44 MigrationEngine: The Processor WorkItemUpdate entered the failed state...stopping run

cbezenco commented 4 years ago

Ok I am not familiar with the code but I went through a VS debug session...

Stepping through I can see that the tfsqc.AddParameter line of code at line 40 in WorkItemUpdate.cs does only update the name of the @TeamProject (me.Target.Config.Project)

_TfsQueryContext tfsqc = new TfsQueryContext(targetStore); tfsqc.AddParameter("TeamProject", me.Target.Config.Project); tfsqc.Query = string.Format(@"SELECT [System.Id], [System.Tags] FROM WorkItems WHERE [System.TeamProject] = @TeamProject {0} ORDER BY [System.ChangedDate] desc", config.QueryBit); WorkItemCollection workitems = tfsqc.Execute();

I can see _config.QueryBit is hard-coded to TfsMigrationTool.ReflectedWorkItemId in WorkItemUpdateConfig.cs at line 27 in the class constructor.

QueryBit = @"AND [TfsMigrationTool.ReflectedWorkItemId] = '' AND..

I am not familiar with overall architecture. Any suggestion how to best fix this ?

If I understood correctly line 27 is set before the config file is processed...

cbezenco commented 4 years ago

I really wanted to get the WorkItemUpdate working so I removed "AND [TfsMigrationTool.ReflectedWorkItemId] = '' from the QueryBit. It worked BUT I was quite disappointed by the result... The Processor name made me thing that it would sync updates made on the source into the target but this was a wrong expectation... WorkItemUpdate is doing a workitem.IsDirty on the target instance. It is not doing a source / destination check so I am really not sure I understand the purpose of this check and I find the WorkItemUpdate documentation miss-leading.

gocoelho commented 4 years ago

You really create the Custom field on target Project with the name ""Custom.ReflectedWorkItemId"?

You should try just "ReflectedWorkItemIDFieldName": "ReflectedWorkItemId"

On my projects, (target and source)... I just create the field with name "ReflectedWorkItemId" for both sides and configure configuration.json like this too.

Do you already try this way?

gocoelho commented 4 years ago

I don't know if it will help you, but I'm using version 8.0.3

configuration.json had a different structure, but I find one for me.

I just had problems when source workitens have a removed iteration or area in they history... no matter if you choose to replayrevivision or not

cbezenco commented 4 years ago

You really create the Custom field on target Project with the name ""Custom.ReflectedWorkItemId"?

You should try just "ReflectedWorkItemIDFieldName": "ReflectedWorkItemId"

On my projects, (target and source)... I just create the field with name "ReflectedWorkItemId" for both sides and configure configuration.json like this too.

Do you already try this way?

Yes I tried. It did not work for me. After using the Process Explorer tool, I discovered that it was call "Custom.ReflectedWorkItemId" and when I used this it worked...

My setup is VSTS project -> VSTS project and my projected are using inherited template.

StefanoTurrini commented 4 years ago

I agree with @cbezenco .... WorkItemUdpate work ONLY on target project, unfortunately... Noone syncing from the source...

github-actions[bot] commented 4 years ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 10 days