Capistrano: Multistage

Posted by Jamis on July 23, 2007 @ 07:59 AM

Some have long wanted a built-in way to support multiple-stages in Capistrano. I’ve been pushing back with the statement that it is easy enough to do in Capistrano manually. Still, I finally compromised and added a “multistage” component to the “capistrano-ext” plugin. You want staging support? Just “gem install capistrano-ext” and then:

require 'capistrano/ext/multistage'

Then, put your custom stage-specific code in config/deploy/staging.rb and config/deploy/production.rb. That’s it. You now deploy via “cap production deploy” and “cap staging deploy”.

If you have other stages you want to support, just set the :stages variable to an array of strings, naming each stage, prior to requiring the multistage module:

set :stages, %w(staging production testing)
require 'capistrano/ext/multistage'

By default, if you omit the stage when you execute a task, Capistrano will abort with a message saying that you need to specify a stage. If you’d rather just default to a stage, set the :default_stage variable:

set :stages, %w(staging production testing)
set :default_stage, "testing"
require 'capistrano/ext/multistage'

Then, when you do “cap deploy”, it will default to “cap testing deploy”.


Posted in Announcements


Have something to add? Click here to leave a comment.

23 Jul 2007

1. Ryan Allen said...

Ah, that is excellent. We’ll definitely be using this!

2. Gaius said...

And just days after I finally got my multistage deployment recipe working!

Thanks for the great work.

3. Ben Reubenstein said...

@Gaius – Ha ha! Me too. I have a simple case statement that takes an argument to switch up some variables for deployment to various spots.

4. Tom Ward said...

This looks excellent. Great work (as is the rest of Capistrano).

One question though: why the need to explicitly state available stages in the recipe? Can’t this be determined by the contents of config/deploy?

5. Jamis said...

Good point, Tom. I’ll see about making that more implicit in a future release.

6. Capify Newbie said...

The line

require ‘capistrano/ext/multistage’

goes in config/deploy.rb right?

7. joost said...

Brilliant. I know it’s easy to build by hand, but having this as an official gem makes it much easier to use. Opinionated, so to speak. <g>

8. Jamis said...

@Newbie, yes.

@joost, that was part of the motivation, to provide a standard way of doing it, so that it was easier to troubleshoot issues that arise. :)

24 Jul 2007

9. Kent said...

This is excellent. Thank you very much for this and all the work that goes into Capistrano and the tool in general. Top notch!

29 Jul 2007

10. Ben said...

This looks interesting but I am not clear about what Multistage is or what problem this solves. Could someone elaborate a little?


11. Jamis said...

Ben, if it doesn’t make sense to you, then you almost certainly don’t need it. :) The idea is that for your applications, you’ll have your production environment that is public facing. But then you might also have a “staging” environment, where you can test in-house, maybe have a few beta testers hit, and so forth, without exposing all those glorious new features (and nasty bugs) to your real users. The multistage module this post announces is one way to configure Capistrano so that you can deploy the same application to these different environments, with a minimum of duplication.

09 Aug 2007

12. nicholas a. evans said...

Thanks a lot for this! I had been rolling my own version of it, and yours is a fair bit more elegant.

Not only is this nice for multiple “staging” environments (qa, production, etc), but it’s also nice if you deploy the same app to different clients: client_one-qa, client_one-production, client_two-nightly, client_two-qa, client_two-production, etc.

15 Aug 2007

13. Brian McQuay said...

This is exactly what I’ve been looking for. Thanks for that.

21 Aug 2007

14. Hob said...

Very nice. I was just getting to the point where I was going to have to deal with just this issue. Thanks Jamis.

One question: Is there a method available in our recipes for determining the current stage? Might help DRY out lines like:

set :deploy_to, ”/path/to/#{application}”/#{stage}

Instead of having to put that line in each deployment file.

15. Jamis said...

@Hob, that would work, just put the variable in a proc, so it is evaluated lazily:

set(:deploy_to) { ”/path/to/#{application}/#{stage}” }

17 Sep 2007

16. David James said...

Hi Jamis, thanks for this handy write up.

I think capistrano-ext needs a small tweak to remove a deprecation message with Cap 2.0.

`cap deploy:setup` gives: [DEPRECATION] Capistrano.configuration is deprecated. Use Capistrano::Configuration.instance instead

I believe the deprecation message comes from line 292 in monitor.rb in capistrano-ext-1.2.0. Not sure if/where there is a Trac for capistrano-ext…?

17. David James said...

On my last comment, I think I spoke too soon—it looks like you specifically crafted the logic to work both with Cap 1.x and 2.0. :) I think I’ll just tweak my local source code to get rid of the deprecation message.

18. David James said...

Ok, last post of the evening (crossing fingers). recipes.rb of mongrel_cluster-1.0.2 was the real culprit, not capistrano-ext. I changed the beginning of recipes.rb to look like this (borrowing some code from capistrano-ext, thanks!):

configuration = Capistrano::Configuration.respond_to?(:instance) ? Capistrano::Configuration.instance(:must_exist) : Capistrano.configuration(:must_exist)

configuration.load do set :mongrel_servers, 2 set :mongrel_port, 8000