Why manually deployment on Heroku dashboard didn't "rake db:migrate" automatically? - ruby-on-rails

I didn't use Heroku for a while. I found Heroku change something so want to give it another try.
But after I click the "Deploy Branch" button, my app is still not working.
So I check the build log and realize Heroku seems not do the db:migrate command.
But it did do the asset:compile command. And I don't found anywhere to click to do the db:migrate thing.
So I have to do it with command line tools, right?

This is a well known limitation of Heroku. It won't run your migrations out of the box. However, you can automate it in couple of ways:
You can write a simple script that will first push new code to Heroku git repository and then run migrations. The problem is that you need to run this script locally on your machine
You can add this buildpack and then set environmental variable DEPLOY_TASKS to db:migrate. You can do this via UI, command line heroku config:set DEPLOY_TASKS='db:migrate' or you can add everything to app.json so it should work out of the box with deploy button.
You can use release phase by adding release: rake db:migrate to your Procfile.
Please keep in mind that there are many issues related to migrating your database during deployment. You can read about it in the docs for release phase.

Related

Azure DevOps - Automatically run rails migrations

I created a Azure devops project that deploys my code from Github. My project is a Rails app that runs on Docker. When I create the Azure DevOps project, it creates the CI/CD pipelines for me. The deployment works, but I can't figure out how to automatically migrate the database when we deploy. I know I can do it manually, but I prefer not to as we might forget when we deploy.
I tried to run the following commands in the "Post Deployment Actions"
rake db:migrate
bundle exec rake db:migrate
rbenv exec bundle exec rake db:migrate
docker-compose run web rake db:migrate
I've also generated my own kuduscript (using kuduscript) to add in the line for migration but it did not work. I don't know if it's because it's not reading my deployment script or if that line doesn't work.
Am I missing something? Should I try to figure out how to migrate through Docker instead? I've looked at all these links but they all run the migration manually.
https://learn.microsoft.com/en-us/azure/app-service/containers/quickstart-ruby
https://medium.com/paris-rb/deploying-your-rails-postgresql-app-on-microsoft-azure-180f8a9fab47
https://learn.microsoft.com/en-us/azure/app-service/containers/tutorial-ruby-postgres-app
So not sure if you ever figured this out but I just had to do this for a migration I'm working on. The best way to do what you're after from what I've found is to setup a stage in your release pipeline like so:
stage setup
Where basically:
Your service connection logs into the container registry
Pulls the image you just built and pushed to the registry
Use a docker run command to then run your image with all the necessary environment variables and anything else needed to run it properly.
You can then use another task if needed to run a docker exec bundle exec rake db:migrate
If the migrate task runs successfully it should exit 0 allowing you to then run your app service on the latest tagged image with the correct database changes already done.

IntelliJ Idea/Rubymine push to Heroku running db:migrate

I'm using IntelliJ Idea with the Rubymine plugin, and Heroku plugin, and I'm a bit stumped when it comes to pushing an app to Heroku. I can set it up and actually push the app: off it goes, and launches successfully. But even before I did that I was expecting it to fail because I couldn't find anyway of getting it to do a db:migrate. And so it proved: the app is launched but of course it fails pretty much immediately because there's no DB.
I've looked on the forums, google etc but nothing. Is this something that can only be done from the command line? I would have expected an IDE to be what it says on the tin: Integrated. So I feel I'm missing something. The Run configuration works as I've said, and the Heroku log has no errors, but I need a way to tell it to run the db:migrate before launching.
Any ideas?
The answer is that it is something that it doesn't do - confirmed by IntelliJ. So in this case, one needs to push the app to Heroku, drop to the command line and run the migration there: heroku run rake db:migrate.
I raised a feature request so this may be something that can be added in the future.
I haven't figured out how to do this automatically as part of the RubyMine/JetBrains Heroku Plugin. But you can cobble this together from other sources.
Start with this gist that creates rake tasks for Heroku operations provided by this answer to a similar question:
Then create a new run configurations for each Rake task that you will be using at some point. You will need at minimum push and migrate. But the other tasks might interest you.
Then create a new compound run configuration calling the Rake tasks you created in step 2 in the correct order.
Step 2 and 3 can be consolidated by creating one rake task for migration, and adding a before rake task to push. But that's kind of counter intuitive.
Note: that this approach does require you to have the Heroku CLI installed and configured with valid credentials.

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.

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

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.

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