Rails 3.2 からRails 4.2 に移行した際に、Capistrano 3 でのデプロイにハマった件。
環境
Ruby 2.1.4
Rails 4.2.1
Capistrano は、Rails 3.2 のものをそのまま使用した。
gem 'capistrano', '~> 3.0.1'
gem 'capistrano-rails', '~> 1.1'
gem 'capistrano-rbenv', '~> 2.0'
gem 'capistrano-bundler'
デプロイコマンド
bundle exec cap production deploy
ブランチが既に存在する旨のエラーメッセージ
INFO [9d4092d6] Running /usr/bin/env git branch issues/123-some-fixes origin/issues/123-some-fixes as yamy@localhost
cap aborted!
SSHKit::Command::Failed: git exit status: 32768
git stdout: Nothing written
git stderr: fatal: A branch named 'issues/123-some-fixes' already exists.
/path/to/project/vendor/bundle/ruby/2.1.0/gems/sshkit-1.7.1/lib/sshkit/command.rb:95:in `exit_status='
/path/to/project/vendor/bundle/ruby/2.1.0/gems/sshkit-1.7.1/lib/sshkit/backends/local.rb:85:in `block (2 levels) in _execute'
/path/to/project/vendor/bundle/ruby/2.1.0/gems/sshkit-1.7.1/lib/sshkit/backends/local.rb:63:in `block in _execute'
/path/to/project/vendor/bundle/ruby/2.1.0/gems/sshkit-1.7.1/lib/sshkit/backends/local.rb:58:in `tap'
/path/to/project/vendor/bundle/ruby/2.1.0/gems/sshkit-1.7.1/lib/sshkit/backends/local.rb:58:in `_execute'
/path/to/project/vendor/bundle/ruby/2.1.0/gems/sshkit-1.7.1/lib/sshkit/backends/local.rb:27:in `execute'
/path/to/project/lib/capistrano/tasks/git.cap:25:in `block (4 levels) in <top (required)>'
以下にエラーメッセージの該当箇所があった。
desc 'override git.rake taske update for repository'
task :update do
run_locally do
execute :git, :fetch, :origin
current_dir = capture "pwd"
if test " [ -f #{current_dir}/.git/refs/heads/#{fetch(:branch)} ] "
info "the branch #{fetch(:branch)} already exists at local"
else
execute :git, :branch, "#{fetch(:branch)}", "origin/#{fetch(:branch)}"
end
end
end
ロガーを追加して実行。
正常系(Rails 3.2)
INFO [18a14868] Running /usr/bin/env git fetch origin on
INFO [18a14868] Finished in 2.780 seconds with exit status 0 (successful).
INFO @@
INFO /path/to/project/.git/refs/heads/issues/100-some-fixes
失敗(Rails 4.2)
INFO [53acc449] Running /usr/bin/env git fetch origin as yamy@localhost
INFO [53acc449] Finished in 2.923 seconds with exit status 0 (successful).
INFO @@
INFO /path/to/project
/.git/refs/heads/issues/123-some-fixes
プロジェクトルート以降で改行されているため、先の判定処理で false になっているようだ。
さらに見ると、以下で改行が付加されていることが分かった。
current_dir = capture "pwd"
capture
は gem 'sshkit'
のメソッドで、移行作業の影響で capistrano と依存関係の gem のバージョンが更新されていることに気付いた。(sshkit 1.7.1)
Gemfile.lock
を見て、他の gem との依存関係も問題なさそうなので、前のバージョンに戻した。もともと明示的には Gemfile
に追加していなかった。
gem 'sshkit', '1.4.0'
これで、先のエラーは解消した。
rake assets:precompile が失敗する
INFO [c7d908ef] Running RBENV_ROOT=/usr/local/rbenv RBENV_VERSION=2.1.4 /usr/local/rbenv/bin/rbenv exec bundle exec rake assets:precompile on some-production-server
cap aborted!
SSHKit::Command::Failed: rake exit status: 1
rake stdout: Nothing written
rake stderr: Nothing written
/path/to/project/vendor/bundle/ruby/2.1.0/gems/sshkit-1.4.0/lib/sshkit/command.rb:98:in `exit_status='
/path/to/project/vendor/bundle/ruby/2.1.0/gems/sshkit-1.4.0/lib/sshkit/backends/netssh.rb:142:in `block (4 levels) in _execute'
/path/to/project/vendor/bundle/ruby/2.1.0/gems/net-ssh-2.9.2/lib/net/ssh/connection/channel.rb:551:in `call'
/path/to/project/vendor/bundle/ruby/2.1.0/gems/net-ssh-2.9.2/lib/net/ssh/connection/channel.rb:551:in `do_request'
しばらくこの情報をもとに調べていたが一向に解決せず、ふと Capistrano の Log level の存在を思い出し、 debug
に設定して確認。
#set :log_level, :info
set :log_level, :debug
DEBUG [dfb6c8fe] rake aborted!
DEBUG [dfb6c8fe] NameError: uninitialized constant ActiveRecord::Observer
DEBUG [dfb6c8fe] /path/to/project/shared/bundle/ruby/2.1.0/gems/multi_db-0.3.1/lib/multi_db/connection_proxy.rb:57:in `setup!'
DEBUG [dfb6c8fe] /ebs01/path/to/project/releases/20150623083226/config/environments/production.rb:71:in `block (2 levels) in <top (required)>'
DEBUG [dfb6c8fe] /path/to/project/shared/bundle/ruby/2.1.0/gems/activesupport-4.2.1/lib/active_support/lazy_load_hooks.rb:36:in `call'
しっかりエラーが表示されていた。
どうやら、Rails 4.0 から Observer が削除されたらしく、以下をGemfileに追加してリポジトリにpush。
gem "rails-observers"
参照: https://github.com/rails/rails-observers
devise のパラメタ不足
DEBUG [3b3ed770] rake aborted!
DEBUG [3b3ed770] Devise.secret_key was not set. Please add the following to your Devise initializer:
DEBUG [3b3ed770]
DEBUG [3b3ed770] config.secret_key = '***'
DEBUG [3b3ed770]
DEBUG [3b3ed770] Please ensure you restarted your application after installing Devise or setting the key.
DEBUG [3b3ed770] /path/to/project/shared/bundle/ruby/2.1.0/gems/devise-3.5.1/lib/devise/rails/routes.rb:480:in `raise_no_secret_key'
DEBUG [3b3ed770] /path/to/project/shared/bundle/ruby/2.1.0/gems/devise-3.5.1/lib/devise/rails/routes.rb:209:in `devise_for'
DEBUG [3b3ed770] /ebs01/path/to/project/releases/20150623094342/config/routes.rb:9:in `block in <top (required)>'
config/initializers/devise.rbに追加。
# Use this hook to configure devise mailer, warden hooks and so forth.
# Many of these configuration options can be set straight in your model.
Devise.setup do |config|
# The secret key used by Devise. Devise uses this key to generate
# random tokens. Changing this key will render invalid all existing
# confirmation, reset password and unlock tokens in the database.
config.secret_key = '***'
assets compile の設定が一部変更されている
DEBUG [9b394669] rake aborted!
DEBUG [9b394669] NoMethodError: undefined method `new' for true:TrueClass
DEBUG [9b394669] (in /ebs01/path/to/project/releases/20150623095211/app/assets/javascripts/application.js)
DEBUG [9b394669] /path/to/project/shared/bundle/ruby/2.1.0/gems/sprockets-2.12.3/lib/sprockets/context.rb:196:in `block in evaluate'
DEBUG [9b394669] /path/to/project/shared/bundle/ruby/2.1.0/gems/sprockets-2.12.3/lib/sprockets/context.rb:194:in `each'
DEBUG [9b394669] /path/to/project/shared/bundle/ruby/2.1.0/gems/sprockets-2.12.3/lib/sprockets/context.rb:194:in `evaluate'
DEBUG [9b394669] /path/to/project/shared/bundle/ruby/2.1.0/gems/sprockets-2.12.3/lib/sprockets/bundled_asset.rb:25:in `initialize'
DEBUG [9b394669] /path/to/project/shared/bundle/ruby/2.1.0/gems/sprockets-2.12.3/lib/sprockets/base.rb:377:in `new'
以下の記事を元に、config/environments/production.rbを修正。
# Compress JavaScripts and CSS
- config.assets.js_compressor = true
+ config.assets.js_compressor = :uglifier
assets のバックアップまわりで変更があった
DEBUG [6a19f5e1] cp:
DEBUG [6a19f5e1] target `/path/to/project/releases/20150623102330/assets_manifest_backup' is not a directory
以下の記事を参考に Capistrano 関連の gem のバージョンを調整。
最新版の Capistrano 3.4.0 ~ 3.2.0 までダウングレードした結果、3.1.0
でエラーがなくなった。
- gem 'capistrano', '~> 3.0.1'
- gem 'capistrano-rails', '~> 1.1'
+ gem 'capistrano', '3.1.0'
+ gem 'capistrano-rails', '~> 1.1.3'
参照: http://stackoverflow.com/questions/29617239/capistrano-3-sprockets-3-rails-4-2-1-wont-deploy
以上で、ようやく正常にデプロイされた。
まとめ
Capistrano は依存関係にある gem のバージョンにかなりシビアであることを再認識した。Rails 4 への移行の際、意図せず依存関係の gem が更新されていないか、事前に確認しておくと良さそうです。