Goodbye Trac, Hello Redmine!

TracLightning3.1.1 から Redmine 1.3.0 へ引っ越した時のメモです。
Redmineを使いたいけど、今までのTracのデータがあるしなぁ、というかたの参考になれば幸いです。

年度末のサービスインを控えた、忙しいこの時期に何でこんなことをやったのか? の理由は→こちら

目次

  1. Redmine セットアップ・追加プラグインなど
  2. SVNリポジトリ作成、設定など
  3. データ移行事前
  4. データ移行当日
  5. データ移行事後

Redmine本体インストール・追加プラグインなど

Redmine本体

bitnami-redmine-*.*.*-*-windows-installerをbitnami公式サイトから入手、インストールしました。特に注意を要することもなく、すんなりインストールできました。

今回はWindows Servernにインストールしたので、Windows ファイアウォールにて下記プログラムの接続を許可しました。

  1. httpd.exe
  2. svn.exe
ライブラリ FasterCSV

別でいれるredmine_importerで使うライブラリだそう。インストールできてるような、できてないような、ちょっと不安な感じです。

  1. モジュール取得 (今回は fastercsv-1.5.1.gem をチョイス)
  2. フォルダを作って
    • mkdir C:\Program Files\BitNami Redmine Stack\apps\redmine\vendor\gems\fastercsv-1.5.1
  3. インストール
    • gem install fastercsv-1.5.1.gem --local
redmine_importer

CSV形式のチケットデータを取り込みます。Tracのチケットデータを移行する時に使いました。
チケットを大量登録する時にも使えそうです。(何度か試しましたが、更新は上手くいきませんでした・・・ ^^;;)

インストールはこちらを参考にさせていただきました

  1. モジュール取得
  2. 解凍してできたディレクトリをC:\Program Files\BitNami Redmine Stack\apps\redmine\vendor\pluginsにコピー
  3. "redmine_importer"にリネーム
  4. インストール
    • cd C:\Program Files\BitNami Redmine Stack\apps\redmine\
    • rake db:migrate_plugins RAILS_ENV=production
  5. Redmine再起動
パーキングロットチャート
  1. モジュール取得
  2. 解凍してできたディレクトリを、C:\Program Files\BitNami Redmine Stack\apps\redmine\vendor\plugins
  3. "parking_lot_chart"にリネーム
  4. Redmineを再起動
WorkTimeプラグイン

おすすめです!朝会の昨日実績報告で使ってます。

  1. モジュール取得
  2. インストール
    • cd C:\Program Files\BitNami Redmine Stack\apps\redmine
    • rake db:migrate_plugins RAILS_ENV=production

SVNリポジトリ作成、設定など

BitNami Redmine Stack には最初から Subversion が付いているので、インストールは不要です

(1) リポジトリの作成

C:\Program Files\BitNami Redmine Stack\use_redmine.bat
svnadmin create C:\repos\dev

(2) システム環境変数のPath登録

C:\Program Files\BitNami Redmine Stack\subversion\bin

(3) モジュールコピー

C:\Program Files\BitNami Redmine Stack\subversion\binの以下2つを 〜\apache2\modules へコピー

  • mod_authz_svn.so
  • mod_dav_svn.so
(4) モジュール有効化

httpd.conf。サーバの『Administrator』ユーザじゃないと編集できませんでした。

  1. コメントIN
    • LoadModule dav_module modules/mod_dav.so
    • LoadModule dav_fs_module modules/mod_dav_fs.so
    • LoadModule authnz_ldap_module modules/mod_authnz_ldap.so
    • LoadModule ldap_module modules/mod_ldap.so
  2. 追記
    • LoadModule authz_svn_module modules/mod_authz_svn.so
    • LoadModule dav_svn_module modules/mod_dav_svn.so
(5) ロケーション定義を追加

httpd.conf。合わせてActiveDirectoryの特定のグループのユーザーにのみアクセスを許可

  • SVNPath: リポジトリへのフルパスをセット
  • Require ldap-group: ActiveDirectoryの特定のグループのユーザーにのみアクセスを許可
  • AuthzSVNAccessFile : アクセス制御の定義を行うファイルを指定します。

サンプルです


 DAV svn
 SVNPath C:/repos/dev
 AuthType Basic
 AuthBasicProvider ldap
 AuthName "SVN Repo Authentication(dev)"
 AuthzLDAPAuthoritative off
 AuthLDAPURL "適宜"
 AuthLDAPBindDN 適宜
 AuthLDAPBindPassword 適宜
 AuthLDAPGroupAttribute member
 AuthLDAPGroupAttributeIsDN on
 Require ldap-group 適宜
 Require valid-user
 AuthzSVNAccessFile C:/repos/AuthzSVNAccess_dev.conf

