本当は怖いHPC

HPC屋の外部記憶装置。メモ書き。ちゃんとしたものは別のところに書く予定です

継続的インテグレーション(笑)をサポートするCruiseControl.rbを使う

(最終更新:2007/12/17)

CruiseControl.rb(略してCC.rb)というのは、Javaで書かれた継続的インテグレーション(Continuous Integration = CI)を実現するためのツール、CruiseControlRubyバージョンだ。

CIとは何かというと、 Martin Fowlerの文章から引用すれば

  • 一日に何度も開発メンバーのそれぞれの成果を結合する
  • その際、完全なビルドとテストを行なう
  • そのプロセスを完全に自動化する
  • その結果を随時メンバーに周知する

というようなこと。動的言語の場合はビルドの概念は無いので、実質的には全自動テスト(と、せいぜいテストサーバーへのデプロイ)を意味することが多い。

さて、そのためのツールとして、今回はCruiseControl.rbを使ってみる。

導入

とりあえずオフィシャルサイトからダウンロードして解凍する。

$ wget http://rubyforge.org/frs/download.php/27495/cruisecontrolrb-1.2.1.tgz
$ tar -zxvf cruisecontrolrb-1.2.1.tgz

これで準備完了。あっけなさ過ぎる。これ自体は単独のRailsアプリケーションなので、システムへのインストールなどは一切必要なく、解凍したまま単独で動作する。

環境設定

本来、単独のRailsアプリケーションであれば設定はまったく必要ないのだが、僕の開発プロジェクトでは1つのプロジェクトの中に複数のRailsアプリケーションと単独のライブラリがいくつか存在しているので、ちょっと設定が必要だ。

まず、テストする対象のプロジェクトをaddする。現時点ではバージョン管理システムSubversionしか対応していない(誰かMercurial用のプラグイン書いてね。あ、ほら、目を伏せないで*1 )。

$ ./cruise add myproj --url http://mysvn.com/path/to/project --username user --password pass 

これで、projects/myproj/work/以下にプロジェクトのコードがすべて格納される。

次に、テストの手順をCC.rbに教えてやる。繰り返すが、単独のRailsアプリケーションなら、何もしなくても動作するはず。

今回の僕のプロジェクトのように構成が複雑になっているような場合は、プロジェクトのあちこちでテストを実行して廻るshellスクリプトを書けばいい*2。これをプロジェクトに追加する。シェルスクリプトの書き方については他に譲るとして、ポイントは、

  • テストに失敗した場合は、非0コードで終了する

というshellスクリプトとしては当たり前の動作をすること。ただし、どれかのテストが失敗した時点で終了してしまうとテストをすべて実行することができなくなってしまうので注意。テストの終了ステータスを蓄積していって、最後に全体の終了ステータスを返すように書く必要がある。
ここでは、とりあえずテストが成功するとして、以下のように即席で書いてみる

#!/bin/sh

# プロジェクト配下のすべてのコードのテストを実行する。
# テストが一つでも失敗した場合は、非ゼロの終了ステータスで終了する

exit 0

このシェルスクリプトの名前を test_all.sh という安直な名前にしてプロジェクトトップの直下に置こう(そうでない場合は、以下の test_all.sh を、自分のシェルスクリプトの場所に読み替えてください)。そして、プロジェクトごとの設定ファイルである projects/myproj/cruise_config.rb を編集しよう。

Project.configure do |project|
  project.build_command = 'sh test_all.sh'
end

よしよし。

サーバー起動

CC.rbのサーバーを起動すると、Subversionリポジトリを5分(変更可能)間隔でチェックして、テストを走らせてその結果を報告してくれる。

CC.rb自体もRailsで書かれている。以下のコマンドでサーバーを起動しよう。

$ LANG=C ./cruise start  # LANG=Cしているのは、CC.rbがsvnの出力を解析するため
=> Booting Mongrel (use 'script/server webrick' to force WEBrick)
=> Rails application starting on http://0.0.0.0:3333
=> Call with -d to detach
=> Ctrl-C to shutdown server
** Ruby version is not up-to-date; loading cgi_multipart_eof_fix
/usr/lib/ruby/gems/1.8/gems/mongrel-1.0.1/bin/mongrel_rails:46: warning: conflicting chdir during another chdir block
** Starting Mongrel listening at 0.0.0.0:3333
** Starting Rails with production environment...
** Rails loaded.
** Loading any Rails specific GemPlugins
** Signals ready.  TERM => stop.  USR2 => restart.  INT => stop (no restart).
** Rails signals registered.  HUP => reload (without restart).  It might not work well.
** Mongrel available at 0.0.0.0:3333
** Use CTRL-C to stop.
Builder for project 'move' started
Logging to: /home/fukuda/devel/cruisecontrolrb-1.2.1/log/move_builder.log

というわけでサーバーが起動する。作業マシンの上で起動したなら、http://localhost:3333/にブラウザでアクセスしよう。以下のような画面が表示されれば成功。

「Build Now」のボタンを押せば、その場でビルドを実行してくれる。成功なら、何事も無かったかのように画面は変化しない。失敗した場合は、ピンク色になって教えてくれる。

あとは、結果をメールで出したりできるし、他のテストツール(rcovとかSeleniumとか)と連携できるけど、それはまた別の機会に。

追記:これほしい!! http://passing.breeze.cc/mt/archives/2006/12/post-13.html

*1:Mercurial対応プラグインは一応rubyforgeにあるけど、とりあえず名前空間が予約してあるだけ、という感じ。http://rubyforge.org/projects/cc-hg/

*2:Windowsでの実行も考えるなら、このスクリプトを普通のRubyスクリプトRakefileにした方がいいかも知れない