Handling a staging environment with capistrano / rails
Just before christmas I worked with one of our customers new server cluster or cloud if you may.
This cluster has production nodes and staging nodes and this post is about how to get capistrano to play nice with both production and the staging environment.
I have googled for a solution but all solutions I found where pretty ugly so i decided to create my own. When writing this line I did a test googling just to give an example of a bad example and my first result where the buckblogs blog. A post about a plugin called multistage I do not how I could miss that
But as my solution is so simple I will continue this post and show you anyway.
As usual I have written to much bullshit and I guess that you just want is some code so here you go.
[cc lang="ruby"]
desc “Run tasks in production enviroment.”
task :production do
# Production nodes
role :app, “192.168.1.30″
role :app, “192.168.2.30″
role :db, “192.168.1.30″, :primary => true
end
desc “Run tasks in staging enviroment.”
task :staging do
# Staging nodes
role :web, “192.168.1.60″
role :app, “192.168.2.60″
role :db, “192.168.1.60″, :primary=>true
end
[/cc]
This is all there is to it. Splitting your role definitions into different tasks.
Now you may wonder how you use this when deploying or whatever you do.
Just add those tasks as params to cap.
[cc lang="bash"]
cap staging deploy:check
cap staging deploy
# or
cap production deploy:check
cap production deploy
[/cc]
And here is a little bonus
Just to spice this up a bit I added another useful function. A little warning if you are about to deploy to your production environment. When running a big/important site you do not want to deploy into the wrong environment
This is how the final code looks.
[cc lang="ruby"]
desc “Run tasks in production enviroment.”
task :production do
# Prompt to make really sure we want to deploy into prouction
puts “\n\e[0;31m ######################################################################"
puts " #\n # Are you REALLY sure you want to deploy to production?"
puts " #\n # Enter y/N + enter to continue\n #"
puts " ######################################################################\e[0m\n"
proceed = STDIN.gets[0..0] rescue nil
exit unless proceed == ‘y’ || proceed == ‘Y’
# Production nodes
role :app, “192.168.1.30″
role :app, “192.168.2.30″
role :db, “192.168.1.30″, :primary => true
end
desc “Run tasks in staging enviroment.”
task :staging do
# Staging nodes
role :web, “192.168.1.60″
role :app, “192.168.2.60″
role :db, “192.168.1.60″, :primary=>true
end
[/cc]
When this code is used you will get something like the image below.

And thats all there is to it. The only thing that I think is missing is a warning/notice if you do not specify either production/staging. Like it is now you will get an error when capistrano cannot find any valid servers.
Happy deploying!

I like what you’ve done and implemented it. However, I’ve run into an issue when attempting to use it. The warning prompt displays, but the multistage plugin complains about no stage being specified.
* == Currently executing `multistage:ensure'
No stage specified. Please specify one of: staging, beta, production (e.g. `cap staging deploy')
Any ideas?
Jason
on June 17th, 2009 at 3:57 am
Hi Jason,
Thanks for your comment. My solution to multiple deploy targets is not dependent on the multistage plugin/gem. Maybe I was to unclear in my post.
If you have any references in your deploy.rb to the multistage plugins try comment those out or uninstall the multistage plugin and I thing you will be fine.
If you do want to use the multistage plugin you can follow the instructions on Jamis blog here: http://weblog.jamisbuck.org/2007/7/23/capistrano-multistage
Thanks.
Mathias Stjernström
on June 17th, 2009 at 7:45 am
Ah, got it. Thanks Mathias!
Jason
on June 17th, 2009 at 11:25 pm
Superb!
Glad I could help.
Mathias Stjernström
on June 18th, 2009 at 9:46 am
To add warning/notice if you do not specify either production/staging stage, one can do following:
#####################################
…
set :stage, nil
…
task :before_deploy do
abort “ERROR: No stage specified. Please specify one of: staging, production (e.g. `cap staging deploy’)” if stage.nil?
end
desc “Run tasks in production enviroment.”
task :production do
# Production nodes
set :stage, “production”
…
end
desc “Run tasks in staging enviroment.”
task :staging do
set :stage, “staging”
…
end
#####################################
Zeeshan
on October 4th, 2009 at 11:42 pm
Thanks Zeeshan!
Thats a great addition!
Sheers!
Mathias Stjernström
on October 5th, 2009 at 6:26 pm
Thanks very much for the elegant and useful solution.
Thomas Peter Berntsen
on November 11th, 2009 at 3:19 pm