multistage 環境で capistrano-rbenv を使うときは rbenv_path の扱いに注意!
タイトル読んで納得した人は読み飛ばしてください。
VM の設定が完了するのを待ちつつ Fulentd Casual Talks #2 の ust 聞きながらこれを書いてます。
capistrano-rbenv 使ってますか?
デプロイ先で rbenv を使う場合は capistrano-rbenv が非常に便利です。
config/deploy.rb に
# rbenv setting require 'capistrano-rbenv' set :rbenv_ruby_version, '1.9.3-p374' set :default_environment, { 'RBENV_ROOT' => "#{rbenv_path}", 'PATH' => "#{rbenv_path}/shims:#{rbenv_path}/bin:$PATH" }
と書いておくだけで rbenv を利用し始めることができます。
まだ rbenv をインストールしていないのであれば
$ cap deploy:setup
とするだけで、rbenv もインストールしてくれます。すばらしいですね。
multistage と capistrano-rbenv の組み合わせ
でも、一個だけ罠があります。
capistrano を使うときに、ほぼ必須とも言える multistage プラグイン(capistrano/ext/multistage)と
この capistrano-rbenv を同時に使うとハマる箇所がひとつあるのです。
それは先ほどの設定で出てきた rbenv_path という変数です。
よく見ると :default_environment を設定するときに利用しているやつです。
実はこの rbenv_path、値を参照する際にデプロイ先と通信する(インストールされているか確認する)ため、
multistage を有効にした状態で先ほどの設定を行うと、エラーで失敗します。
$ bundle exec cap dev deploy:setup * executing "echo $HOME/.rbenv" no servers found to match {:once=>true, :eof=>true}
multistage プラグインがデプロイ先ホストを決定する前に rbenv_path が通信しようとしてしまうためです。
これを防ぐためには :default_environment を決めるタイミングを multistage の実行後にずらします。
namespace :rbenv do task :setup_shellenv do set :default_environment, { 'RBENV_ROOT' => "#{rbenv_path}", 'PATH' => "#{rbenv_path}/shims:#{rbenv_path}/bin:$PATH" } end after 'multistage:ensure', 'rbenv:setup_shellenv' end
そうすると、以下のように実行タイミングが調整されてうまく rbenv を利用することができます。
bundle exec cap dev deploy:setup ~/Dropbox/gnavi/gnavi-gauth-infra triggering load callbacks * 2013-02-18 11:49:28 11:49:28 == Currently executing `dev' triggering start callbacks for `deploy:setup' * 2013-02-18 11:49:28 11:49:28 == Currently executing `multistage:ensure' triggering after callbacks for `multistage:ensure' * 2013-02-18 11:49:28 11:49:28 == Currently executing `rbenv:setup_shellenv' * executing "echo $HOME/.rbenv" servers: ["localhost"] [localhost] executing command command finished in 73ms (以下略)
Web で探したら、rbenv_path を使わず直接値を書いている人もいましたが、
ユーザや OS が変わると必ずしも /home/foo/.rbenv になるとは限らず、
いずれコピペで失敗しそうなのでこんな風にしてみました。
この部分も capistrano-rbenv が吸収してくれると幸せなんですけどねえ。