View Rahoul Baruah's profile on LinkedIn Basecamp project management and collaboration

The blog of Rahoul Baruah from 3hv Ltd

What's going on?

My name is Rahoul Baruah (aka Baz) and I'm a software developer in Leeds (England).

This is a log of things I've discovered while writing software in Ruby on Rails. In other words, geek stuff.

However, I've decided to put this blog on ice - I would ask you to check out my business blog here (or subscribe here).

15 March, 2007

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"
end
end


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/sh
cap -S stage=staging deploy
# deploy_to_production
#! /bin/sh
cap -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.

No comments:

eXTReMe Tracker