この投稿は Fujitsu Advent Calendar 2017GitLab Advent Calendar 2017 の 10日目 の記事です。(大幅遅刻です。ごめんなさい、ごめんなさい、ごめんなさい。)
この記事に書かれた見解は、個人のものであり、所属する会社・組織を代表するものではありません。


前フリを書いたら長くなってしまったので、それはばっさり後にまわして、いきなり本題からいきます。

migrate-redmine-to-gitlab

migrate-redmine-to-gitlabを使います。

どれくらいちゃんと移行できるのか

公式ドキュメント の記述に、実際にやった結果を補足しながらまとめてみます。

「移行可否」欄の凡例:
- ◎:問題なく移行できる。
- ○:移行できるが若干の問題あり。
- △:公式ドキュメントには移行できると書いてあるがやってみたらだめだった。
- ×:移行できない。

Redmine GitLab 移行可否 ○または△の詳細
チケット(issue) Issue
説明 Description TextileがMarkdownに変換されない(後述)
著者 Opened by ~ 移行を実行したユーザー(Access Tokenの持ち主)になる
追加日/終了日 メタデータではなくIssue本文に挿入される
例:(from redmine issue 1 created on 2017-12-10, closed on 2017-12-10)
コメント Comment TextileがMarkdownに変換されない(後述)
コメントの著者 ~ Commented 移行を実行したユーザー(Access Tokenの持ち主)になる
コメント日 メタデータではなくComment本文に挿入される
例:(from redmine: written on 2017-12-12)
 トラッカー Label
優先度 Label
ステータス Open/Closed open(未完了)かclosed(完了)かのみ
担当者 Assignee
チケット番号 Issue ID
関連チケット Related Issue ◎? Related Issue は GitLab EE の機能のため確認できず
添付ファイル Files
ロードマップ/バージョン Milestone
ウォッチャー Subscribe ×
ユーザー/グループ/ロール User/Group/Role × 予め GitLab 側に手で作成が必要
リポジトリ Repository ×
Wiki Wiki ×
タグ Label ×

実行環境

今回はお試しなので、Redmine と GitLab は これ用に Docker でさくっと立てました。

手順

公式ドキュメント 通りやれば OK なのですが、ハマりどころ、注意点などを補足しながら説明します。

1. 移行先の GitLab の準備

  1. プロジェクトを作る
    Redmine と同じ名前でなくてもかまいません。
  2. ユーザーを登録してプロジェクトのメンバーに追加する
    issue を作成する権限を持っていれば、プロジェクトが属するグループのメンバーでも、プロジェクトのメンバーでもかまいません。
    少なくとも、移行するチケットの担当者になっているユーザーは全員必要です。
    公式ドキュメントには「GitLab 側に対応するユーザーが見つからない場合は、admin ユーザー (root?) が担当者になります」と書いてありますが、実際には ERROR: Required users presence... FAILED というエラーになりました。
    GitLab の Username が Redmine の login (ログインID) と同じである必要はありませんが、同じにしておいた方が後で楽です。

重要: プロジェクトには、Milestone も Issue も無いことが条件になっています。

2. Redmine to Gitlab migrator のインストール

terminal
$ sudo pip install migrate-redmine-to-gitlab

3. config.json を書く

config.json
{
  "redmine": { "host":"https://forge.codelutin.com", "path":"projects/observe", "key": "XXX" },
  "gitlab": { "host":"https://gitlab.com", "path":"ultreia.io/ird-observe", "key": "XXX" }
}

Redmine の key

個人設定画面の右側のサイドバーになる「APIアクセスキー」です。
可能なら、システム管理者者権限を持ったユーザーのキーを使った方が後で楽です。

redmine-get-key.png

ここに「APIアクセスキー」が出ないときは、システム管理者の「管理」画面の、「設定」の「API」タブで「RESTによるWebサービスを有効にする」をONにします

GitLab の key

「User Settings」の「Access Tokens」で「Personal Access Token」を生成します。
gitlab-token-before.png

生成したトークンは生成直後の画面にしか表示されませんので、忘れずに控えておきましょう。
gitlab-token-after.png

