RedmineからJiraにスキームとデータを移行するツールを作ってみた

# はじめに
皆さん、課題やタスクの管理はどんなツールを使って行っていますか？まさか、まだExcelで管理しているなんて人はいませんよね。

業務の生産性を考えると、結構前から（平成の頃から）チケット管理ツール（ITS：Issue Tracking System）を使うのが主流になってきていると思います。

特に日本では、まず無料の「Redmine」を利用される方が多いと思います。弊社（NRI 野村総合研究所）でも同様に各部署のプロジェクト単位でRedmineを利用しているケースが見受けられました。

ただ、弊社では社内共用ツールとして「Atlassian Jira」を提供しており、機能の豊富さ、使い勝手からJiraへの移行の要望が複数挙がりました。

そこで今回は、RedmineのチケットをJiraに移行する仕組みを作ったので、簡単にその紹介を行いたいと思います。
# どんな仕組み？
ざっくり言うと以下の様な４ステップでスキームとデータを移行します。
![fig0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580859/ad5c6d18-e615-2d13-de2e-2cb846cf964f.png)
Redmineから各種定義情報をJira向けにxmlで抽出し、Jiraへスキーム・オブジェクトとしてインポートする形で設定し、その上で、RedmineのチケットをCSVで抽出し、最後にJira標準のCSVインポータでデータをインポートするツールたちです。

実装は、仕組みを一から作るのは大変なので、Jiraの3rd Partyプラグインの[ScriptRunner for Jira](https://marketplace.atlassian.com/apps/6820/scriptrunner-for-jira?hosting=server&tab=overview)を利用し、GroovyスクリプトでRESTエンドポイントを作成する形で行いました。
# 概要について
## 0) 準備
まず、移行元のRedmineとhttp(s)通信可能なネットワーク上に、作業用のJiraを用意します。移行先のJiraがこのネットワーク上にある（立てられる）場合、本稿の作業用のJiraは移行先のJiraと同一で問題ありません。

Jiraの用意が出来たら、ScriptRunnerの機能で、1)「Redmineのプロジェクト設定情報をXMLファイルにエクスポート」、2)「エクスポートしたXMLを、作業用Jiraと移行先Jiraのスキーム＆オブジェクトにインポート」、3)「Redmineのチケット情報をCSVファイルにエクスポート」、の3つのREST Endpointを作成します。

そして、Redmineの管理画面からREST通信を有効化します。これでRedmineのREST APIを外部から利用可能となります。
## 1) Redmineのプロジェクト設定情報をエクスポート
<img width="800" alt="fig1s.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580859/3c6d448a-8338-2fef-b3e1-167d1c1b0035.png">
まず、1)「Redmineのプロジェクト設定情報をXMLファイルにエクスポート」 REST Endpointに対しAPIコールを実行します。具体的には簡易的にcurlコマンドで認証情報を付与して実行すると固定名称のXMLファイルが、作業用Jiraサーバのホームディレクトリ配下に作成されます。

このXMLには、移行元Redmineの全プロジェクト情報（フィールド、ステータスなど）およびリスト値などが含まれています。
## 2) XMLをJiraにインポート
<img width="800" alt="fig2s.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580859/62691581-cb86-f838-b8da-a45da28cdfe6.png">
先のステップで作成されたXMLファイルをインプットパラメータとして、「エクスポートしたXMLを、作業用Jiraと移行先Jiraのスキーム＆オブジェクトにインポート」 REST Endpointに対しAPIコールを実行します。

これで、Redmineのチケット情報を取り込む準備ができました。
## 3) Redmineのチケットをエクスポート
<img width="800" alt="fig3s.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580859/751dd181-81f0-75fd-c669-68cc9a88e68d.png">
いよいよメインとなるRedmineのチケット情報のエクスポートです。

Redmineのプロジェクトキーをキーパラメータとして、3)「Redmineのチケット情報をCSVファイルにエクスポート」 REST Endpointに対しAPIコールを実行します。このAPIはプロジェクト単位でエクスポートする形としています。複数プロジェクトを指定することも可能です。

また、同時にJiraの項目とのマッピングファイル（次のCSVインポートで使用）を出力します。そのまま次のステップに進む場合、Redmine上のフィールドは同名のJiraカスタムフィールドに移行される形になりますが、このマッピングファイルを変更することで、Jira既存の項目や別名項目などに変換しながら移行することが可能です。
## 4) Jiraにチケットをインポート
<img width="800" alt="fig4s.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580859/7c05b0de-f108-d0f4-c18a-8025b93bb3e4.png">
最後に、CSV化されたRedmineのチケット情報をJiraにインポートします。この仕組みはJira標準のCSVインポータを利用する為、Jira画面からの操作となります。

添付ファイルを移行対象とする場合、添付ファイルのRedmine上のURLがCSVのカラムに入る為、インポート実行時もRedmineとhttp(s)通信が可能である必要があります。

インポートした後にJiraでチケットを確認すると、主に記号文字等が文字化けする場合があります。この場合、インプットのCSVの当該文字を置換して再度インポートする事で正常に取り込むことができます。
# 工夫（苦労）したところ
チケット情報の抽出処理がAPIの都合で1件ずつしか行えず、当初はかなり時間がかかりました。また抽出件数が増えると比例して処理時間が延びるような事もあり作りを見直す場面もありました。

また、本利用の際、Redmine上でユーザが非アクティブ化されたチケットがエラーで抽出できないというバグが発生し、原因究明に手間取ったりもしました。
# おわりに
今回の試みは処理を分割することで、データに人の手作業を介在させる事をポイントとしました。全自動は操作的には楽なのですが、予想外の結果になった時のリカバリーが効かない為、最終的には手作業で辻妻を合わせられるツールとすることで汎用化を図りました。
これにより、合計2万件強のチケットを約半日で移行する事が出来ました。

弊社asleadチームではこのような試みも行っています。

※asleadはTwitter上でも情報を発信しています。https://twitter.com/aslead_NRI