TracからJIRAへのデータ移行

BTSの移行の一番やっかいな部分は既存データの移行だと思います。他のBTSからJIRAへのデータ移行については、次の資料にまとまっています。
他の課題管理ツールから移行する - JIRA (ジラ) 関連資料 - Go2Group Wiki
Tracからの移行の場合にはビルトインのインポータは存在しないので、ここで挙げられているスクリプトを使うことにしました。JIRAとしてデータインポート方法は次のような方法があり、

  • CSVファイルからのインポート
  • Jelly(XMLベースのスクリプトエンジン)スクリプトからのインポート
  • RPC(SOAP or XML RPC)を使う
  • 直接DBにデータを登録する

紹介されているサードパーティスクリプトはCSVもしくはJellyを使っています。今回は、Jellyを使う次のスクリプトを使いました。
yet another Trac 2 JIRA import - JIRA Community Space - Atlassian Documentation - Confluence
このスクリプトでは、

  • プロジェクトは作成してくれる
  • Tracと同一のユーザをJIRAで作成しておけばユーザも移行してくれる
  • チケットのコメント・添付ファイルも移行してくれる
  • TracのマイルストーンはJIRAのバージョンに移行される

私の環境では、Tracのバージョンが0.10.4、Pythonのバージョンが2.5で、yatrac2jira-v2.py というスクリプトを使いました。使用方法は、Tracのサーバにて次のように実行します。

python yatrac2jira-v2.py <Tracの対象プロジェクトのパス> <JIRAでのタグ> <JIRAでのプロジェクトオーナーのユーザID> > output.jelly

日本語ファイル名の添付ファイルがあると、192行目付近の添付ファイルの処理でurllib.quoteでKeyErrorが発生しました。

print '<jira:AttachFile key="${key}" filepath="' + env.path + "/attachments/ticket/" + str(ticket.id) + "/" + urllib.quote(ch[4]) + '" option="override"/>'

とりあえず、次のようにencode()を追加したところOKでした。

print '<jira:AttachFile key="${key}" filepath="' + env.path + "/attachments/ticket/" + str(ticket.id) + "/" + urllib.quote(ch[4].encode) + '" option="override"/>'

また、Tracでのチケットタイプと優先度を変更している場合には、スクリプト内でマッピングを追加しておく必要があります。

def mapIssueType(type):
    type = type.capitalize();
    if type == "Enhancement":
        return "Improvement"
    elif type == "Defect":
        return "Bug"
    elif type == "Task":
        return "Task"
    elif type == "Highlevel":
        return "Improvement"
    sys.stderr.write("Fallback to Bug for "+type+"\n")
    return "Bug"

def mapPriority(p):
    #if p == "major" or p == "minor" or p == "normal" or p == "trivial" or p == "critical":
    #return p.capitalize();
    p = p.capitalize();

    if p == "Highest":
        return "Blocker"
    if p == "Blocker":
        return "Blocker"
    if p == "High":
        return "Critical"
    if p == "Critical":
        return "Critical"
    if p == "Medium":
        return "Major"
    if p == "Normal":
        return "Major"
    if p == "Major":
        return "Major"
    if p == "Minor":
        return "Minor"
    if p == "Low":
        return "Minor"
    if p == "Trivial":
        return "Trivial"
    if p == "Lowest":
        return "Trivial"
    sys.stderr.write("Fallback to major priority for "+p+"\n")
    return "Major"

次に、出力されたJellyスクリプトでの添付ファイルのパスが、Tracのサーバ内でのローカルのパス("C:\TracLight\projects\trac\プロジェクト名"の部分)になっていますので、JIRAが別サーバの場合には、添付ファイルをJIRAサーバにコピーしたうえで、この部分を修正します。

<jira:AttachFile key="${key}" filepath="C:\TracLight\projects\trac\プロジェクト名/attachments/ticket/1/attachment.zip" option="override"/>

ただし、日本語ファイル名はJIRAではエンコードされたままなのでなんとかしたいところです。

JIRAでJellyスクリプトを読込みます。JIRA管理ページにて、[オプションと設定]-[Jelly Runner]を開きます。Jellyスクリプトをサーバにコピーしておいてそのパスを指定するか、ファイルの内容を貼りつけます。

これでインポートできるはずなのですが、、私の環境では、約1000件のチケットのうち400件目くらいで次のエラーが発生していました。

スクリプトを実行できません。 
Extra Information: [hide]
Error: <JiraJelly xmlns:jira="jelly:com.atlassian.jira.jelly.enterprise.JiraTagLib">
Exception: org.apache.commons.jelly.JellyTagException: file:/home/jira/Share/output.jelly:12718:0: Unable to make temporary copy of file.
java.io.PrintWriter@13b92a1

この問題についてはまだ調査中ですが、すべてインポートできれば、ひとまず移行できる状態にはなりそうです。あとは、次の点をどうするかが課題です。

  • チケット本文・コメント内でのTracリンク(#111, r1111, ...)
  • チケットのwiki記法(改行, 箇条書きなど)
  • Subversionのコミットログに記述したTracリンク

ところで、JIRAは標準ではWYSYWIGエディタは搭載していないんですね。
[#JRA-8943] WYSIWYG / Rich Text Editor - Atlassian JIRA

追加

Jellyスクリプトのインポートに失敗する問題は、Tracの添付ファイルフォルダで欠けているファイルがあったためでした。jiraのlogs/catalina.outファイルにログが出てました。