capistranoでrailsアプリをbundle packageを使ってデプロイしようとしてハマった話。
ちょっとまとめるのが億劫だったので、つらつらと。
困った
あるプロジェクトで、capistranoのcopyストラテジーを使って
デプロイしているのですが、その際に、外部へgemを取りに行かないように、
bundle package を使っています。
で、その bundle package をする部分は自前で定義していて、
下記のように単純にやっていました。
system("cd #{destination} && bundle package --all")
しかしこれだと予期したように動かなかった。
想定としては、
/tmp/hogehoge/vendor/cache
の下に、gem達が入るはずなのに、なぜか
capコマンド実行ディレクトリ/vendor/cache
に入ってしまった。
原因
ググると、こんな記事が見つかりました。
どうやらbundlerが定義している環境変数が原因だったよう。
確認してみる。
$ bundle exec env | grep -i bundle : : BUNDLE_BIN_PATH=/hoge/.rbenv/versions/2.0.0-p0/lib/ruby/gems/2.0.0/gems/bundler-1.3.1/bin/bundle BUNDLE_GEMFILE=/hoge/hoge/Gemfile RUBYOPT=-I/hoge/.rbenv/versions/2.0.0-p0/lib/ruby/gems/2.0.0/gems/bundler-1.3.1/lib -rbundler/setup
確かに環境変数がセットされていました。
具体的には、BUNDLE_BIN_PATH と RUBYOPT の bundler/setup がいけなかったようです。
対応
参照した記事と同様に、bundle package を実行する際に、
bundler関連の環境変数をリセットする処理を入れると。想定通りに動きました。
def bundle_package execute "bundle packaging" do with_clean_env do system("cd #{destination} && bundle package --all") end end end def with_clean_env bundled_env = ENV.to_hash %w(BUNDLE_GEMFILE RUBYOPT BUNDLE_BIN_PATH).each{ |var| ENV.delete(var) } yield ensure ENV.replace(bundled_env.to_hash) end
結局のところ
色々頑張ってみたけど、実は bundler には、
with_clean_env
なるメソッドが実装されていて、さらにその状態でコマンドを実行する
with_clean_system
まで用意されていました。
なので、自前で書かずとも、
def bundle_package execute "bundle packaging" do Bundler.clean_system("cd #{destination} && bundle package --all") end end
とかやればOKでした。
それはそうと、とりあえずcopyストラテジーで bundle package が使いたいだけなんだけど?
という方は、自分のリポジトリではないですが、
https://github.com/rainux/capistrano-strategy-copy-with-bundle-package
とかを参照したら良い感じになるのではないでしょうか。
勉強になりました。
おしまい。
0 件のコメント:
コメントを投稿