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:
Post a Comment