Tips for Upgrading to Capistrano 2 15 comments

posted Friday, April 27, 2007 by topfunky

So Jamis Buck has been hard at work on a new version of Capistrano, the deployment and automation tool for any task that a sysadmin could possibly imagine doing on a server.

There’s a new website and also the start of a wiki. There is a new engine that separates the parts so they can be used independently.

There are also a few changes that break existing recipes. No worries…they are easy to fix. Here’s how I did it.

Get Capified

Install the pre-release gem. You might need to get Highline first.

sudo gem install highline
sudo gem install -s http://gems.rubyonrails.com capistrano

Tell Capistrano install the new Capfile in your Rails application.

$ cd my_rails_app
$ capify .

Comment out all external libraries

Any external task libraries will probably be incompatible with Capistrano 2. I commented them all out and started from scratch (although the authors will probably update them in the next few weeks).


# require 'railsmachine/recipes'
# require 'deprec/recipes/cache_svn'
# require 'vmbuilder/plugins'

Some are actually included in the main distribution now, like Chris McGrath’s recipe that updates a cached copy of your code on the server. It’s now available with this setting:


set :deploy_via, :remote_cache

If you don’t already have a cached copy on the server, it will make one for you in shared/cached-copy. Subsequent deployments will just do an svn update on that directory instead of doing a full checkout every time. A fresh copy is then copied into the releases directory. This is a much faster way to deploy and I use it on every one of my deployments.

Note: If you were using this technique before, you can use the old repository_cache variable and it will work as expected.


set :repository_cache, "#{shared_path}/svn_trunk/" 
set :deploy_via, :remote_cache

The default task

Namespaces are nice, but they will break older recipes that use callbacks such as after_deploy. There’s now a default task inside the deploy namespace that you can use instead.

I wrote a simple callback that runs the cleanup task after every deployment.


namespace :deploy do

  desc "Run this after every successful deployment" 
  task :after_default do
    cleanup
  end

end

Other callbacks work the same way. Just put them inside your namespace and they will work normally.


namespace :deploy do

  task :after_update_code do
    # ...
  end

  task :before_symlink do
    # ...
  end

end

One thing I haven’t figured out yet is how to call tasks in another namespace. For now, you can just call local tasks as methods as usual. See the call to cleanup above.

Override the deployment altogether

For this blog I have a special deployment file that just updates the theme and clears out the cache. I can still deploy with cap deploy, but it skips update_code, symlink, and the other steps.

For that, I just override the deploy:default task.


namespace :deploy do

  desc "Update the theme and delete cached files." 
  task :default do
    # Call custom tasks in this namespace
    update_theme
    sweep_cache
  end

  task :update_theme do
    # ...
  end

end

Make directories

My first few deployments failed because there was no shared/pids directory to link to from the current/tmp/pids directory. In fact, that directory didn’t exist, either.

I ran the deploy:setup task and added empty tmp directories to svn. There are now directories that can be properly linked to.

Restart Mongrel

Bradley Taylor is probably fixing this right now, but until the next mongrel_cluster gem is released, you can restart mongrel with this task:


set :mongrel_config, "/etc/mongrel_cluster/#{application}.yml" 

namespace :deploy do

  task :restart do
    sudo "mongrel_rails cluster::restart -C #{mongrel_config}" 
  end

end

Relevant PeepCode

If you want to learn more about Capistrano, check out the PeepCode episode on the topic. It will be updated for Capistrano 2 after the official release and will be a free update for anyone who bought it previously.

And in other news

The new Rails Podcast with Zed Shaw already has people rolling in the aisles with laughter, amazement, and hate.

This blog is now running on nginx from top to bottom with Rails and PHP running side by side. Some of my notes and scripts are available.

I had the honor of being interviewed by Fabio Akita (also in Brazilian Portuguese).

Travels are hardly over before they start again. I’ll be speaking at RailsConf in Portland in May, Ruby en Rails in Amsterdam June 7 (no website available yet), and Ostrava on Rails in the Czech Republic June 22-23.

And thanks to the incredible support of the Ruby community, I’ll be going fulltime on PeepCode Screencasts next month! I’m putting the final coat of wax on the next episode (Javascript with Prototype, together with Justin Palmer).

