by interexchange

GitHub Readme.md

Heroku buildpack: Ruby: InterExchange edition

This is my fork of the official Heroku Ruby buildpack. Use it when creating a new app:

heroku create myapp --buildpack \

Or add it to an existing app:

heroku config:add \

Or just cherry-pick the parts you like into your own fork.

Contained within are a few tiny but significant differences from the official version, distilled from project-specific buildpacks I've created in the past.

Custom compilation tasks

If the COMPILE_TASKS config variable is set, it will be passed verbatim to a rake invocation.

You can use this for all sorts of things. My favorite is db:migrate.

Database migration during compilation

Let's take a look at the standard best practice for deploying Rails apps to Heroku:

  1. heroku maintenance:on.
  2. git push heroku master. This restarts the application when complete. If you have any schema additions, your app is now broken (hence the need for maintenance mode).
  3. heroku run rake db:migrate.
  4. heroku restart. This is necessary so the app picks up on the schema changes.
  5. heroku maintenance:off.

That's five different commands, none of them instantaneous, and two restarts. The most common response to this mess is to wrap deployment up in a Rake task, but now you have two problems: a suboptimal deployment procedure, and application code concerned with deployment.

Now let's take a look at a typical deploy when COMPILE_TASKS includes db:migrate:

  1. git push heroku master.
    • First the standard stuff happens. Bundling, asset precompilation, that sort of thing.
    • rake db:migrate fires. The app continues working unless the migrations drop something from the schema.
    • The app restarts. Everything is wonderful.

We've reduced it to a single step, limiting our need for maintenance mode to destructive migrations. Even in that case, it's not always strictly necessary, since the window for breakage is frequently only a few seconds. Or with a bit of planning, you can avoid this situation entirely.

Twelve-factor snobs (of which I am one) would generally argue that admin processes belong in the run stage, not the build stage. I agree in theory, but it in practice, boy does this make things a whole lot simpler.

Commit recording

This takes the upcoming and previously deployed commit SHAs and makes them available as $REVISION and $ORIGINAL_REVISION for the duration of the compile. They are also written to HEAD and ORIG_HEAD in the root of the application for easy access after the deploy is complete.

These can be used from COMPILE_TASKS to make a poor man's post-deploy hook.