★AuthzSVNAccess_dev.confサンプル。※参考サイトはこちら

[groups]
devmembers = yamakai,yamamoto
[/]
 * = r
[/trunk]
hoge = rw
@devmembers = rw
(6) 環境変数の変更を反映させるためにWindowsを再起動
(7) 確認

"http://localhost/dev/"でブラウザからリビジョン0が見れることを確認する

データ移行 事前

こちらで詳細を書きましたが、開発チームとは別に導入案件のSVNリポジトリを作りました。

  • 案件毎の空SVNリポジトリ事前作成 (trunk, branches, tags)
  • 案件毎リポジトリ SVN権限設定 (Apache > httpd.conf)
  • 案件毎のtrunkを各案件のメンバーのPCにチェックアウトしておいてもらう(移行後はこちらにデータが入ってくる)
  • 作業開始前バックアップ

データ移行 当日

(1) SVNリポジトリデータ
  1. @旧サーバ。まず今のリポジトリをダンプ。
    • svnadmin dump /path/to/svn/repos > repos.dump
  2. ダンプしたものを新サーバへもっていく
  3. @新サーバ。まずリポジトリを作成して、旧サーバからもってきたダンプを流し込むだけ。
    • svnadmin create /path/to/svn/repos
    • svnadmin load /path/to/svn/repos < repos.dump
(2) 過去チケット
  • csvインポートプラグインを使いました。TracからエクスポートしたチケットデータをRedmine用に整形する時のポイントは以下のとおり
    • 日付フォーマットは yyyy-mm-dd
    • ユーザ名を設定するところは、名前でなくてRedmine上のユーザIDを使う
    • チケットステータス文言を変更。closed → 終了、new → 新規 など
    • 改行コードをLFで初期化。混ざりまくりでお手上げ状態だったので、改行コードを削除しました。
  • 添付チケットについてはチケット移行完了後に、個別で貼り付け

Tracからチケットデータをエクスポートするときに使ったクエリのサンプル

SELECT
  p.value AS __color__,
 (CASE status 
    WHEN 'closed' THEN 'color: #777; background: #ddd; border-color: #ccc;'
    ELSE 
      (CASE owner WHEN '$USER' THEN 'font-weight: bold' END)
  END) AS __style__,
  id        AS ticket,
  t.type    AS 'tracker',
  summary   AS 'title',
  status    AS 'status',
  priority  AS 'priority',
  owner     AS '担当者',
  c6.value  AS '開始日',   
  c7.value  AS '期日', 
  description AS '_description',  
  milestone AS '対象バージョン',
  reporter  AS '登録者',
  time      AS '登録日付',
  c10.value AS 'Rev', 
  keywords  AS 'Keywords',
  c1.value  AS '検出日', 
  c5.value  AS '検出局面', 
  c4.value  AS '完了日', 
  c3.value  AS '確認者', 
  c2.value  AS '確認日', 
  c11.value AS 'TestCases',
  c12.value AS 'TroubleReason',
  resolution
FROM
  ticket t
  LEFT OUTER JOIN enum p ON p.name = t.priority AND p.type='priority'
  --修正リビジョン→Rev
  LEFT OUTER JOIN ticket_custom c10 ON (t.id = c10.ticket AND c10.name = 'rev')
  --テストケースNo→TestCases
  LEFT OUTER JOIN ticket_custom c11 ON (t.id = c11.ticket AND c11.name = 'testcase_id')
  --開始予定日→開始日
  LEFT OUTER JOIN ticket_custom c6  ON (t.id = c6.ticket  AND c6.name  = 'due_assign')
  --完了予定日→期日
  LEFT OUTER JOIN ticket_custom c7  ON (t.id = c7.ticket  AND c7.name  = 'due_close')
  --障害原因分類→TroubleReason
  LEFT OUTER JOIN ticket_custom c12 ON (t.id = c12.ticket AND c12.name = 'trouble_reason')
  --検出日
  LEFT OUTER JOIN ticket_custom c1  ON (t.id = c1.ticket  AND c1.name  = 'detected_date')
  --検出局面
  LEFT OUTER JOIN ticket_custom c5  ON (t.id = c5.ticket  AND c5.name  = 'detection_phaset')
  --完了日
  LEFT OUTER JOIN ticket_custom c4  ON (t.id = c4.ticket  AND c4.name  = 'complete')
  --確認者
  LEFT OUTER JOIN ticket_custom c3  ON (t.id = c3.ticket  AND c3.name  = 'close_checker')
  --確認日
  LEFT OUTER JOIN ticket_custom c2  ON (t.id = c2.ticket  AND c2.name  = 'close_check_date')
ORDER BY
  t.id

Tracからチケットのコメント履歴をエクスポートするときに使ったクエリのサンプル