4. 初期化

terminal
$ migrate-redmine-to-gitlab init
INFO: Create cache dir: ./redmine
INFO: Init <migrate_redmine_to_gitlab.commands.Init object at 0x7fee....7860>
INFO: Got redmine project: 1
INFO: Go gitlab project 1
INFO: Redmine Cache dir: ./redmine
INFO: Project file project to ./redmine/project.json
INFO: Run <migrate_redmine_to_gitlab.commands.Init object at 0x7fee....7860>
:
INFO: End <migrate_redmine_to_gitlab.commands.Init object at 0x7fee....7860>

この段階で、Redmine 側の情報を全て持ってくるようです。
完了すると、こういうディレクトリ構造ができていると思います。

.
├── config.json
└── redmine
    ├── attachments
    ├── issues
    ├── project.json
    ├── users
    └── versions

前述の「Textile が Markdown に変換されない」問題は、この段階で Pandoc 等で変換しておくことができると思います。
今回はそこまでやりませんでした。そのうちやって、続編を書きたい。

5. ユーザーの対応づけ

redmine/users1.json, 2.json のようなファイルが Redmine のユーザーの数だけ入っています。
これをひとつひとつ編集して、login (ログインID) の値を、対応する GitLab の Username に書き換えます。
前述のように、
- config.json に設定する Redmine の「APIアクセスキー」をシステム管理者権限を持ったユーザーの物にしておくと、全ユーザの login が取得できているはずです。一般ユーザーの物だとそのユーザー以外の login が取得できないので、全部手で入力しないといけません。
- Redmine の login と GitLabの Username を同じにしておけば、この書き換えは必要ありません。ただし、最低限 adminroot に変える必要はあるでしょう。

5.json
{
    "id": 5,
    "login": "jeffi7",
    "firstname": "jeff",
    "lastname": "inoue",
    "mail": "jeffi7@example.com",
    "created_on": "2017-12-12T08:05:34Z",
    "last_login_on": "2017-12-12T09:45:48Z",
    "api_key": "d9617fd..............7608eeb",
    "status": 1
}

上記は見やすくするために整形してありますが、実際にはインラインで入っています。

ここで不足があると、後のチケットの移行のときにこのようなエラーになります。

ERROR: Required users presence... FAILED

6. ロードマップ(バージョン) の移行

Redmine のロードマップ(バージョン) を GitLab の Milestone に移行します。

terminal
$ migrate-redmine-to-gitlab roadmap
INFO: Init <migrate_redmine_to_gitlab.commands.Versions object at 0x7fe09a748860>
:
INFO: 2 version(s) created on GitLab
INFO: End <migrate_redmine_to_gitlab.commands.Versions object at 0x7fe09a748860>

7. 添付ファイルの移行

terminal
$ migrate-redmine-to-gitlab attachments
INFO: Init <migrate_redmine_to_gitlab.commands.Attachments object at 0x7fa3b3244828>
:
INFO: 1 attachments(s) created on GitLab
INFO: End <migrate_redmine_to_gitlab.commands.Attachments object at 0x7fa3b3244828>

8. チケットの移行

Redmine のチケットを GitLab の Issue に移行します。
タイトルに Redmine のチケットID を付けない方法と、付ける方法とがあります。
チケットID を付けておくと、次のステップで GitLab の Issue ID を Redmine の チケットID と同じにすることができます。

チケットIDを付けない方法

terminal
$ migrate-redmine-to-gitlab issues
:
INFO: 5 issue(s) created on GitLab
INFO: End <migrate_redmine_to_gitlab.commands.Issues object at 0x7fe20289c828>

チケットIDを付ける方法

terminal
$ migrate-redmine-to-gitlab issues-with-id
:
INFO: 5 issue(s) created on GitLab
INFO: End <migrate_redmine_to_gitlab.commands.IssuesWithId object at 0x7fe20289c828>

9. チケットIDの移行

