database.ymlって書いてますがファイルならなんでもいけます
前提
自分のビルドスクリプトだとこういう風にすることが多いです
# 最初にJenkins用のDB接続情報が書かれたdatabase.ymlを作る cp config/database.yml.jenkins config/database.yml # あとは普通にテスト RAILS_ENV=test bundle exec rake db:create RAILS_ENV=test bundle exec rake db:migrate:reset bundle exec rspec
しかしこれだと同じプロジェクトを別々のジョブ*1にした場合にも同じDBを使うためロックがかかってテストが落ちることになり、Throttle Concurrent Builds Plugin - Jenkins - Jenkins Wiki で同一DBは1つずつしかテストしないような排他制御をしていました。
ジョブが増えてくるとDBがボトルネックになってビルド全体が遅くなるため、スクリプトを
if [ $JOB_NAME = "app_develop" ]; then cp config/database.yml.jenkins_develop config/database.yml else cp config/database.yml.jenkins_master config/database.yml fi
や
cp config/database.yml.${JOB_NAME} config/database.yml
のようにすることも考えたのですが、ジョブが増えた時に似たようなファイルが大量にできてしまうので汎用性がありません。
差し込み変数でファイルを作れるようにgemやJenkinsのプラグイン作るしかないと思ってたのですが、今日画期的な方法*2を思いついたので実践してみました。
【本題】ジョブごとに手軽にファイルを動的生成する
こんなファイルを作っておいて
database.yml.jenkins
test: adapter: mysql2 encoding: utf8 database: app_test_JOB_NAME pool: 20 username: user password: pass socket: /var/run/mysqld/mysqld.sock
cat config/database.yml.jenkins | sed -e "s/JOB_NAME/${JOB_NAME}/" > config/database.yml
sedし忘れてもエラーにならないように CREATE DATABASE
できる名前にしてます
ビルド実行時には環境変数が代入されるため実際には
cat config/database.yml.jenkins | sed -e "s/JOB_NAME/app_develop/" > config/database.yml
のようなコマンドが実行されて
test: adapter: mysql2 encoding: utf8 database: app_test_app_develop pool: 20 username: user password: pass socket: /var/run/mysqld/mysqld.sock
のようなdatabase.ymlが作られるため、ジョブの増減に柔軟に対応できるようになりました。
まとめ
Simple is best.
gemやpluginを作らずともシェルの基本コマンドだけで簡単に実現できるならそれにこしたことはないと思った次第。