miauのブログ

はてなダイアリー「miauの避難所」をはてなブログに移行しました

Redmine の wiki ページを俯瞰する(やっつけ)

プロジェクトに新規メンバーが入る予定で、説明用のドキュメントを準備していたのですが。これまでやってきた案件は Redmine でそれぞれプロジェクトを用意してしまっているので、Wiki ページがいろんなプロジェクトに散らばっていて、必要なドキュメントを探しにくくなっていました。

親プロジェクトに Wiki ページをまとめたりといった形で整理して行きたいわけですが、ひとまず整理のとっかかりとして、各プロジェクトの Wiki ページを俯瞰できるようにしてみました。

本当はマクロなんかを作って格好良くやりたいんですが、やっつけでデータを更新しています・・・。

Wiki の親ページを設定する

Trac を使っているときは、トップページに

を使ってページ一覧を出すようにしていたのですが、Redmine にはページ一覧を出力するマクロは無いようで。

代わりに子ページの一覧を出す child_pages() というものがあったので、親ページを持たないページはプロジェクトごとのスタートページを親ページに設定することで、これと似たような機能を実現してしまいます。

今回は親ページを設定していないページが多数あったので、Rails のコンソールを使って一気に更新します。

コンソールの起動

Redmine のインストールディレクトリに移動して、

ruby script/console production

を起動します。

親ページ更新用のメソッド定義

起動したコンソールに、以下をペーストして、メソッドの定義を行います。

def update_wiki_structure(project_name, test=false)
  wiki = Project.find_by_name(project_name).wiki
  pages = wiki.pages
  page_by_title = Hash[*pages.map{|page| [page.title, page, page.pretty_title, page] }.flatten]
  pages.each{|page|
    if page.parent.nil? && page.title != wiki.start_page && page.pretty_title != wiki.start_page
      parent_name = wiki.start_page
      length = page.title.mb_chars.length
      (length - 1).downto(1){|i|
        parent_candidate = page.title.mb_chars[0, i].to_s
        if page_by_title[parent_candidate]
          parent_name = parent_candidate
          break
        end
      }
      puts "#{page.title} -> #{parent_name}"
      unless test
        page.parent = page_by_title[parent_name]
        page.save!
      end
    end
  }
  nil
end

プロジェクト名を渡すと、そのプロジェクト中の Wiki ページに対して親ページの更新を行うメソッドです。

  • 親ページが設定済みの場合は更新しない
  • スタートページの場合は更新しない
  • ページ名の先頭部分が別のページ名と一致する場合、そのページを親ページに設定する
    • 例えば「議事録」のようなページが存在する場合、「議事録20101217」の親ページは「議事録」になります
    • Redmine は routes の関係でページ名にスラッシュが使えないのでこのようなページ名にしていますが、見づらいのでリネームしたほうがいいかもしれません・・・
  • 第二引数に真となる値を渡すと DB の更新は行わない

というような仕様になっています。

プロジェクト名を確認

コンソールで

Project.find(:all).each{|project| puts project.name}; nil

のように実行すると、

sandbox
hoge
fuga

プロジェクト名の一覧が出力されます。

ページ名更新メソッドの呼び出し

定義した update_wiki_structure に上記で出力されたプロジェクト名を渡します。たとえば sandbox プロジェクトに適用したい場合は、コンソールで

update_wiki_structure "sandbox", 1

のように実行します。(まだ実際に更新を行いたくないので、第二引数に 1 を渡しています。)

すると、

環境構築手順 -> WikiStart
環境構築手順CIサーバ -> 環境構築手順
環境構築手順DBサーバ -> 環境構築手順
議事録20101202 -> WikiStart
議事録20101209 -> WikiStart
議事録20101217 -> WikiStart

のように、各ページの親ページ候補が出力されます。

もしこの設定が気に食わないようなら、あらかじめページを作っておきましょう。たとえば上記であれば「議事録」というページを作っておいたほうがいいですね。

問題ないようであれば、

update_wiki_structure "sandbox"

のように第二引数を渡さずに実行すると、親ページの更新が行われます。

プロジェクト一覧の出力(ついで)

各プロジェクトでどのリポジトリを使っているかわからなくなりがちなので、これも Wiki に載せてしまおうということで。

これもコンソール上で

Project.find(:all).each{|project| puts "|{{project(#{project.name})}}|#{project.identifier}|#{project.id}|#{project.repository.try(:type)}|#{project.repository.try(:url)}|#{project.description}|"};nil

のようにして textile 形式のテーブルを出力してみました。

|{{project(sandbox)}}|sandbox|1|Git|/var/git/sandbox.git|テスト用プロジェクトです。|
|{{project(hoge)}}|hoge|2|Git|/var/git/hoge.git|hoge プロジェクト|
|{{project(fuga)}}|fuga|3|Git|/var/git/fuga.git|fuga プロジェクト|

を入れている前提で、project() マクロを使ってます。id は普段必要になりませんが、hook からリポジトリを叩きたい場合は確か id を指定する形だったので表示しています。

親プロジェクトのスタートページに一覧を表示

親プロジェクトのスタートページはこんな感じになりました。

h1. プロジェクト一覧

|name|identifier|id|repository.type|repository.url|description|
|{{project(sandbox)}}|sandbox|1|Git|/var/git/sandbox.git|テスト用プロジェクトです。|
|{{project(hoge)}}|hoge|2|Git|/var/git/hoge.git|hoge プロジェクト|
|{{project(fuga)}}|fuga|3|Git|/var/git/fuga.git|fuga プロジェクト|

h1. Wiki ページ

h2. root

{{child_pages()}}

h2. [[sandbox:]]

{{child_pages(sandbox:)}}

h2. [[hoge:]]

{{child_pages(hoge:)}}

h2. [[fuga:]]

{{child_pages(fuga:)}}

気が向いたらやるメモ

Wiki ページを作るたびに親ページを設定したり、プロジェクトが増えるたびに親プロジェクトの Wiki を更新するのは面倒なので、このあたりはマクロ化しておきたいところです。

実は結構簡単にできそうなので、参考ページをメモしておきます。