Capistrano: Multistage
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:
1 |
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:
1 2 |
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:
1 2 3 |
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”.
Done!
Reader Comments
Ah, that is excellent. We’ll definitely be using this!
23 Jul 2007
And just days after I finally got my multistage deployment recipe working!
Thanks for the great work.
23 Jul 2007
@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.
23 Jul 2007
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?
23 Jul 2007
Good point, Tom. I’ll see about making that more implicit in a future release.
23 Jul 2007
The line
require ‘capistrano/ext/multistage’
goes in config/deploy.rb right?
23 Jul 2007
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>
23 Jul 2007
@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. :)
23 Jul 2007
This is excellent. Thank you very much for this and all the work that goes into Capistrano and the tool in general. Top notch!
24 Jul 2007
This looks interesting but I am not clear about what Multistage is or what problem this solves. Could someone elaborate a little?
Thanks!
29 Jul 2007
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.
29 Jul 2007
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.
9 Aug 2007
This is exactly what I’ve been looking for. Thanks for that.
15 Aug 2007
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.
21 Aug 2007
@Hob, that would work, just put the variable in a proc, so it is evaluated lazily:
set(:deploy_to) { ”/path/to/#{application}/#{stage}” }
21 Aug 2007
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 Sep 2007
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.
17 Sep 2007
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
-DJ
17 Sep 2007