rails 3, bundler, capistrano

March 17, 2010

in software

Deploying a rails app with capistrano got just a little bit trickier with the new bundler integration. Here’s a super-simplified task you can tack onto the end of your deployment recipe to make sure that your server gets a bundle set up (and updated, if need be):

namespace :bundler do
  task :create_symlink, :roles => :app do
    shared_dir = File.join(shared_path, 'bundle')
    release_dir = File.join(current_release, '.bundle')
    run("mkdir -p #{shared_dir} && ln -s #{shared_dir} #{release_dir}")
  end
 
  task :bundle_new_release, :roles => :app do
    bundler.create_symlink
    run "cd #{release_path} && bundle install --without test"
  end
end
 
after 'deploy:update_code', 'bundler:bundle_new_release'

You’ll likely want to customize this further — maybe restrict what’s installed by bundler based on the rails environment, etc. This should generally work though, in case you don’t feel like thinking about it anymore, like i do…

[Update]
I added symlinking to a shared dir to make not re-install each time, after finding a couple more cap recipes online. This is a great post, and basically had the original code here plus a few extras.

sheboigan!

{ 1 trackback }

links for 2010-08-17 « Caiwangqin’s delicious bog
August 17, 2010 at 7:04 pm

{ 8 comments… read them below or add one }

neal clark April 13, 2010 at 4:02 am

hey matt, great post! i integrated part of it into my first production bundler deploy. cheers!

the biggest change i made was not to call ‘bundle install’ if ‘bundle check’ tells me there’s nothing to install. here’s what i have for the ‘bundle install’ step on my app (i have no idea how this will look when pasted into your blog):

task :bundle, :role => [:app, :web] do
deploy.create_bundler_symlink
run “cd #{release_path} ; bundle check 2>&1 > /dev/null ; if [ $? -ne 0 ] ; then sh -c ‘bundle install –disable-shared-gems –without test’ ; fi”
end

thanks for the help!

matt April 13, 2010 at 7:51 am

I think it came through correctly here… thanks for the tip, I think I’m gonna try it myself!

Michael Pearson July 19, 2010 at 11:35 pm

Thanks, you just saved me my afternoon. (see: https://gist.github.com/f25b7b8b4a63b398a400)

J. Pablo Fernández July 29, 2010 at 8:30 am

You could cd to #{current_path} and avoid creating the symlink at all. By the way, under which user are you deploying and which user are you running the app as?

matt July 29, 2010 at 2:38 pm

You’re right, but what I wanted to accomplish was not having the bundle re-generated during each deployment. If the bundle configuration remains the same, it doesn’t have to “re-install” anything if you use the symlink approach. If you don’t mind the extra deployment time (and space taken up by multiple copies of bundles), then it’s not necessary to symlink.

I generally run rails applications as a custom user, and deploy “as” another one. That’s entirely up to you and your particular deployment scenario — i.e., what kind of access you have, how your web server is configured, etc, etc. Of course, you can always run and deploy as root if you feel like living on the edge…

kazjote August 4, 2010 at 9:12 am

Thanks for great recipe :)

I use it already for some time and found an issue with failing deployments.

In simple words, if anything goes wrong during the deployment after bundler install task you will end up with unbootable application state.

The solution is to provide on_rollback tasks which I covered on my blog: http://kazjote.eu/2010/08/04/bundler-and-capistrano-the-right-way

Evan August 31, 2010 at 8:48 pm

Looks like this is easier to deal with these days, add the following to your deploy.rb:

require ‘bundler/capistrano’

…and you’re done!

see also http://github.com/carlhuda/bundler/blob/master/lib/bundler/capistrano.rb

matt September 1, 2010 at 2:25 pm

Cool, thanks! I knew it would just be a matter of time…

Leave a Comment

Previous post:

Next post: