Common LispプロジェクトをJenkinsで継続的インテグレーション
Clackのバグ報告を定期的にもらいます。ありがたいことなのですが、そのほとんどが○○の処理系でエラーが出てる、などです。具体的に言えば、追加したシンボルがその処理系の標準パッケージのシンボルとコンフリクトする、とかですね。
こういうつまらないものであれば、自動テストを走らせるだけで簡単に見つかるようなものです。けれど、Clackは現在6000行近くあり、一回テストするのに2分くらいかかるので、コードを変更するたびにすべての処理系でテストするなんて現実的じゃありません。かと言っていつの間にかバグ入ってるという状況は避けたい。
なので重い腰をあげて、Clack Project用にJenkinsさんを立てて継続的インテグレーションすることにしました。できたJenkinsサーバは以下のURLで運用しています。
せっかくなのでセットアップの流れをまとめておきます。
サーバ
まずはサーバが必要です。さくらVPSの512MBを借りてUbuntu 10.04をインストールしました。Ubuntuを選んだのは使い慣れたAPTが使えるからです。
JavaとかJenkinsとか、リバースプロキシ用のApache2を立てたりして、とりあえずJenkinsが動くようにしました。
プラグイン
次にJenkinsのプラグインをインストールしました。Webインターフェイスからインストールできるのですごく楽です。
とりあえずGit Pluginを入れないとClackのソースを取ってこられないので入れました。GitHub Pluginはpush時にビルドを走らせることができるらしいので便利そうです。
Jenkins氏にテスト結果をパースさせる
初期状態でもテストを走らせるワンライナーを書けばビルドを実行できます。
$ ccl --eval '(ql:quickload :clack-test)'
ただテストを走らせるだけだと、コマンドの返り値が0かどうかしか見てなさそうなので、ちゃんとテスト結果をパースして成功/失敗を管理する必要があります。
幸いClackはCL-TEST-MOREでテストされているのでTAP (Test Anything Protocol) を解釈してくれるものを探せば楽なんじゃないかと思いました。
最初に見つけたのはTAP Pluginでした。これはTAPの結果をファイルに吐いておけばパースしてくれるプラグインです。しかし、使ってみると、plan行を無視するため途中で死んでもテストが成功してしまうというとても夢のある仕様だったので使うのをやめました。
他にTAPでそのまま解釈してくれそうな方法もなかったので、Jenkinsが解釈するJUnitのXML形式でテスト結果を出力することにしました。
まず、一度テストの結果をTAP形式でファイルに吐いておき、PerlのTAP::Formatter::JUnitに付いてくるtap2junitで変換してJenkinsで集計するという流れで動きました。
ここでCPAN祭りになるので少し時間がかかります。
ログの分割出力
現状、ClackのテストはCL-TEST-MOREで書いて (ql:quickload :clack-test) のようにテスト用のシステムをロードするとすべてのテストが実行されるようにしています。
けれど、この方法だと結果の出力が全部つながってしまいます。ファイル単位で出力しなければJenkinsがパースできません。
そこで以下のようなスクリプトを書いて、
このように実行するようにしました。
/usr/local/bin/ccl --load test-utils.lisp --eval '(run-test-system :clack-test)' --eval '(quit)'
これを実行するとテストファイルと同じ場所に".log"ファイルができるので、これをtap2junitを使ってXMLに変換します。
for f in `find t -name "*.log"`; do tap2junit --name $f $f; done
とりあえずCCLとSBCLでテストするように以下のように設定しました。
ちょっとハックっぽいので、もう少し運用してみてから良い方法を考えて汎用化したいと思います。
まとめ
ここまでセットアップするのに2日くらいかかりましたが、動くようになってよかったです。CL-TEST-MOREがTAPで結果出力する利点が初めて役立ちました。
今はとりあえず、開発チームが小さいので定期実行ではなく、push時にだけビルドするようにしてあります。
これから管理しなければいけないCLのライブラリも増えてくると思いますが、ある程度の規模のものはこちらで自動ビルドするようにして品質は落とさないように気をつけたいですね。