Capistrano and Bundler

Sounds great doesn't it? Carefree deployments and gem management for your app. However, I ran into a few pitfalls that made the first experience less than carefree.

bundle:install step

After integrating bundler into capistrano with

require 'bundler/capistrano'

a bundle:install step gets kicked off to install your gems locally.  Pretty cool, but beware of defaults if you're on a multiserver deployment setup.  The default step flags are --deployment --quiet which will download all of the gems from the net.  Maybe not so bad for some folks but on a beefy rails app, this took forever across four servers and 38 gems.  Nevertheless, capistrano is easily customizable and can make this easier with the following line:

set :bundle_flags, "--deployment --quiet --local"

In order for this to work properly though, make sure and package up the gems with your application!

Custom rake tasks

The app I work on has a few custom steps for compiling a custom Ruby library, building extra documentation, etc. so there are a few more after "deploy:update_code" steps to address upon deployment.  Everything was pretty simple and easy to update for bundler; the only trick is knowing you have to do this update.

Each custom step was built into a rake task for lazyness in development, so each resembled something like this:

namespace :xapian do
   desc "Rebuild Xapian index."
   task :rebuild, :roles => :xapian_index do
     run "cd #{release_path}; rake xapian:rebuild_index models=\"MyModelName\"", :env => {'RAILS_ENV' => stage}
   end
end

We were calling rake directly, but this will lead you to step failures pretty quickly if the version of rake differs (or doesn't exist) in the deployment environment.  Simply replace rake with #{rake}.  The step will automatically be executed as #{bundle_cmd} rake instead (e.g. bundle exec rake by default).

 

Posted