Carton考2014
こうするのがいいかなーと思ってる。経緯は端折って大枠だけ。Webアプリケーションプロジェクトの場合です。
cpanfileちゃんと書いてコミット
今やどこでもやってますね。scan-prereqs-cpanfileも便利です。
開発者は各自carton installでモジュールをインストール。プロジェクトごとにPerlをビルドしたりしてる場合は、cpanm --installdeps .でも別に良い。
CI環境でcpanfile.snapshotを作る
CI環境は必ず以下のとおりとする。
- 本番環境と同じアーキテクチャ
- 本番環境と同じバージョンのPerl
- まっさらな状態(Globalに何のモジュールも入っていない)
CIにcarton installもさせて、必要なモジュールをlocal/に入れてテストさせる。毎回サラからcarton installしてたら時間かかるので、git pull; carton installとかで良い。
それでテスト回して、通ったらcpanfile.snapshotを自動コミットさせる。
追記:@soh335 先生に教えてもらったのですが、local/をサラにしないと、cpanfile.snapshotが変になることがあるようで、cpanfile.snapshot作ってコミットさせる処理はテスト回すジョブとは別のジョブにしたほうが良さそう。
サラなPerlが必須なのは以下の理由。
- cpanfileへの依存モジュールの書き漏れを防ぐ(CIで気付ける)
- グローバルにインストールされているモジュールに因ってインストールされるモジュールが変わってしまうことがある
ちなみにCartonはバージョン1以降は、0.x系と違ってグローバルなモジュールも見るようになっています。(lib::core::onlyを使ってない)
開発者は手元ではcpanfile.snapshotを更新してはならない
% git skip-worktree cpanfile.snapshot
とかやっておくと良さそう。
本番環境では carton install --deployment
CIでテスト通ったのと同じ構成のモジュールがインストールされるので安心。
carton execは使わないでラッパーシェルを使う
carton execと同じような環境変数を設定してくれるラッパーシェルを書いて、carton execの代用とする。一番シンプルな形だと以下の様な感じ。
#!/bin/sh
set -e
export PATH="local/bin:/opt/perl-5.18/bin:$PATH"
export PERL5LIB="local/lib/perl5"
exec "$@"
その他プロジェクト固有の環境変数とか、プロジェクトディレクトリへのcdとか設定したい項目をこのシェルの中に入れ込んでおくと良い。本番兼CI用のラッパーシェルはちゃんとリポジトリにコミットしておくこと。以下の様な感じ。
% cat env-exec
#!/bin/sh
set -e
cd $(dirname $0)
export USER=app
export HOME=/home/$USER
export PLACK_ENV=production
export PATH="local/bin:/opt/perl-5.18/bin:$PATH"
export PERL5LIB="lib:local/lib/perl5"
exec "$@"
これは
% /path/to/env-exec perl ...
とかやって使う。proveとかplackupとかcarton installとかもこれを噛ます。
これは、carton execが結構起動コストが掛かる(carton check的なこともやってる)のでバッチ等では気になるので避けたいとか、どうせperl起動するときにラッパーシェルを噛ませるので、その中でcarton execがやってくれるような環境変数設定処理も一緒に書いておけばいいじゃんという感じです。
ちなみに、CI環境でcpanfile.snapshot作るとかは今のプロジェクトではやってないので誰か試してみてください。