Trac を Redmine 経由で GitLab に移行する

[Trac/Redmine+Subversion+Jenkinsなどを捨ててGitLabに移行するまでの道のり](https://qiita.com/hkato/items/3ddfe72985f7536bdf97)

## 概要

![overview](http://www.plantuml.com/plantuml/png/nPGnRuCm48LtViKfNPB1KQHsWQ7AKALBXwhg7btCXRZ1DZeVRNv-eIH3B1oXTYXCcFVTlNk7M0T1bjRMMOCiHfi6dS3idL73l3H1UxUOmTs-krQhB3vNZx6q0EcULHk87LfItU4diH1VrxUcOXJQxjdRRKyi6Oy4yoyZ1sXGz64nkoRUgBJ64Tml7vOdy0wUl3uITzumx-ziKiqHnzF1IS82pYDFhvkQBKg01vMgZDIuKqDr7wlER_i5A8iEAxBa918z6td1tLYA2Nxm6MFzi4me1BqyP2cBjwSie281zbXQRBBqebLN9DcXk1IuRIBDNzQMvbCH6Dju5h2cfY3UqPzYC26q57wVmi3_LmYNzh4YpT7fXslOVv2MqQzq_ig-RBMOuLUKvvjDde-t66TwTrTTrkJArjRV)

## 環境とツール

### 環境

- Trac 1.0.3 + SQLite3 (本番ソース CentOS7 EPEL 版)
- Redmine 3.4.13 (一時作業用 on Docker)
- GitLab 13.1.4 (一時作業用 on Docker)
- GitLab 13.1.4 (本番ターゲット CentOS7 Omnibus 版)

### ツール

- [Trac username converter](https://github.com/hkato/trac-username-converter)
- [Redmine: migrate from Trac patch](https://github.com/hkato/migrate_from_trac.rake)
- [gitlab-user-management](https://github.com/msawady/gitlab-user-management)
- [Redmine to Gitlab migrator](https://github.com/redmine-gitlab-migrator/redmine-gitlab-migrator)

## Ticket/Issue Id について

- Trac: プロジェクトごとに Id が割り振られる
- Redmine: システムとして Id が割り振られる、他のプロジェクトから影響を受ける
- GitLab: プロジェクト毎に Id が割り振られる

Trac → GitLab は相性がよい
Redmine って…　複数インスタンスを統合するときに、なかなかの苦労が必要な様だ。

参考: [Redmineサーバ統合事例](https://qiita.com/y503Unavailable/items/b84953bab417e5a0560c)

## 作業インスタンスでの変換

以下、私のやった方法です。

同一マシンで Redmine, GitLab を Docker で動かし、さらに移行ツールも動かすと Docker にそれなりのメモリ割り当てしないと辛かったです。私は 16GB の macOS 上で Docker Desktop for Mac に 8GB 割り当てました。いきなり本番環境に移すのは…リスク覚悟で。捨てるインスタンスなのでクラウド上に一時的に環境を用意するのも良い。

また、前述した Ticket/Issue Id の関係もあり、中間となる Redmine はプロジェクト毎に初期化したい。このことからも Docker などで作っては消すが良い。

- 参考
  - GitLab Docs > Installation > Requirements > Hardware requirements > [Memory](https://docs.gitlab.com/ee/install/requirements.html#memory)
  - [redmineサーバの適正スペックについて](https://teratail.com/questions/3763) - teratail

### 1. Redmine を Docker で立ち上げる

[いまさらだけどTracからRedmineに移行する](https://qiita.com/hkato/items/8783b3316089b5033923)

起動後はもちろん admin の初期パスワード設定。

Trac のインスタンスは立ち上げている必要なし(SQLite3 の場合だが…他のデータベース利用の場合はどうなんでしょう)。 db/trac.db や attachments などのあるプロジェクトディレクトリがあれば良い。

### 2. Trac から Redmine に移行

同様に上記の記事。
Trac のユーザ名が Redmine そして GitLab と異なる場合やチケット Owner のテキストフィールドにシステム上に存在するユーザー名以外の文字列を入れたりしている場合は、次の方法で trac.db を変換してから Redmine に移行。

[いまさらだけどTracからRedmineに移行する（ユーザー名変換）](https://qiita.com/hkato/items/1722cf3cb93a8b10b95a)

### 3. GitLab を Docker で立ち上げる

[最小限のGitLab環境を作る（移行テスト用）
](https://qiita.com/hkato/items/50054c0c0d84634be5e2)

もちろん root の初期パスワード設定。

### 4. API Key の取得

双方の REST API を使って移行するので Redmine, GitLab ともに API Key / Access Token を取得。

こちらの Key の取得方法を参照
[Redmine のプロジェクトを GitLab Issues へ移行する](https://qiita.com/jeffi7/items/75834ca22b9ddf473ed1)

#### Redmine

- 管理
  - "API" タブ
    - "RESTによるWebサービスを有効にする" のチェックをON
- admin ログイン
  - 個人設定
    - APIアクセスキー を表示し メモ

#### GitLab

Administrator login > Profile Settings > Access Tokens で生成。

最近のバージョンでは API の用途別でどの権限を与えるかのチェックが細かくなってます。まあ、一時的な作業場なので全部有効でも良いでしょう(私は、絞って検証してません)。

### 5. GitLab にユーザーを追加

Trac から Redmine に移行したユーザー一覧から admin と trac のユーザー以外を GitLab に追加。

ユーザー数が少ない場合は手でやっても良いかと。

私は、こちらで CSV を作って登録しました。

- [【GitLab】【Python】GitLabにユーザーを一括で登録、グループ参加](https://www.msawady.com/entry/2018/02/04/205432) - msawady’s tech-note - Haten Blog
- [gitlab-user-management](https://github.com/msawady/gitlab-user-management) - GitHub

### 6. Redmine から GitLab に移行

#### 移行ツールの準備

[Redmine to Gitlab migrator](https://github.com/redmine-gitlab-migrator/redmine-gitlab-migrator) - GitHub

pip install の例があるが、PyPI にあるものは古く動作しないので、GitHub 上のソースからインストールする。

```sh
$ git clone https://github.com/redmine-gitlab-migrator/redmine-gitlab-migrator.git
$ cd redmine-gitlab-migrator
$ python -m venv venv
$ source venv/bin/activate
$ ./setup.py install
```

また Textile → Markdown の変換のために Pandoc を呼び出しているので、Pandoc をインストールしする。

```sh
$ brew install pandoc       # macOS
$ apt install pandoc        # Debian/Ubuntu
$ yum install pandoc        # CentOS/RHEL
```

#### 実際の移行

Redmine to Gitlab migrator のドキュメントの通りだが…
適宜オプションを指定してください。

##### Gitlab グループとプロジェクトの作成とユーザーの追加

事前にグループとプロジェクトを追加しメンバーを追加しておく。
結局このプロジェクトは一時的なものなので、最終的に本番環境へエクスポート・インポートするので、`migrate/proj1` とか仮のグループ名・プロジェクト名でも良い。

##### roadmap/milestone

```sh
migrate-rg roadmap --redmine-key xxxx --gitlab-key xxxx \
  <redmine project url> <gitlab project url> --check
```

チェックが通れば、--check　を外し実際の移行処理。

##### issue/ticket

```sh
migrate-rg issues --redmine-key xxxx --gitlab-key xxxx \
  https://redmine.example.com/projects/myproject \
  http://git.example.com/mygroup/myproject --check --keep-id
```

チェックが通れば、--check を外し実際の移行処理。

##### Wiki

うまくいきませんでした。
Wiki は GitLab Wiki に移行するというのもありますが、GitLab Pages に移行するという手もあるのと、とりあえず自分が移行させたい Trac/Redmine プロジェクトは開発の収束したプロジェクトで現在 Wiki を書き換えてプロジェクト推進するという体制ではないので、とりあえず放置。

Wiki を積極活用せずスタートページに概要がある程度かつ履歴不要のプロジェクトに関しては、[Wikiページを他の形式にエクスポート](http://blog.redmine.jp/articles/new-feature-1_4/export-all-wiki-pages/)し Pandoc を使って Markdown に変換しました。

細かいことは後で考えます…。

## 本番環境への移行

公式ドキュメントによる手順はこちら

GitLab Docs > User Docs > Projects > Project settings > [Project import/export](https://docs.gitlab.com/ee/user/project/settings/import_export.html)

### 作業インスタンスからエクスポート

一時作業用の GitLab からエクスポートします。
エクスポートする前にある程度チケット等の内容を関係者各位と確認をしてからがよいでしょう。私は Trac → Redmine → GitLab のユーザー登録時のマッピングテーブルなどを間違えて何度かやり直しました。

### 本番環境へのインポート

root/Administrator あるいは同等の権限があるアカウントでログインし実行すること。管理者権限のないアカウントで実行すると Issue の担当者はインポートしたユーザーなってしまいます。

## リポジトリーの移行

インポート直後のプロジェクトには他のリポジトリーから移行させるか空のリポジトリを作るかの選択がでてくるので、

- すでに別な場所にリモートリポジトリーを作成していれば、そのURLからインポートしてくれる
- 空のリポジトリーを作成した場合は、普通の Git の操作で
  - [いまさらだけどSubversionからGitへ移行する（その1: リポジトリー変換）](https://qiita.com/hkato/items/1b092bff149b13f77505)

## くりかえし

Trac プロジェクトの数だけ、 一時作業用 Redmine/GitLab を毎回潰しては再構築し、本番環境にインポートを繰り返し。(作業用 GitLab に関しては潰さなくても良いがユーザーの追加を API 経由で行ったとき重複するとエラーになり面倒なので、私は毎回壊して再構築した)

## まとめ（Trac → GitLab）

- Milestone や Issue はそれなりにいい感じで移行でき、事前にきちんとユーザーを作成してあれば、そのユーザのまま Issue を移行できた。また Trac ticket Id → GitLab issue Id は同じ番号のまま揃って移行できる
- Wiki は変換できないので後日楽な方法を考える

## つづく

次は、チケット/Issue Id がシステムで一意のため、プロジェクト毎に番号が歯抜となる仕様の Redmine の移行かなぁ。