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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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

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.

1
2
3
4
5
cap staging deploy:check
cap staging deploy
# or
cap production deploy:check
cap production deploy

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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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

When this code is used you will get something like the image below.

Warning when deploying to production

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!

Posted in Hosting, Programming, Rails, Ruby at January 6th, 2009. Trackback URI: trackback Tags: , , , Written by: 
  • Jason

    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.

    1
    2
    * == Currently executing `multistage:ensure'
    No stage specified. Please specify one of: staging, beta, production (e.g. `cap staging deploy')

    Any ideas?

  • Mathias Stjernstr√∂m

    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.

  • Jason

    Ah, got it. Thanks Mathias!

  • Mathias Stjernstr√∂m

    Superb!

    Glad I could help.

  • Zeeshan

    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

    #####################################

  • Mathias Stjernstr√∂m

    Thanks Zeeshan!

    Thats a great addition!

    Sheers!

  • Thomas Peter Berntsen

    Thanks very much for the elegant and useful solution.

  • http://www.evanreeves.com/blog Evan Reeves

    I don’t think that Capistrano supports role definition within tasks as of version 2.5.21. I tried to configure my tasks similarly and received errors when trying to define my roles in a similar manner.

It's past my bedtime is using WP-Gravatar