When I stumbled across Richard Huang’s DRY bundler in capistrano, I got excited thinking I’d learn even more about bundler’s internals and maybe even a few more tricks with using bundler and capistrano together. Unfortunately, all I really got was to use this in my deploy.rb:

require 'bundler/capistrano'

Now that will probably be enough for most people. But if you’re already using bundler 1.0 with capistrano, you probably aren’t most people.

The bundler team has put a lot of work into documenting every little part of the project, so after we’ve required bundler’s capistrato recipe, let’s grab the task explanation:

% cap --explain bundle:install
------------------------------------------------------------
cap bundle:install
------------------------------------------------------------
Install the current Bundler environment. By default, gems will be installed to
the shared/bundle path. Gems in the development and test group will not be
installed. The install command is executed with the --deployment and --quiet
flags. You can override any of these defaults by setting the variables shown
below.

  set :bundle_gemfile,      'Gemfile'
  set :bundle_dir,          fetch(:shared_path)+'/bundle'
  set :bundle_flags,        '--deployment --quiet'
  set :bundle_without,      [:development, :test]

You’re probably going to want to start playing around with bundler 1.0 on your dev machine before you deploy it on production. Since bundler 0.9 doesn’t support all the useful flags in 1.0, so we need to empty a couple of these default settings to make it work:

set :bundle_dir, ''
set :bundle_flags, ''

Now you can have 1.0 on your dev machines and test that this deploys properly.

If you’re like me, you forgot that need a few gems in your development group on your staging machine. So just set the groups you can live without:

set :bundle_without, [:test]

Of course, our production environment doesn’t actually need anything in the development group, and we use separate production and staging cap tasks to load settings for our different environments. So we just modify those to have the right bundler groups:

task :staging do
  set :bundle_without, [:test]
  # other staging specific settings, like
  # set :rails_env, 'staging'
end

task :production do
  # this is the default, but left here for reference
  set :bundle_without, [:development, :test]
  # other production specific settings, like
  # set :rails_env, 'production'
end

Once you’ve got everything tailored and working, you can update bundler on your boxes and restart the app servers. You could leave the bundle_dir and bundle_flags settings the way they are, but I strongly recommend using the --deployment flag to run in deployment mode, the --quiet flag to stop printing so much information, and a bundle directory in your shared_path instead of deployment mode’s default of vendor/bundle.

You’ll also want to start using bundle package to include all the gems you need into vendor/cache. Check that into your in your version control to make the deployment process even better, you won’t even have to talk to rubygems when you run bundle install during a deploy.

If you like more technical documentation, bundler goes into even more depth in its manual pages for bundle-install(1) and bundle-package(1). They explain in depth how deployment mode works differently, how conservative updating works, how gems are cached and quite a bit more. If you find yourself wanting even more control than I’ve explained here, that’s where I would look.