Deploying to Multiple Stages

Multistage is an easy way to write your deployment script for multiple environments. Typically you might have a development, testing and production environment. The deployment strategy values might differ ever so slightly between these different environments(stages) and you don't want to write the same task 3 times over for each environment. Another typical usage might be to deploy different applications/code/<whatever you're deploying> to the same set of servers.

Note: This wiki article will assume you are starting from scratch as this makes it easier to explain and give examples.

Installation

Capistrano Multistage ships in its own gem, install with:

# gem install capistrano-ext

Secondly create a sandpit directory:

$ mkdir -p tms/config/deploy

tms stands for "Test Multi-Stage"

The config and deploy directories is the directory structure expected by Capistrano and will be required if you want your deployment to work without any further modifications.

Edit tms/capfile and add the following two lines:

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

The first line will set two stages called dev and prod. This can be more dynamic but more on that later. the second line one would hope is kind of self explanatory...

The author always use the following task to do testing with but you are free to add any testing task that you might prefer.

task :uname, do
  run "uname -a"
end

That takes care of your main config file. Capistrano will now expect two files called dev and prod to exist in the tms/config/deploy directory.

Create these files and add a role definition in each such as:

dev

role :appservers, "devserver1", "devserver1"

prod

role :appservers, "appserver1", "appserver2"

That should be it. If you now run cap uname you will get the following message:

No stage specified. Please specify one of: dev, prod (e.g. `cap dev uname')

Following the instructions in the message, if you run

cap dev uname 

or cap prod uname

you will see your task being executed only for the stage that you specified.

Optionally you can also add the following line which will automatically deploy to the default stage specified. set :default_stage, "dev"