select
 ticket,
 newvalue
from
 ticket_change c
where
 field = 'comment'
 and newvalue not like ''
order by ticket, time


Tracから抜きしたデータをExcelのマクロを使ってRedmine用に整形し、出力します。項目値変換はlookup関数がお勧めです。

Option Explicit
Sub WRITE_REDMINE_TICKET()
    Const cnsTITLE = "出力処理"
    Const cnsFILTER = "テキストファイル (*.csv;*.*),*.csv;*.*"
    Dim xlAPP As Application      ' Applicationオブジェクト
    Dim intFF As Integer            ' FreeFile値
    Dim strFILENAME As String   ' OPENするファイル名(フルパス)
    Dim strREC As String           ' 書き出すレコード内容
    Dim GYO As Long                ' 収容するセルの行
    Dim GYOMAX As Long          ' データが収容された最終行
    Dim lngREC As Long             ' レコード件数カウンタ

    ' Applicationオブジェクト取得
    Set xlAPP = Application

    ' 「名前を付けて保存」のフォームでファイル名の指定を受ける
    xlAPP.StatusBar = "出力するファイル名を指定して下さい。"
    strFILENAME = xlAPP.GetSaveAsFilename(InitialFileName:="IKOU_TICKETS.csv", _
        FileFilter:=cnsFILTER, Title:=cnsTITLE)

    ' キャンセルされた場合は以降の処理は行なわない
    If StrConv(strFILENAME, vbUpperCase) = "FALSE" Then Exit Sub

    ' 収容最終行の判定(Excel認知の最終行から上に向かってデータがある行を探す)
    GYOMAX = Cells.SpecialCells(xlCellTypeLastCell).Row
    Do While Cells(GYOMAX, 1).Value = "0"
        GYOMAX = GYOMAX - 1
    Loop
    If GYOMAX < 2 Then
        xlAPP.StatusBar = False
        MsgBox "データを2行目から入力してから起動して下さい。", , cnsTITLE
        Exit Sub
    End If

    ' FreeFile値の取得(以降この値で入出力する)
    intFF = FreeFile
    ' 指定ファイルをOPEN(出力モード)
    Open strFILENAME For Output As #intFF
    ' 1行目から開始
    GYO = 1
    ' 最終行まで繰り返す
    Do Until GYO > GYOMAX
        ' N列内容をレコードにセット(先頭は3行目)
        strREC = Cells(GYO, 1).Value & "," & _
                 Cells(GYO, 2).Value & "," & _
                 """" & Cells(GYO, 3).Value & """" & "," & _
                 Cells(GYO, 4).Value & "," & _
                 Cells(GYO, 5).Value & "," & _
                 Cells(GYO, 6).Value & "," & _
                 Replace(Cells(GYO, 7).Value, "/", "-") & "," & _
                 Replace(Cells(GYO, 8).Value, "/", "-") & "," & _
                 """" & Cells(GYO, 9).Value & """" & "," & _
                 Cells(GYO, 10).Value & "," & _
                 Cells(GYO, 11).Value & "," & _
                 Cells(GYO, 12).Value & "," & _
                 """" & Cells(GYO, 13).Value & """" & "," & _
                 """" & Cells(GYO, 14).Value & """" & "," & _
                 Replace(Cells(GYO, 15).Value, "/", "-") & "," & _
                 Cells(GYO, 16).Value & "," & _
                 Replace(Cells(GYO, 17).Value, "/", "-") & "," & _
                 Cells(GYO, 18).Value & "," & _
                 Replace(Cells(GYO, 19).Value, "/", "-") & "," & _
                 """" & Cells(GYO, 20).Value & """" & "," & _
                 """" & Cells(GYO, 21).Value & """"

        ' 改行をクリアして
        strREC = Replace(strREC, vbLf, "")
        strREC = Replace(strREC, vbCr, "")
        ' Redmine用に LFで改行
        strREC = strREC & vbLf

        If strREC <> "" Then
            ' レコード件数カウンタの加算
            lngREC = lngREC + 1
            ' レコードを出力。セミコロンでCRLFの改行抑止
            Print #intFF, strREC;
        End If

        '行を加算
        GYO = GYO + 1
    Loop
    
    ' 指定ファイルをCLOSE
    Close #intFF
    xlAPP.StatusBar = False

    MsgBox "ファイル出力が完了しました。" & vbCr & "レコード件数=" & lngREC & "件", vbInformation, cnsTITLE
End Sub
(3) wiki
  • wiki記法の修正が必要です
  • 手作業で移行してます。1日で終わらせる必要もなかったので、のんびりやってます。

データ移行 事後

TODOはこんなもんでした

  1. Eclipse宛先切り替え方法連絡