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

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

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

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.

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.

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:

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:
Push schema changes to Heroku
migrate
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.

Just for those googling folks like me I want to give a plain solution here.
I am using Rails 4 and needed to add a simple Rake task to the deployment to heroku. As I am using the 'deploy to heroku' button in github there is no chance to run "heroku run ..." immediately after deployment.
What I did: I extended the standard Rake Task 'assets:clean' that is automatically run during a deployment to heroku. The task still runs normally but I have attached my own stuff to it's end. This is done with the 'enhance' method. In the example below I add a db:migrate because this is probably what most people want:
# in lib/tasks/assets_clean_enhance.rake
Rake::Task['assets:clean'].enhance do
Rake::Task['db:migrate'].invoke
end
I admit that this is no perfect solution. But the heroku Ruby Buildpack still does not support any other way. And writing my own buildback seemed a bit of an overkill for so simple a thing.

I use a rake task to put the app in maintenance mode, push, migrate and move it off maintenance mode.

I wrote SmartMigrate buildpack which is a simple Heroku buildpack to warn of pending migrations after a ruby build whenever new migrations detected. This buildpack is intended to be part of a Multipack that has a preceding Ruby buildpack.
With due respect to other solutions here, this buildpack has 3 advantages over those:
No need for maintenance mode
No need for out-dated ruby buildpack forks that just insert the migration at the end
No need to run migrations ALL THE TIME, a warning is only displayed if new migrations are detected since the last deployment

