Hudsonで継続的ビルドを行う

Hudsonいいですね。非常に直感的に使い易いインターフェイスで日本語化もされている為、最初に使うCIツールとしては敷居が低いのはポイントです。Maven2の設定がある程度できる人ならば、すぐに使いこなせるのではないでしょうか?
というわけで色々設定してみたのですが、何時継続的なビルドを行うか?という話です。私自身も継続的ビルドといえば、デイリービルドのような形で「毎日決まった時間に実行する」のが一般的と思っていました。実際にContinuum でもそのような設定ができますし、Cronのように定期的な実行をサポートするツールと組み合わせるのが一般的なのではないでしょうか?しかし、もっと効果的に継続的なビルドを行うにはコミット毎に行うべきだとHudsonのヘルプに書いてありました。実際にコミットをトリガとしてビルドをする為の設定をまとめておきます(簡単です!)。

まず、ヘルプから引用しておきましょう。

このプロジェクトを定期的に実行するクーロンのような機能を提供します。

この機能は、クーロンの代替品としてHudsonを使用するのが第一なので、 <span style="font-weight:bold;">プロジェクトの継続的なビルドに使用するのは、望ましくありません。</span> 継続的インテグレーションのやりはじめの頃は、 ナイトリーやウィークリーのようにビルドを定期的にスケジュールすることを考え勝ちで、 この機能を使用します。しかしながら、継続的インテグレーションのポイントは、 変更したらすぐにビルドを開始し、変更へのフィードバックをすばやくすることです。 そうするには、 SCMの変更通知をHudsonに中継する必要があります。

上記の通り、この機能を使用する前に、この機能が本当にあなたが必要とするものなのか、 考えてみてください。 

これはビルド・トリガと呼ばれる、ビルドのタイミングを設定する項目の「定期的に実行」に関するヘルプです。Hudsonの思想では継続的なインテグレーションは変更後即なわけです。その為にはSCM(今回はSubversion)での変更をHudsonに通知する必要があります。もしくは、Subversionにポーリングを行い変更を検知する方法も選択できますが、負荷も考えるとSubversion側からpullする方法が推奨されています。

Hudsonの設定

Hudsonの設定箇所は、ビルド・トリガの項目を「リモートからビルド」に設定する事だけです。もし、公開されるような場所にHudsonがあるならば、認証用のトークンを設定します。この設定を行うだけで、後は http://hostname/hudson/job/xxxx/build?token=TOKEN_NAME へHTTPリクエストを投げればビルドが開始されるようになります。

Subversionの設定

Subversionではcommit時などにhookスクリプトを起動する事が出来、メールでの通知などを行う事ができます。このpost-commitのhookを使用して、Hudsonにビルドを指示すればOKです。
スクリプトは例えばこんな感じです。

#!/bin/sh
wget -o /var/tmp/null http://hostname/hudson/job/xxxx/build?token=zzzzzzzzzzz

HTTPリクエストを投げればよいだけなので、Linuxならばwgetで充分でしょう。
尚、post-commitの設定時には、実行権限を与えることを忘れがちなので注意してください。

以上で簡単にコミット時に継続的なビルドを行う設定が出来ました。

ジョブの単位

昨日の設定では、ジョブで「mvn clean package site」と実行していましたが、siteの実行時にカバレッジ測定用のテストが重複して実行され、テスト回数が重複してしまう問題がありました。これ自体はバグなのか仕様なのか解りませんが、課題トラッカーに既に登録されているようです。
HudsonのMLで相談してみたところ、ジョブは分けて実行することで回避しているとの話を聞くことが出来ました。また、意味的に分かれているpakageとsiteは別に実行する方がいい、と考える方もおられました。個人的にはジョブはプロジェクト単位だから分けるべきじゃないなぁとは感じたのですが、コミット駆動で設定を行っていくうちに、分けた方がいいと考えるようになりました。
理由としては、mvn site はコミット毎にやる必要がない、という事です。siteではJavaDocの生成やカバレッジの測定などを行いプロジェクトの情報収集を行うタスクです。カバレッジJavaDocなどは定期的にチェックすることで品質を高めます。自動化されて更新される事は有効ですが、頻繁に更新される時期でも1日1回やれば充分です。逆に継続的なテストは、コミット毎に行うことでデグレの発生を即時に通知することが可能になります。次の日の朝、昨日の朝1でコミットした影響が解るよりも、コミットしたならば即時に解る方が良いわけです。
このように効果的な実行タイミングが異なる為、ジョブとして分ける、という考え方は正しいのではないでしょうか?とはいえ、同じリポジトリをみる同一のプロジェクトなのですから、ジョブグループのような仕組みが合って、ジョブを複数登録することが可能で、それぞれの実行トリガを設定できる、という形が理想かもしれません。

pilikaでの設定

現在の設定は、ビルド(テスト)はコミット毎、siteの更新は毎晩2:00という設定で運用しています。