前述のように、タイトルに Redmine のチケットID を付けて Issue を移行しておくと、ID を Redmine と同じにできます。
ただし、GitLab API ではなく直接 GitLab のデータベースにアクセスして書き換えますので、GitLab が動いているマシン上で migrate-redmine-to-gitlab を実行する必要があります。
(今回はそこまでやりませんでした。そのうちやって、続編を(以下同文)

ここまでで、移行は実質的に完了です。

下記のスクリーンショットでは、移行後に Label に色をつけたり、優先順位をつけたりしてあります。
gitlab-completed.png
gitlab-imported-issue#1.png

10. Redmine から GitLab にリンクを張る

移行元の Redmine をもう使わないなら、以降の処理は必要ないと思います。

Redmine のバージョンから GitLab Milestone にリンク

$ migrate-redmine-to-gitlab link-roadmap
:
INFO: Link redmine version 1 (Ver1) to gitlab milestone 1
:
INFO: Link redmine version 2 (Ver2) to gitlab milestone 2
:
INFO: End <migrate_redmine_to_gitlab.commands.LinkRedmineRoadmap object at 0x7ff2ba0d8828>

こんな風になります。
redmine-roadmap-after.png

Redmine のチケットから GitLab Milestone にリンク

実行してみたらエラーになってしまったのですが、使わないと思ったので原因は調べていません。
(そのうち...これはやらないかな。)

$ migrate-redmine-to-gitlab link-issues
INFO: Init <migrate_redmine_to_gitlab.commands.LinkRedmineIssue object at 0x7fd680b3e898>
INFO: Got redmine project: 1
INFO: Go gitlab project 1
INFO: Redmine Cache dir: ./redmine
INFO: Project file project to ./redmine/project.json
INFO: Run <migrate_redmine_to_gitlab.commands.LinkRedmineIssue object at 0x7fd680b3e898>
INFO: Start <migrate_redmine_to_gitlab.commands.LinkRedmineIssue object at 0x7fd680b3e898>
INFO: Got 5 issue(s) from redmine.
INFO: Got 5 issue(s) from gitlab.
Traceback (most recent call last):
  File "/usr/bin/migrate-redmine-to-gitlab", line 11, in <module>
    load_entry_point('migrate-redmine-to-gitlab==2.0.2', 'console_scripts', 'migrate-redmine-to-gitlab')()
  File "/usr/lib/python3.6/site-packages/migrate_redmine_to_gitlab/commands.py", line 91, in main
    args.command(config, args).run()
  File "/usr/lib/python3.6/site-packages/migrate_redmine_to_gitlab/commands.py", line 107, in run
    self.execute()
  File "/usr/lib/python3.6/site-packages/migrate_redmine_to_gitlab/commands.py", line 575, in execute
    gitlab_issue = gitlab_issues_index[subject]
KeyError: 'シンプルなチケット'

前フリに書くはずだった後書き

私のチームでは、社内の開発者向けに、GitLab で「コードホスティングサービス」や、アジャイル開発の現場支援を提供しています。
(詳しく知りたい社内の人はグローバルコミュニケーション基盤で私のプロフィールを見てください。)
外部イシュートラッカーとして Redmine を GitLab と連携させて使っているチームが多いのですが、Baclogs プラグインの開発が本家で止まって久しいところへ、最近 GitLab が、
- イシューボード(カンバンボード)と優先順位付きラベル
- バーンダウンチャート (現状 EE のみ。CEにも搭載予定。)
- 関連イシュー (EE のみ)
等の機能が追加されるなど、イシュートラッカーとしても Redmine と肩を並べるようになってきたので、これからは GitLab だけで完結させたい機運が高まってきました。できれば Redmine に溜まった過去のチケットも GitLab に移行したいと思いました。

同じ課題を抱えている人が他にもいるに違いないと思ってググってみると見つかるのがオープンソースのすばらしいところ。このふたつが見つかりました。
- Redmine to Gitlab migrator
- Migrate Redmine to GitLab
よく見てみると、前者は約2年前で更新が止まっており、これをフォークして開発を継続しているのが後者のようです。後者の Migrate Redmine to Gitlab を試してみることにしました。

ToDo

  • Textile から Markdown に変換してみる
  • チケット ID の移行もやってみる
  • 実際の Redmine プロジェクトを移行してみる