I think David Sulc's approach is the only one which ensures that you avoid requests getting through while the app is in a broken state.
It is a bit of a pain, but may be necessary in some circumstances.
As he stated, it does require that the db migrations are non-destructive.
However, it can be difficult to push your migrations and schema changes prior to the rest of the code, as the obvious approach ('git push heroku {revnum}') relies on you having checked the migrations in before the rest of the code.
If you haven't done that, it's still possible to do this using a temporary branch:
Create a branch, based at the git revision that you most recently pushed to heroku:
git branch <branchname> <revnum-or-tag>
Check out that branch:
git checkout <branchname>
If your db migration commits only contained migrations, and no code changes, cherry-pick the commits that contain the database changes:
git cherry-pick <revnum1> <revnum2>...
If you commited your db changes in revisions which also contained code changes, you can use 'git cherry-pick -n' which won't automatically commit; use 'git reset HEAD ' to remove the files that aren't db changes from the set of things that are going to be commited. Once you've got just the db changes, commit them in your temporary branch.
git cherry-pick -n <revnum1> <revnum2>...
git reset HEAD <everything that's modified except db/>
git status
... check that everything looks ok ...
git commit
Push this temporary branch to heroku (ideally to a staging app to check that you've got it right, since avoiding downtime is the whole point of jumping through these hoops)
git push heroku <branchname>:master
Run the migrations
heroku run rake db:migrate
At this point, you might think that you could just push 'master' to heroku to get the code changes across. However, you can't, as it isn't a fast-forward merge. The way to proceed is to merge the remainder of 'master' into your temporary branch, then merge it back to master, which recombines the commit histories of the two branches:
git checkout <branchname>
git merge master
git diff <branchname> master
... shouldn't show any differences, but just check to be careful ...
git checkout master
git merge <branchname>
Now you can push master to heroku as normal, which will get the rest of your code changes across.
In the second-to-last step, I'm not 100% sure whether merging master to {branchname} is necessary. Doing it that way should ensure that a 'fast-forward' merge is done, which keeps git happy when you push to heroku, but it might be possible to get the same result by just merging {branchname} to master without that step.
Of course, if you aren't using 'master', substitute the appropriate branch name in the relevant places above.

I've been using the heroku_san gem as my deployment tool for a while. It is a nice small, focused tool for the push + migration. It adds some other rake commands that make accessing other functions (like console) easy. Beyond not having to remember database migrations, my favorite feature is its Heroku configuration file – so I can name all my servers (production, staging, playground4, shirley) whatever I want – and keep them straight in my head.

Related

Generate a rails migration directly on Heroku

I have some sort of snafu that happened where an intern accidentally uploaded a bit of code to our staging site and then cancelled. Now, there is a page on the staging site that requires a migration that doesn't exist on the staging site.
I'm relatively new to this as well and I'm wondering what the best way to add a migration for that missing column directly to the staging site. Is it
Pull the code, add the migration, push the code (which changes the
staging from the dev, as the dev has the master.
Generate the migration in some other way in heroku directly?
I honestly don't even know if the way we think this error happened is actually the truth. I just have to fix it.
If your migration existed you can rollback on directly on heroku in activity onglet.
or
Pull your repo
Add your migration
Push it on heroku
Run heroku run rake db:migrate --app your_staging_app

heroku app not being properly updated?

I'm new to the web development scene, so sorry if my lack of knowledge bugs you
When i run my local code using rails s and testing on my own server, the front end is not the same as the local one.
My first attempt was to initially fix some snippet of code, then use git push, then git push heroku master.
I've tried deleting the app and pushing fresh new code again, and it still doesn't work
I've tried heroku restart, and no changes also
Any suggestions?
edit
pictures for clarity
top is local, bottom is heroku server
Further to #RSB's comment, you'll probably find that your CSS is not being compiled properly
To fix this, you'll have to perform a precompile when you deploy. However, Heroku already does this, so probably won't be an issue
The best thing to do is eliminate any potential issues -
#config/environments/production.rb - config.serve_static_assets = true
local - rake assets:precompile RAILS_ENV=production
git add .
git commit -a -m "CSS Test"
git push heroku master
Try running this command in your project folder
heroku run rake assets:precompile

rails app in development doesn't show up on heroku

Im developing a rails app. Following this tutorial here:
Tutorial
I finished a part and wanted to push all the changes up to heroku and view them there. I can view the site on my local machine. On heroku all I see is this:
I typed in the following commands after I made my changes, saw the site was working on my local computer.
$ git add .
$ git commit -m "Finish layout and routes"
$ git checkout master
$ git push
$ git push heroku
$ heroku open
I even looked at the heroku logs but couldn't make sense of whats going wrong! There is no content in my database, its empty. I just have views setup.
Why did you checkout to master? Are you working on another branch?
If that is the case, you will need to merge your changes to master before pushing your code (supposing you are on master which is already the case after the checkout):
git merge other-branch
Also don't forget to migrate your database on heroku.
heroku rake db:migrate
EDIT
To find out your current branch, type:
git branch
It will mark the current branch with a '*'.
If you have removed the public/index.html file, you'll have to do git rm public/index.html as well, then commit and push to Heroku. If you delete a file locally, git won't pick up on that without doing the git rm, and Heroku's knowledge of your app is 100% through Git.
I had a similarly strange (but unrelated) problem when I had an app that was storing uploaded files on Heroku. Every time I'd do a push they'd all go away. It confused me greatly until I realized that Heroku essentially wipes every time you do a push, and anything that isn't in git isn't kept. A good reason to use S3 or similar for uploaded file storage.

Rails 3: HEROKU staging and production repo managment

I've setup my app to run on Heroku with a staging and production environment as according to their documents. http://devcenter.heroku.com/articles/multiple-environments
It seems pretty straightforward to manage with the staging app, push entire deployments or new branches up to test in staging. What I wonder is how to manage the production version.
How do I keep my production up and running when deploying new code? Do I pull in the changes from staging or do I redeploy the entire app with the changes merged in?
Secondly, how do I manage and keep my database intact during all of this? I'm used to running locally where if you do a new deploy and a new rake :db:migrate, you lose all your database data. How is this done in production to not lose your records?
Thanks you and ANY other tips regarding heroku management is welcome.
Typically, you make changes locally, including migrations or whatever. Before pushing your changes to your production app, push changes to your staging app to double-check things are okay.
If you added migrations in your changes, be sure to run heroku run rake db:migrate to migrate your staging database. Running rake db:migrate should not destroy any data so long as your migration is proper - i.e. no weird tampering with data, just the standard addition/renaming/etc. of columns or introducing new tables. (Obviously if you drop a table in a migration it'll be gone.)
Then, if everything is okay with your staging app, push changes to your production, and again run heroku run rake db:migrate if you had any new migrations. If things are not okay, run heroku help to get a list of commands you can use - particularly ones with regard to releases so you can revert back to a previous release. Also heroku logs is really useful, and heroku console (actual command might be slightly different), though when you start a console, be really careful not to tamper with data too much.
With Heroku, there's no deploy command needed - right when you git push, your updated code is there. No "cap deploy" with capistrano, if you've used that before.
Hope this helps.

Capistrano deploy but manually run migrations

I'm using Capistrano to deploy a Rails application. I'm thinking of a situation where there were database changes, so I can't simply cap deploy because the migrations need to run before the code is updated. I realize there's a cap deploy:migrations, but that's a little more automatic than I'd like. I'd like to:
Push the new code to the releases directory, but not update the symlink or restart the application.
ssh into the server, run rake:db_abort_if_pending_migrations to confirm that the migrations I want to run are the only pending ones, then run rake db:migrate manually.
Complete the deploy, updating the symlink and restarting the application.
Is there any easy way to do this with the built-in Capistrano tasks, or would I need to write my own deployment steps to accomplish this?
I should mention too that I'm thinking of cases (like adding columns) where the migration can be run on a live database. For more destructive changes I realize I'd need to bring down the site with a maintenance page during the deploy.
Try:
cap deploy:update_code
Do what you described loging in to the server manually or via cap
shell
cap deploy:symlink deploy:restart
See cap -e deploy:update_code deploy:symlink deploy:restart deploy:shell for more information.
I hope this will be helpful to You.

Resources