One of the first things I’ll do when working on a new project is to automate the build ASAP. Starting a new job a couple weeks ago, I took the opportunity to get CruiseControl.rb up and running and getting the tests running reliably.
At my last job, we had automated the build by having CC.rb run rake db:migrate followed by rake test. This worked out fairly well, and we made it a practice to peer-review all migrations before committing them.
This technique had a few drawbacks, however. One thing was that we were testing our migrations. If someone committed a migration that broke, the build would fail. Likewise, if someone committed a migration and then needed to change it later, we would have to manually roll back the database and re-migrate up, which was a pain in the butt.
Having the build run the migrations was nice, since other developers would be alerted to a potentially bad migration, but it ended up being more trouble than it was worth.
At my new job, there’s an established practice of using migrations to add static data to the database (which is the subject for another post). Migrations are an easy way to do this, but you run into trouble if the data being added depends on other data in the database, or if the migration was bad.
I’m of the opinion that you should avoid hitting the database as much as possible during tests, and by running migrations during the build (especially ones that depend on static data in the database), you end up coupling yourself even more tightly to the database.
After thinking about it for a while, I’ve decided that the schema.rb file is, after all, the de facto source of the database schema (big DUH here). Therefore, each build should wipe the the test database clean of tables and then load the schema.rb file from the repository.
Our new rule here now is that if you check in a new migration, you must also check in the new schema.rb.
By doing this, we consider migrations a tool for communicating small changes to developers over time, and we have a reliable, repeatable way to load a fresh db schema into a new development environment.
