Thursday, December 3, 2009

Rakefile: Prevent destructive rake tasks in the production environment.

We are using the same server for our staging and production deploys. The problem is that the default RAILS_ENV is set to production so when I go to the staging app and start messing about with rake db:seed (or worse, rake db:reset) I am almost always a hair's breadth away from imminent death.

(Here's a handy bash script I wrote to easily switch between your Rails environments.)

So I decided to do something about it and protect destructive or database altering rake tasks from being run in the production environment. I really like this approach and I think I'll use it in future projects regardless of the setup. The fact is you only do a rake db:reset in production once, during the cold deploy of your app. It allows rake db:migrate and its variants, but not rake db:migrate:reset. Look at the code for the full list of restricted rake tasks. The tasks in PROTECT_SOME are matched explicitly, PROTECT_ALL restricts all variants of that task.

This shows the warning message and confirmation that appear. If you know what you are doing, or you want to automate things with Capistrano and need to run one of the protected tasks just pass FORCE=true to the task.

[deployer@rails1 ~/rails_apps/rails1.creagency.com.au/current] echo $RAILS_ENV
production
[deployer@rails1 ~/rails_apps/rails1.creagency.com.au/current] rake db:reset
(in /www/rails_apps/rails1.creagency.com.au/releases/20091204033227)
****************************************************************************
* WARNING! You are in the PRODUCTION environment and are running a Rake task 
* that will DESTROY your PRODUCTION database!
* 
* If you know what you are doing you can run this task with FORCE=true to
* prevent this message appearing.
****************************************************************************

Are you sure? (Yes|No) [No]

Quitting.
[deployer@rails1 ~/rails_apps/rails1.creagency.com.au/current] 
And here is the code. Just add it to the bottom of your application's Rakefile:

2 comments:

Anonymous said...

Why don't you just create a "staging" environment?

Karl Varga said...

We have one now, but at the time we didn't so we had staging and production on the same box.

That said, this is useful just to prevent inadvertently running destructive tasks against your production environment, which you would never want to do.