Heroku makes deploying Ruby web app a breeze, however it doesnāt run rake db:migrate
automatically each time you push a new commit to it.
You might have seen the error screen below after deploying your Rails app on Heroku:
I used to freak out when seeing this, but most of the time it is caused by me forgetting to run rake db:migrate
after deploying a feature which has new database migrations.
If you view logs of the app, and see thereās an error saying ārelation ātable_nameā does not existā , it means the database migration is not run hence no table is created.
Wouldnāt it be good if thereās a way to tell Heroku to automatically run ārake db:migrateā after each git push? š¤
Luckily Heroku has a feature named ārelease phaseā, it allow us to run tasks after a git push is received, but before the app is deployed.
From Heroku documentation :
Release phase enables you to run certain tasks before a new release of your app is deployed. Release phase can be useful for tasks such as:
- Sending CSS, JS, and other assets from your appās slug to a CDN or S3 bucket
- Priming or invalidating cache stores
- Running database schema migrations
We can specify the commands to run during release phase in the Procfile file, using the release
process type :
release: rake db:migrate
web: bundle exec puma -t 5:5 -p ${PORT:-3000} -e ${RACK_ENV:-development}
In the above Procfile , the ārake db:migrateā command will be run during release phase.
If you want to run multiple rake commands in the release phase, you can put them together like this :
release: rake db:migrate other:thing whatever
web: bundle exec puma -t 5:5 -p ${PORT:-3000} -e ${RACK_ENV:-development}
(thanks for the tip Jonathan!)
Alternatively, you can put the commands into a single bash file (eg: release-tasks.sh, located at the root of your repository), then execute the bash file in the release phase like this :
release: ./release-tasks.sh
web: bundle exec puma -t 5:5 -p ${PORT:-3000} -e ${RACK_ENV:-development}
With this, you wonāt need to run migration task manually after each git push, and this can make continuous deployment simpler.