環境依存の情報の管理やHudsonのジョブ設計など

環境依存の情報(DBサーバやメールサーバのIPアドレス、ファイルパスなど)をどう管理していくかは重要です。ローカルと結合環境では当然これらの値が違ってくるでしょう。

僕がやっているのはこれらの設定が書かれたファイルをリポジトリに置く際はローカルにあわせたものとし、ビルドする際に結合環境に切り替える。結合環境用の値は別途ビルド用の設定ファイルに書いておく。

例えばHibernateを使っているならhibernate.cfg.xmlには

jdbc:oracle:thin:@localhost:1521:XE

というローカル用のDB接続情報を書いておきます。

でビルドする際にこの値を結合環境用に

jdbc:oracle:thin:@dbserver:1521:sample

のように書き換えます。この情報はビルド用の設定ファイル(例:Antならbuild.properties)に書いてビルド時に置換します。
これは書いておいてコミットします。ビルド時にシステムプロパティで引数で渡すという手もあるかも。DBFluteのReplaceSchemaは環境変数で環境ごとのDBを切り替えて作れますね。
ともあれ、これなら開発者はソースをチェックアウトしてすぐに開発に着手でき、ビルドスクリプトの存在を開発者は意識する必要が無いです。

またファイルパスは基本的に相対パスを使うようにします。フルパスを使う場合でもc:\のようにWindows限定のものは書かないようにします。
log4jなら設定ファイルに/var/log/aaa.logと書けばWindowsならC:\var\log\aaa.logに出力されます。たしか。

ソースにフルパスをベタで書かないのも重要です。システムプロパティや環境変数を活用する。テストコードに平気でc:\tempとか書かれてると残念な感じです。

Hudsonでビルドする際にもフルパスで書かないほうがよいです。そうほうが分散ビルドした際もスケールするし。

どうしてもフルパスが欲しい場合は環境変数WORKSPACEを使ってパスを構築してジョブの設定からシステムプロパティや環境変数に渡すのがいいですね。ビルドスクリプトはそれを受け取って処理する感じ。ビルドスクリプトに/var/lib/hudsonのようなHudson依存のものが書かれていると本末転倒な感じです。

Hudsonのジョブ設計も重要ですね。

例えば

 |---trunk/ 
           |--sample-common/ 共通的に用いられるモジュール
           |
           |--sample-launcher/ ランチャーアプリ(sample-commonに依存している)

のようにsample-commonというモジュールがあってそれに依存するsample-launcherがあり、sample-launcherのテストケースがある。
sample-launcherのテストを実行するにはsample-commonモジュールが必要なのでsample-commonをコンパイルする必要があります(静的言語の話です)。

この場合にsample-commonのみをチェックアウトするsample-commonジョブとsample-launcherのみをチェックアウトするsample-launcherジョブの2つを用意してsample-launcherジョブの上流ビルドにsample-commonを指定し、sample-launcherのテスト実行時に上流ビルドの成果物を参照するためにsample-commonジョブのワークスペースを見にいくのはアンチパターンだと思います。って文章長いw

そうではなくsample-commonとsample-launcherの両方をチェックアウトしてsample-commonのビルドの後にsample-launcherのテストを実行するジョブを作ればいい。複数Eclipseプロジェクトに対して1つのHudsonジョブが対応するイメージです。

sample-commonのみをチェックアウトするジョブはsample-commonに関わるものだけを行うという感じです。

じゃあ、もしsample-launcherに依存するsample-hogeがあった場合にsample-hogeのテストはどうHudsonで実行させるか?

sample-common, sample-launcher, sample-hogeをチェックアウトして順番にビルドしてからsample-hogeのテストを実行される。がいまのところの僕の回答です。sample-launcherのテストジョブとsample-commonが重複してDRYじゃないかもしれませんが、それはいいと思ってます。

ジョブは独立しているのが望ましい。ジョブごとのワークスペースもね。Hudsonではジョブごとにワークスペースが独立しているので普通にやれば依存はしないのですが、ジョブ設定やビルドスクリプトでも依存しないようにする。

こう書いていくとビルドパイプラインに矛盾しそうですが、そこはまた別問題かなと。

なんかまとまってないですが、Twitterにつぶやいてばかりなのもアレなので脳内を吐き出してみました。