XPのプラクティスのうちの一つ、“継続的インテグレーション”についての詳細はこちら。
要は、
- 継続的インテグレーションテスト部分も含めて「全てが自動化された」「再現可能な」ビルドを、「日に何度も」行うこと
だそうです。
スクリプト言語だとデプロイはあってもビルドって殆ど無いですよね。なので、
“自動的に日に何度もテストを行うこと”
という風に勝手に縮小理解しました。
継続的インテグレーションについては、CIサーバー(Continuous Integration Server)というやつが沢山あって非常に機能も豊富です。
僕の仕事には少々大げさな気がしたのと、
「cronでsvn up && rakeじゃ駄目なのかしら?」
などと思ったのでそれをちょっとだけサポートするコマンドを作ってみました。
komagata’s saimaa at master – GitHub
インストール
$ sudo gem install komagata-saimaa -s http://gems.github.com
これでsaimaaというコマンドが入りました。
使い方
saimaaは-cでshellで実行したいコマンドを引数に取って実行します。
$ saimaa -c "ls /tmp"
コマンドが成功(0を返す)した場合、何もしません。
$ saimaa -c "ls /tmppppp"
--project--
--stdout--
--stderr--
ls: cannot access /tmppppp: No such file or directory
コマンドが失敗(0以外を返す)した場合、標準出力にコマンドの標準出力と標準エラー出力を返します。
$ saimaa -c "ls /tmppppp" example
--project--
example
--stdout--
--stderr--
ls: cannot access /tmppppp: No such file or directory
引数はプロジェクト名として認識されます。(このジョブのタイトルみたいなものです)
通知
saimaaは-nで通知のためのコマンドを引数にとって、-cで実行したコマンドの標準出力を標準入力として実行します。 (command | notifier みたいなのと同じです。)
$ saimaa -c "ls /tmppppp" -n "figlet" example
_ _
_ __ _ __ ___ (_) ___ ___| |_
_____ _____| '_ \| '__/ _ \| |/ _ \/ __| __|____ _____
|_____|_____| |_) | | | (_) | | __/ (__| ||_____|_____|
| .__/|_| \___// |\___|\___|\__|
|_| |__/
_
_____ ____ _ _ __ ___ _ __ | | ___
/ _ \ \/ / _` | '_ ` _ \| '_ \| |/ _ \
| __/> < (_| | | | | | | |_) | | __/
\___/_/\_\__,_|_| |_| |_| .__/|_|\___|
|_|
_ _ _
___| |_ __| | ___ _ _| |_
_____ _____/ __| __/ _` |/ _ \| | | | __|____ _____
|_____|_____\__ \ || (_| | (_) | |_| | ||_____|_____|
|___/\__\__,_|\___/ \__,_|\__|
_ _
___| |_ __| | ___ _ __ _ __
_____ _____/ __| __/ _` |/ _ \ '__| '__|____ _____
|_____|_____\__ \ || (_| | __/ | | | |_____|_____|
|___/\__\__,_|\___|_| |_|
_ _
| |___ _ ___ __ _ _ __ _ __ ___ | |_ __ _ ___ ___ ___ ___ ___
| / __(_) / __/ _` | '_ \| '_ \ / _ \| __| / _` |/ __/ __/ _ \/ __/ __|
| \__ \_ | (_| (_| | | | | | | | (_) | |_ | (_| | (_| (_| __/\__ \__ \
|_|___(_) \___\__,_|_| |_|_| |_|\___/ \__| \__,_|\___\___\___||___/___/
___ _ _
/ / |_ _ __ ___ _ __ _ __ _ __ _ __ _ __ _ | \ | | ___
/ /| __| '_ ` _ \| '_ \| '_ \| '_ \| '_ \| '_ (_) | \| |/ _ \
/ / | |_| | | | | | |_) | |_) | |_) | |_) | |_) | | |\ | (_) |
/_/ \__|_| |_| |_| .__/| .__/| .__/| .__/| .__(_) |_| \_|\___/
|_| |_| |_| |_| |_|
_ __ _ _
___ _ _ ___| |__ / _(_) | ___ ___ _ __
/ __| | | |/ __| '_ \ | |_| | |/ _ \ / _ \| '__|
\__ \ |_| | (__| | | | | _| | | __/ | (_) | |
|___/\__,_|\___|_| |_| |_| |_|_|\___| \___/|_|
_ _ _
__| (_)_ __ ___ ___| |_ ___ _ __ _ _
/ _` | | '__/ _ \/ __| __/ _ \| '__| | | |
| (_| | | | | __/ (__| || (_) | | | |_| |
\__,_|_|_| \___|\___|\__\___/|_| \__, |
|___/
最初に実行したコマンドが成功した場合、通知コマンドは実行されません。
$ saimaa -c "ls /tmp" -n "figlet" example
何に使うの?
だからどうした的なコマンドですが、要するに下記の用に使うことを念頭に置いています。
$ saimaa -c "svn up && rake" -n "mail -s '[example] rspec' notify@example.com" example-project
svn upして、rake [spec]が失敗した時だけnotify@example.comにメール飛ばす。
前述のfigletもそうですが、通知コマンドは標準入力を取るコマンドならば何でもかまいません。(growlnotifyとか)
実際のcronの設定としてはこんな感じです。(ossuary=納骨堂のサイトの設定)
$ crontab -l
PATH=/usr/bin:/bin:/usr/local/bin
HOME=/home/deployer
0 * * * * saimaa -c "cd /var/www/test/ossuary && svn up && script/spec spec -f progress" -n "mail -s '[ossuary] rspec' dev@actindi.net" ossuary
10 * * * * saimaa -c "cd /var/www/test/ossuary && svn up && script/cucumber features -s -l ja" -n "mail -s '[ossuary] cucumber' dev@actindi.net" ossuary
毎時間、0分と10分にそれぞれtrunkのコードにrspecとcucumberのテストを走らせています。
密かに $HOME/.saimaa/saimaa.yml にコマンドの実行結果をプロジェクト名毎に保存するようになっています。(今のところ特にインターフェースはありません)
shでワンラインでかけそうな、どうということは無いコマンドですが、僕の中での継続的インテグレーションの要件を一応みたしています。
また、ruby, rubygems, githubの組み合わせは自作コマンドを配布するとても楽な組み合わせなので最近多用しています。
マルチプラットフォームで動くし、Macなら、/opt/local/bin、Debianなら、/usr/bin といったパスの通ったところに配置してくれるし、gemコマンドでインストール、アンインストールも楽です。
もし、興味がおありの方はちょっとためしてみてもらえるとありがたいです。おそらく、開発サーバーに入って30分もあれば継続的インテグレーションが始められる筈です。