ビルド時に環境ごとに設定ファイルをAntで切り替える方法

例えば以下のように環境依存な設定ファイルがあるとします。この設定ファイルを環境にあわせてどうやってビルド、デプロイするのがいいのか?というのがテーマです。

sample-common/
   |--src/
          |--main/
                   |--resources/
                              |--mail.properties メールサーバのホスト名が書かれている

sample-db/
   |--src/
          |--main/
                   |--resources/
                              |--ibatis-config.xml DBサーバのURLが書かれている

ibatis-config.xmlはこんなイメージです

<property name="JDBC.ConnectionURL" value="jdbc:oracle:thin:@localhost:1521:XE" />

ひとつのやり方としては、これらの設定が書かれたファイルをリポジトリに置く際はローカルにあわせたものとし、ビルドする際にAntのreplacetokenとreplacevalueで置換して結合環境に切り替えるというやり方があります。
ただしreplacevalueに${db.url}のようにプロパティを指定できないため、結合環境の値をベタ書きにする必要があります。これがいまいち。メリットはリポジトリからチェックアウトしてすぐに開発に着手できること。

他には

<property name="JDBC.ConnectionURL" value="@db.url@" />

のように
@db.url@という感じで置換文字を使ってAntのfiltersetで切り替えるというものがあります。
何に切り替えるかというのはビルド用の設定ファイルbuild.propertiesあたりに書く。
デフォルトは結合環境用にしておいてバッチたたいたらローカル用に書き変わるとか(逆でもいいかも)しとけば、それなりに柔軟に対応できそうです。結合環境が変わったらビルド用の設定ファイル書き換えればいい。ただしリポジトリからチェックアウトしてすぐに開発に着手はできません。チェックアウト後に(ローカル用に値を置換するために)バッチを実行する必要があるでしょう。

ローカルと結合の2つの環境しかないならこれぐらいでもいいですが、総合テスト環境とか、運用環境とか環境の数が多くなってくるとこのやり方では厳しい気がします。環境ごとの値をどこに書いて管理するの?って言う話になります。

そこで教えてもらったやり方が概要が下記です。ちなみにこのやり方は2002年にはすでに行われていたようです。2002年なんて俺新人でしたが、Antの存在すら知らなかったですよ。--) ていうかEclipseすらそんなにメジャーじゃなくてJBuilderが重いとか言ってた時期ですがな。Strutsが知られてきたのもこのぐらいかも。先人は偉大ですね。こういうビルドスクリプトをどう書くかというネタはほとんど見たこと無いのだが、あまりに常識すぎて誰も書かないのだろうか。--);

閑話休題

構成はこんな感じです。

sample-common/
   |--src/
          |--main/
                   |--resources/
                              |--mail.properties  リポジトリ上は空。チェックアウト後にantを実行すると置換してここにコピーされる。ただしsvn:ignore

sample-db/
   |--src/
          |--main/
                   |--resources/
                              |--ibatis-config.xml  リポジトリ上は空。チェックアウト後にantを実行すると置換してここにコピーされる。ただしsvn:ignore 

project-sample/ 環境ごとに何で置換すべきかが書かれている。
  |--product/  運用環境
  |--it/ 総合テスト環境
  |--ct/ 結合テスト環境
  |--ut/ 単体テスト環境
        |--sample-common/
               |--src/
                      |--main/
                              |--resources/
                                         |--mail.properties.filter
        |--sample-db/
               |--src/
                      |--main/
                              |--resources/
                                         |--ibatis-config.xml.filter                                        
                                         
resouce-sample/ 設定ファイル専用置き場。置換文字列で書かれている。
  |--sample-common/
         |--src/
                |--main/
                        |--resources/
                                    |--main.properties.template
  |--sample-db/
         |--src/
                |--main/
                        |--resources/
                                    |--ibatis-confg.xml.template                 

ポイントはresource-sampleという設定ファイル専用プロジェクトを作ることと環境ごとの値を保持するプロジェクトを作ること。

utのibatis-config.xml.filterはこんな感じですね。

db.url=jdbc:oracle:thin:@localhost:1521:XE

ctならこんな感じになるんでしょう。

db.url=jdbc:oracle:thin:@dbserver:1521:sample

で、こんな感じで置換する。ant -Denv=utみたいな感じで実行します。

<copy file=".../ibatis-config.xml.template" tofile=".../ibatis-config.xml">
  <filterset>
    <filtersfile file=".../${env}/.../ibatis-config.filter" />
  </filterset>
</copy>

今風にさらに発展させるとフォルダ構成や拡張子を統一してCoC的にしてこの部分はmacrodefを使って共通化します。

この方式なら環境が増えてもproject-sample以下に環境を増やせばいいだけでビルドスクリプト自体は変更する必要が無いのでスケールします。