Migrate Azure DevOps work item queries to a new organization
Tags: devops, azure, api, rest
Published: 2019-12-18 05:07:55

> Note: I originally published this article on Medium on 12/6/2019

At [Blue Chip Consulting Group](https://www.bluechip-llc.com/), we are often brought in to help companies with mergers and acquisitions. Sometimes this means moving [Azure DevOps](https://azure.microsoft.com/en-us/services/devops/?nav=min) projects from one organization to another.

There are several reliable tools to help with this type of work. The [Azure DevOps Migration Tools](https://github.com/nkdAgility/azure-devops-migration-tools) project is a decent open source option which handles several key aspects of migration very well. Unfortunately, it's not well documented and [requires a deep understanding](https://nkdagility.github.io/azure-devops-migration-tools/) of how to configure each task. [OpsHub has a nice commercial offering](https://www.opshub.com/products/opshub-visual-studio-migration-utility/) which we've used with great success, but it focuses mostly on the migration of work items and expects core pieces such as areas, iterations, and user accounts to be set up ahead of time.

A recent engagement had a project with dozens of custom shared queries which needed to be migrated. I tried using the DevOps Migration Tool to accomplish this, but was unsuccessful after several tries so I went to the [Azure DevOps REST API documentation](https://docs.microsoft.com/en-us/rest/api/azure/devops/wit/queries?view=azure-devops-rest-5.1) to see what it would take to write something myself. It turns out that the query and create payloads looked very similar, so I decided to roll my own solution.

I typically work in C#, but decided to go with Powershell because of the [dynamic handling of Json payloads](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/convertfrom-json?view=powershell-6) that it offers. It was apparent from the documentation and some sample requests I tested in [Postman](https://www.getpostman.com/) that a recursive enumeration of the [Get result](https://docs.microsoft.com/en-us/rest/api/azure/devops/wit/queries/get?view=azure-devops-rest-5.1) would be easy to pipe into the target DevOps instance to [create the queries](https://docs.microsoft.com/en-us/rest/api/azure/devops/wit/queries/create?view=azure-devops-rest-5.1) in the target organization.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/7bnvrcyuftnyar9q5i9l.jpeg)

The script requires a few items to be in place before you run it
* **The project name** : the script assumes you're moving the queries to a project with the same name in the destination DevOps organization. If you're targeting a different instance it should be an easy tweak to the PowerShell script to introduce a different target project name
* **The source and target organization names** : These are the custom url segments that identify the organization and follow dev.visualstudio.com in the DevOps base url. This script will work even if you are using the old url format of <organization>.visualstudio.com.
* **Personal Access Tokens for each organization** : The source organization requires Work Item Read and the target organization required Work Item Read/Write. [Here's an article that shows how to create a PAT in your DevOps instance](https://docs.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=preview-page).

You'll want to set up [areas and iterations](https://docs.microsoft.com/en-us/azure/devops/organizations/settings/about-areas-iterations?view=azure-devops) in the target organization before running this script if your queries depend on them. DevOps Migration Tools handles this well if you enable the NodeStructuresMigrationConfig processor. Doing so is as easy as using these settings for the [configuration.json](https://github.com/nkdAgility/azure-devops-migration-tools/blob/master/docs/configuration.md):
```json
 "Processors": [
 {
   "ObjectType": "VstsSyncMigrator.Engine.Configuration.Processing.NodeStructuresMigrationConfig",
   "PrefixProjectToNodes": false,
   "Enabled": true
 },
 …
 ]
```
And that's it. The script can be executed multiple times. It'll skip queries with the same name and folder hierarchy location in the destination organization.

The script can be found in [this GitHub repository](https://github.com/jkewley/AzureDevOpsQueryMigration).