15 comments

Leave a response

  • Thanks for the tips!

    Not sure which Chris you’re trying to refer to in the “Comment out all external libraries” section, but you reference Chris Wanstrath (http://errtheblog.com) but link to Chris McGrath (http://octopod.info/).

  • Congrats on going full-time with the Peep!

  • Gravatar icon topfunky

    See, that’s the benefit of having a link and a title…you’re bound to get at least one of them correct!

    I was actually referring to Chris McGrath and have fixed it now.

  • Gravatar icon Rahsun McAfee

    1) Congrats on Full Time with Peepcode!

    2) The last Ruby on Rails podcast interview was great for sure!

    3) Freely updating Capistrano peepcode to version 2 for those who already paid is a demostration of the type of service that everyone should pay attention to!

  • Gravatar icon David Parker

    I just got through with Peepcode’s REST screencast and I posted a review on Lulu. Great stuff Geoffrey! I’ll definitely be checking out more Peepcode videos in the future! And congrats on going full time with it!

  • Say you have a namespace info and a task httpd_mem:

    namespace :info do
      desc "Get top 5 httpd processes by real memory usage" 
      task :httpd_mem, :roles => [:web, :stats, :cms] do
        run <<-CMD
        ps axcmo pid,rsz,command | grep httpd | awk '{LIMIT = 1; if ($2 > LIMIT) printf $2/1024 " MB\n"}' | sort -rn | head -n5
        CMD
      end
    end

    To execute that task in another namespace:

    namespace :whatever do
      task :httpd_mem do
        info.httpd_mem
      end
    end

  • Gravatar icon topfunky

    @Jesse: Awesome. Thanks for the explanation.

  • Gravatar icon Tim Carey-Smith

    For those wanting to have a look at a mongrel_cluster recipe for cap 2.0, here is the recipe file.

    Note the use of ‘before’ and ‘after’ callbacks and also the ‘depend’.

    I also, override the “deploy:setup” task as I assume you are using the “mongrels” as your app servers.

  • I recently created a recipe for cap 2 that deploys Mint using some code from your post on the Mint forums. I wanted it to be tied a bit tighter with the app itself.

    Hopefully somebody can set me straight if I’m way off base, but it’s working well for me.

  • Older tasks not in any namespace will still work, such as :before_deploy and :after_deploy. In this article Jamis mentions that they will be deprecated in the future.

  • Older tasks not in any namespace will still work, such as :before_deploy and :after_deploy. In this article Jamis mentions that they will be deprecated in the future.

  • I’ve put together a Rails plugin called “Capistrano Bells” that gives you a collection of Capistrano 2 recipes to use while developing and deploying your app. My main focus was to take the parts of the deprec gem that I missed most and make the Capistrano 2 friendly.

    It’s my first attempt at a Rails plugin, and it’s still not totally finished. Still, I was able to use it to deploy a new project, and it worked well enough.

    If you’re interested, you can check it out here: Introducing: Capistrano Bells

  • One thing I haven’t figured out yet is how to call tasks in another namespace.

    looks like you can call the name space as an object, and the task as a method.

    so you can call deploy.migrate outside the :deploy namespace

    cheers,Jodi

  • looks like you can call the name space as an object, and the task as a method.

    so you can call deploy.migrate outside the :deploy namespace

    That doesn’t work for me…
    namespace :deploy do
      task :after_cold do
        web.restart
      end
    end
    
    namespace :web do
      task :restart, :roles => :web do
        default_run_options[:pty] = true # or else you'll get "sorry, you must have a tty to run sudo" 
        sudo "/etc/init.d/httpd restart" 
      end
    end
    
    results in…
      * executing `deploy:after_cold'
      * executing `deploy:restart'
    

    Using Capistrano 2.1.0.

  • great work, going to try upgrading to Capistrano 2 when they finally release Deprec 2

    all the best,

    John.

Your Comment

Nuby on Rails

Geoffrey Grosenbach / Ruby / Code / Graphics / Design / Rails / Merb / Javascript / CSS

Ads by The Lounge

Manufactured with

Subscribe

Subscribe (RSS)