Rails 3 and Heroku: automatically "rake db:migrate" on push?

24,048

Solution 1

Here is a rake task that wraps up everything into a one-liner (and also supports rollback):

https://gist.github.com/362873

You still might wind up deploying on top of your boss's demo, but at least you don't waste time typing between the git push and the rake db:migrate.

Solution 2

Heroku now has the ability to handle this as part of their "release phase" feature.

You can add a process called release to your Procfile and that will be run during each and every deploy.

Rails >= 5 Example

release: bundle exec rails db:migrate

Rails < 5 example

release: bundle exec rake db:migrate

Solution 3

What about this simple command chaining solution:

git push heroku master && heroku run rake db:migrate

It will automatically run the migrate as soon as the first one finishes successfully. It's tipically 1-2 seconds delay or less.

Solution 4

I created a custom buildpack that gets Heroku to run rake db:migrate for you automatically on deployment. It's just a fork of Heroku's default Ruby buildpack, but with the rake db:migrate task added.

To use it with your app you'd do this:

heroku config:set BUILDPACK_URL=https://github.com/dtao/rake-db-migrate-buildpack

Also note that in order for it to work, you need to enable the user-env-compile Heroku Labs feature. Here's how you do that:

heroku labs:enable user-env-compile

And here's my evidence that this works:

rake db:migrate on Heroku deployment

Solution 5

Perhaps you could try separating your schema commits (migrations, etc.) commits from code commits (models, validations, etc.).

(Note the following assumes your migration changes are NOT destructive, as you've indicate covers most of your use cases.)

Your deploy process could then be:

  1. Push schema changes to Heroku
  2. migrate
  3. Push application code to Heroku

This is of course far form optimal, but is an effective way to avoid downtime in the situation you've described: by the time the app receive the code for the dynamic fields, the DB will already have migrated.

(Of course, the simplest solution would be to simply push and migrate while your boss is out to lunch ;-D)

Otherwise, even if schema modifications were carried out automatically you'd still run the risk of a request passing through right before the migrations have been run.

Share:
24,048
Max Williams
Author by

Max Williams

Updated on July 05, 2022

Comments

  • Max Williams
    Max Williams almost 2 years

    I have a slight annoyance with my heroku push/deploy process, which otherwise has been a joy to discover and use.

    If i add a new migration to my app, the only way i can get it up onto the heroku server is to do a push to the heroku remote. This uploads it and restarts the app. But it doesn't run the migration, so i have to do heroku rake db:migrate --app myapp, then heroku restart --app myapp. In the meantime, the app is broken because it hasn't run the migrations and the code is referring to fields/tables etc in the migration.

    There must be a way to change the deployment process to run the rake db:migrate automatically as part of the deploy process but i can't work it out.

    Is it something i set in a heroku cpanel? Is it an option i pass to heroku from the command line? Is it a git hook? Can anyone set me straight? thanks, max

  • Max Williams
    Max Williams about 13 years
    That's just not satisfactory i'm afraid: i want to be able to deploy at any time without worrying about whether my boss is demoing the site to clients or whatever (at which time the appearance of a maintenance page would mean a very angry boss). Thanks for answering though :)
  • Aditya Sanghi
    Aditya Sanghi about 13 years
    Do you really want to be deploying while your short-fused boss is demoing? I'm not sure heroku provides this feature as yet! The best thats currently possible is no human wait in the meantime.
  • Max Williams
    Max Williams about 13 years
    I don't want to but it inevitable happens :) In my non-heroku apps it's fine as long as the migration is non-destructive, which it almost always is (ie they are usually to add new fields or new tables, rather than delete anything). So, you have an interim period where the old code is running with the new schema, which is generally fine (as the schema only contains additions), then after the migration finishes a rolling restart of the mongrels/unicorns happpen, which has very little if any noticeable downtime/slowdown.
  • Max Williams
    Max Williams almost 13 years
    i ended up going with your solution after Paul (below) posted an actual rake task up. Guess i was just too lazy to write my own. Thanks :)
  • GMA
    GMA over 10 years
    YES. 10 seconds of work to set up and it's exactly what I was looking for. Much better than the other answers here, at least for my purposes. Thanks.
  • Dorian
    Dorian about 10 years
    My recommendation would be to fork the project and use the fork as the deploy process. Because here you trust a Github repo to deploy your production code.
  • Nathan
    Nathan about 10 years
    I preferred an object-oriented version of the gist mentioned: gist.github.com/jfeaver/9820478
  • GMA
    GMA about 10 years
    Good point. However, this repo doesn't work anymore anyway because user-env-compile, which it depends on, has been removed. :(
  • Matt
    Matt about 10 years
    Should the migration fail, this leaves you in a bit of a mess though.
  • link0ff
    link0ff almost 10 years
    If the migration fails, roll back the last release. Otherwise, restart the app to use new schema changes.
  • reconbot
    reconbot over 9 years
    This is great, it looks .. almost exactly like the one I use. =)
  • Gon Zifroni
    Gon Zifroni about 9 years
    Don't do this, on Heroku your DB connection might not be ready at that specific point in the deploy process.
  • slothbear
    slothbear about 9 years
    heroku_san hasn't been updated in a while, but I'm using it on Rails 4.2 projects without problems.
  • cwd
    cwd over 8 years
    I think this gist may be a bit outdated now - the code seems like it is from heroku's earlier days when more manual intervention was required after a push
  • eloyesp
    eloyesp about 8 years
    You can force push to heroku so you can skip all those merges and just force push master after running the migration.
  • Loubot
    Loubot over 7 years
    Gave the +1. I had to change it to rake db:migrate
  • Max Woolf
    Max Woolf over 7 years
    yeah, Rails 5 replaces rake globally with the rails binary. I'll update my answer.
  • Loubot
    Loubot over 7 years
    Cheers for that. Haven't moved to rails 5 yet.
  • hajpoj
    hajpoj over 7 years
    docs: devcenter.heroku.com/articles/release-phase Note release phases are in Beta and the commands run when a new release is created (ie 1. an app build 2. a pipeline promotion 3. a config var change 4. a rollback 5. a rlease via the Platform API)
  • Mark Swardstrom
    Mark Swardstrom over 2 years
    Don't forget to add -a appname if you have more than 1 app referenced in git remotes