ttlog

日々の開発で得た知見の技術メモ。モバイルアプリネタが多いです。

Azure DevOps(Boards)のWork ItemをOrganization間で移行する

はじめに

あまり無いことだとは思いますが、Azure DevOpsの情報を別Organization(企業)へ移行する必要が生じました。 Azure Reposのソースコードの移行はGitなので簡単に出来たのですが、Azure BoardsのWork Itemについてはなかなか情報が見つかりませんでした。 Azure DevOps CLIを使ってみたり、移行元でQueriesを使い全WorkItemをExcelにエクスポートし、移行先でインポートする方法などもありましたが、添付ファイル(Attachment)の移行が出来なかったり等、色々問題がありそうなので採用出来ず。 いろいろ調べた結果、Azure DevOps Migration ToolsというOSSツールを使用することである程度の移行が出来たため、手順を記録しておきます。

これらの手順を実行する場合は自己責任にてお願いします。

Azure DevOps Migration Tools とは

名前の通り、Azure DevOpsの移行用ツールです。C#で記述されているオープンソースのツールになります。移行対象はAzure Boards(Work Item)がメインですが、Azure Test Plansの移行もbeta版ですが提供されているようです。(2020年10月現在)

Windows専用ツールであり、Windows向けパッケージマネージャであるChocolateyからインストール出来ます。

公式サイトはこちらです。

また、GitHubリポジトリはこちらです。

注意点

このツールは公式サイトに以下の記載がある通り、初心者向けのツールではありません。Azure DevOpsの構造に精通していないと運用は難しいかと思います。

WARNING: This tool is not designed for a novice. This tool was developed to support the scenarios below, and the edge cases that have been encountered by the 30+ contributors from around the Azure DevOps community. You should be comfortable with the TFS/Azure DevOps object model, as well as debugging code in Visual Studio.

こんな記事を書いている私ですが、およそ精通してるとは言えないため、使い方が誤っている可能性は大いにあります...ご了承ください...

何が移行出来た?

  • タイトル
  • State(New, Active, Closed, etc.)
  • 親子関係
    • ただし、移行出来たものもあれば何故か出来なかった(Unparentになった)ものも...
  • コメント
  • 添付ファイル(Attachment)
  • Area
  • Iteration
  • Tags

etc...おおよそのものは移行できるのではないかと思います。

何が移行できなかった?

  • アサイン先(Assigned To)
    • 移行元のユーザのまま。(当たり前ですが)
    • あとでQueriesを使い移行元ユーザを抽出 → 一括で変更は出来たため、そこまで問題無し。
  • ブランチ、Pull Request等のLink情報
    • 移行自体は出来るけど、移行先のLink対象と一致せずエラーになり、結局は自分で設定し直すことに。

設定次第ではもしかしたら出来たかもしれないけど、私の知識では不可能でした。

移行手順

移行先プロジェクトのWork Itemを拡張する

移行先のWork Itemに移行状態を記載するというツールの仕様上、これを記載するためにWork ItemにCustom Fieldを追加する必要があります(※移行先のみ)。 まずはこのCustom Fieldを追加します。

