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 }
{ 8 comments… read them below or add one }
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!
I think it came through correctly here… thanks for the tip, I think I’m gonna try it myself!
Thanks, you just saved me my afternoon. (see: https://gist.github.com/f25b7b8b4a63b398a400)
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?
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…
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
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
Cool, thanks! I knew it would just be a matter of time…