Deploying to a Staging Server with Capistrano

Capistrano is one of my favourite Rails features. It’s vital to “agile” development - there’s no point running through your iterations, making fast, small changes, if you can’t easily get them into the hands of the (hopefully) paying public. (It’s also a major reason I’m not too interested in deploying on IIS any more).

However, one of the things I have found is that sometimes you get stuff that runs fine on your local boxes but fails on your server (I had a weird one where Bluecloth worked fine here but not there - despite freezing all my Gems and Rails itself).

So I wanted to set up an intermediate deployment on my server.

A quick hunt found Mike Burn’s article which I then adapted for my own purposes.

Firstly - created a new subdomain and database on my server - and a folder for deploying to.

Then I added a new environment file - /config/environments/staging.rb - this was a copy of development.rb but with code caching turned on.

Next, I set up a new database configuration in /config/database.yml - staging: that points to my newly created staging database.

To get Capistrano to deploy correctly, I amended /config/deploy.rb like so:

if stage == "production" set :deploy_to, "/home/user/myapp_live"else set :deploy_to, "/home/user/myapp_staging"end

I also needed to adapt things after the code had been copied, so the following was added to the end of deploy.rb:

desc "After updating the code, back up the database and migrate"task :after_update_code do run "/home/user/mysql/backup.sh"  # if this is a staging deployment, switch the environment to staging, not production  if stage == "staging"   # switch to the staging environment   run "sed -i 's/\"production\"/\"staging\"/' #{release_path}/config/environment.rb"   # migrate the database   run "cd #{release_path} && rake RAILS_ENV=staging db:migrate" else   # migrate the database   run "cd #{release_path} && rake RAILS_ENV=production db:migrate" endend

Basically, I did not trust the deploy_with_migrations task to work the way I wanted it to (I kept noticing rake RAILS_ENV=production db:migrate appearing in the log).

So instead I back up my database manually using a script and then - if I’m in production mode I just migrate the database (explicitly setting the Rails Environment). However, if I’m in staging mode then I use sed to change my environment settings (so that the line ENV["RAILS_ENV"] ||= “production” becomes ENV["RAILS_ENV"] ||= “staging”) and then migrate the database (explicitly setting the Rails Environment).

One final step - I created two shell scripts - deploy and deploy_to_production that look like this:

# deploy#! /bin/shcap -S stage=staging deploy# deploy_to_production#! /bin/shcap -S stage=production deploy

These call Capistrano’s deploy task, setting an internal variable stage to “staging” or “production” respectively.

Further Enhancements - I’m going to change deploy.rb so that it uses different Subversion Urls for staging and production - so staging pulls from http://mysvn/myapp/staging and production pulls from http://mysvn/myapp/live.

This entry was posted on Thursday, March 15th, 2007 at 11:48 am and is filed under Ruby on Rails and Software Development. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

Leave a Reply