Work Itemを拡張するためのInherited Processを作成する

  • Organization Settings > Boards > Processを開く。
  • Processesタブから、ベースとなるProcess(私の場合は”Agile")の右側の"..."をクリックし、"Create inherited process"を開く。
  • Process name, Descriptionを記述し、”Create process"を選択し、新しいProcessを作成する。

作成したInherited ProcessにField追加

  • 作成したProcessを選択し、"Bug"を選択する。
  • "Layout"タブから"New field"を選択する。
  • 表示されたポップアップで"Create a field"を選択し、以下を入力して"Add field"を選択する。
    • Name: "ReflectedWorkItemID"
    • Type: "Text (single line)"
  • 以上をWork Item Type全て(Epic, Feature, etc.)に適用する(何故か"Bug"に追加しただけで動作してしまったけど、恐らく全部に適用した方が良さそう?)

ここで設定した名前("ReflectedWorkItemID")は後述する設定ファイルに記述する名前になります。

移行先プロジェクトのProcessを作成したInherited Processに変更する

  • Organization Settings > Boards > Processを開く。
  • Processesタブから、移行先のプロジェクトが適用しているProcessを開く。
  • Projectsタブを開き、プロジェクト名右側の"..."をクリックし、"→ Change process"を選択する。
  • 新しく作成したProcessを選択し、保存する。

ちなみにProcessについては以下の記事が分かりやすく書いていただいており参考になります。
https://qiita.com/mstakaha1113/items/2c857e85ed6203d93028

Azure DevOps Migration Toolsのインストール

以下の二通りがあるようです。

  • (recommended)Install from Chocolatey
  • Download the latest release from GitHub and unzip

私は前者のChocolateyを使用しました。

  1. Chocolateyのインストール(https://chocolatey.org/install)
  2. コマンドプロンプトから以下を実行
    • choco install vsts-sync-migrator

成功するとc:\tools\vstssyncmigration\にインストールされ、この中のmigrate.exeを使用して移行します。

設定ファイルの作成

基本的には公式サイトのGetting Startedにサンプルの設定ファイルを含めて記載されています。

  1. コマンドプロンプトを開き、c:\tools\vstssyncmigration\へ移動する
  2. ./migration.exe initを実行
  3. configuration.jsonが作成されるので、それを編集する

私の場合はサンプルの設定ファイルを色々いじった結果、以下のようになりました。

{
  "Version": "11.0",
  "TelemetryEnableTrace": false,
  "workaroundForQuerySOAPBugEnabled": false,
  "Source": {
    "Collection": "https://dev.azure.com/{移行元Organization}",
    "Project": "{移行元プロジェクト名}",
    "ReflectedWorkItemIDFieldName": "ReflectedWorkItemID",
    "AllowCrossProjectLinking": false,
    "PersonalAccessToken": "{移行元で作成したPersonal Access Token(PAT)}",
    "LanguageMaps": {
      "AreaPath": "Area",
      "IterationPath": "Iteration"
    }
  },
  "Target": {
    "Collection": "https://dev.azure.com/{移行先Organization}",
    "Project": "{移行先プロジェクト名}",
    "ReflectedWorkItemIDFieldName": "ReflectedWorkItemID",
    "AllowCrossProjectLinking": false,
    "PersonalAccessToken": "{移行元で作成したPersonal Access Token(PAT)}",
    "LanguageMaps": {
      "AreaPath": "Area",
      "IterationPath": "Iteration"
    }
  },
  "GitRepoMapping": null,
  "Processors": [
    {
      "ObjectType": "NodeStructuresMigrationConfig",
      "PrefixProjectToNodes": false,
      "Enabled": true
    },
    {
      "ObjectType": "WorkItemMigrationConfig",
      "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,
      "SkipToFinalRevisedWorkItemType": false,
      "WorkItemCreateRetryLimit": 5,
      "FilterWorkItemsThatAlreadyExistInTarget": true,
      "PauseAfterEachWorkItem": false,
      "AttachmentMazSize": 480000000,
      "CollapseRevisions": false,
      "LinkMigrationSaveEachAsAdded": false
    }
  ]
}
  • "Version"はインストールしたAzure DevOps Migration Toolsのバージョンを記述
    • ./migration.exe --versionで確認
  • "Source"以下に移行元の情報を記述
  • "Target"以下に移行先の情報を記述
  • "ReflectedWorkItemIDFieldName"にはWork Itemを拡張した際に追加したCustom Fieldに指定した名前("ReflectedWorkItemID")を記述
  • "FieldMaps", "WorkItemTypeDefinition"は不要そうだったので削除
    • 移行元と移行先でFieldやWorkItemTypeが異なる場合のマッピング設定?
  • "Processors"内にそれぞれの"Enabled"はtrueに変更(trueにしないとそのProcessorが起動しない)

移行開始

以下のコマンドで移行ツールを起動します。

./migration.exe --config configuration.json

途中、移行元/移行先のMicrosoftアカウントへのログインが表示されるかもしれませんが、必要に応じてログインすれば続行するかと思います。

まとめ

私は以上の手順で、不完全ではありますが移行が出来ました。

最初に書きましたが、私自身あまりAzure DevOpsに詳しくなく、他のプロジェクトでも同様に移行できるかは全く不明なため、これらの手順を実行する場合はあくまで自己責任にてお願いします。