Ruby-on-rails Rails 3 和 Heroku:推送时自动“rake db:migrate”?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5966290/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 01:06:22  来源:igfitidea点击:

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

ruby-on-railsgitheroku

提问by Max Williams

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

我对我的 heroku 推送/部署过程有点不满,否则发现和使用它是一种乐趣。

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.

如果我向我的应用程序添加一个新的迁移,我可以将它放到 heroku 服务器上的唯一方法是推送到 heroku 远程。这将上传它并重新启动应用程序。但它不运行迁移,所以我必须这样做heroku rake db:migrate --app myapp,然后heroku restart --app myapp。与此同时,该应用程序已损坏,因为它没有运行迁移,并且代码在迁移中引用了字段/表等。

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

必须有一种方法可以更改部署过程,使其rake db:migrate作为部署过程的一部分自动运行,但我无法解决。

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 cpanel中设置的吗?这是我从命令行传递给 heroku 的一个选项吗?它是一个 git 钩子吗?谁能让我直截了当?谢谢,最大

采纳答案by Paul A Jungwirth

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

这是一个 rake 任务,它将所有内容打包成一个单行(并且还支持回滚):

https://gist.github.com/362873

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 pushand the rake db:migrate.

您仍然可能会在老板的演示之上进行部署,但至少您不会浪费时间git pushrake db:migrate.

回答by Max Woolf

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

Heroku 现在能够将其作为其“发布阶段”功能的一部分来处理。

You can add a process called releaseto your Procfileand that will be run during each and every deploy.

您可以添加一个调用release到您的进程,该进程Procfile将在每次部署期间运行。

Rails >= 5 Example

Rails >= 5 示例

release: bundle exec rails db:migrate

release: bundle exec rails db:migrate

Rails < 5 example

Rails < 5 示例

release: bundle exec rake db:migrate

release: bundle exec rake db:migrate

回答by Cristian

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.

一旦第一个成功完成,它将自动运行迁移。通常延迟 1-2 秒或更短。

回答by Dan Tao

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

我创建了一个自定义 buildpack,它可以让 Herokurake db:migrate在部署时自动为您运行。它只是 Heroku 的默认 Ruby buildpack 的一个分支,但rake db:migrate添加了任务。

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-compileHeroku Labs feature. Here's how you do that:

另请注意,为了使其工作,您需要启用user-env-compileHeroku Labs 功能。这是你如何做到的:

heroku labs:enable user-env-compile

And here's my evidence that this works:

这是我证明这有效的证据:

rake db:migrate on Heroku deployment

rake db:migrate 在 Heroku 部署中

回答by David Sulc

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
  1. 将架构更改推送到 Heroku
  2. 迁移
  3. 将应用程序代码推送到 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)

(当然,最简单的解决方案是在你的老板出去吃午饭时简单地推送和迁移;-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.

否则,即使模式修改是自动执行的,您仍然会面临在运行迁移之前请求通过的风险。

回答by Kari

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.

我正在使用 Rails 4,需要向 Heroku 的部署添加一个简单的 Rake 任务。当我在 github 中使用“部署到 heroku”按钮时,没有机会在部署后立即运行“heroku run ...”。

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:

我所做的:我在部署期间自动运行的标准 Rake 任务“assets:clean”扩展到 heroku。该任务仍然正常运行,但我已将自己的东西附加到它的末尾。这是通过“增强”方法完成的。在下面的示例中,我添加了 db:migrate ,因为这可能是大多数人想要的:

# 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.

我承认这不是完美的解决方案。但是 heroku Ruby Buildpack 仍然不支持任何其他方式。对于这么简单的事情,编写我自己的 buildback 似乎有点矫枉过正。

回答by Aditya Sanghi

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

我使用 rake 任务将应用程序置于维护模式、推送、迁移并将其移出维护模式。

回答by hammady

I wrote SmartMigrate buildpackwhich 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.

我编写了SmartMigrate buildpack,它是一个简单的 Heroku buildpack,用于在检测到新迁移时在 ruby​​ 构建后警告挂起的迁移。此 buildpack 旨在成为具有前面 Ruby buildpack 的 Multipack 的一部分。

With due respect to other solutions here, this buildpack has 3 advantages over those:

考虑到此处的其他解决方案,此 buildpack 具有 3 个优势:

  1. No need for maintenance mode
  2. No need for out-dated ruby buildpack forks that just insert the migration at the end
  3. No need to run migrations ALL THE TIME, a warning is only displayed if new migrations are detected since the last deployment
  1. 无需维护模式
  2. 不需要过时的 ruby​​ buildpack 分支,只需在最后插入迁移
  3. 无需一直运行迁移,只有在自上次部署后检测到新迁移时才会显示警告

回答by sheltond

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.

我认为 David Sulc 的方法是唯一一种可以确保在应用程序处于损坏状态时避免请求通过的方法。

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.

但是,在代码的其余部分之前推送迁移和架构更改可能很困难,因为显而易见的方法 ('git push heroku {revnum}') 依赖于您在代码的其余部分之前检查迁移。

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.

  • 根据您最近推送到 heroku 的 git 修订版创建一个分支:

    git branch <branchname> <revnum-or-tag>
    
  • 看看那个分支:

    git checkout <branchname>
    
  • 如果您的数据库迁移提交仅包含迁移,而没有代码更改,请挑选包含数据库更改的提交:

    git cherry-pick <revnum1> <revnum2>...
    
  • 如果您在还包含代码更改的修订中提交了数据库更改,则可以使用不会自动提交的“git cherry-pick -n”;使用“git reset HEAD”从将要提交的一组内容中删除不是数据库更改的文件。一旦您获得了 db 更改,请将它们提交到您的临时分支中。

    git cherry-pick -n <revnum1> <revnum2>...
    git reset HEAD <everything that's modified except db/>
    git status
    ... check that everything looks ok ...
    git commit
    
  • 将此临时分支推送到 heroku(理想情况下,推送到暂存应用程序以检查您是否做对了,因为避免停机是跳过这些障碍的重点)

    git push heroku <branchname>:master
    
  • 运行迁移

    heroku run rake db:migrate
    
  • 在这一点上,您可能认为您可以将“master”推送到 heroku 以获取代码更改。但是,您不能,因为它不是快进合并。继续的方法是将 'master' 的其余部分合并到您的临时分支中,然后将其合并回 master,这将重新组合两个分支的提交历史:

    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>
    
  • 现在您可以像往常一样将 master 推送到 heroku,这将使您的其余代码更改。

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.

在倒数第二个步骤中,我不是 100% 确定是否需要将 master 合并到 {branchname}。这样做应该确保完成“快进”合并,当您推送到 heroku 时,这会让 git 保持快乐,但是通过将 {branchname} 合并到 master 而没有这一步,可能会获得相同的结果。

Of course, if you aren't using 'master', substitute the appropriate branch name in the relevant places above.

当然,如果您不使用“master”,请在上面的相关位置替换相应的分支名称。

回答by slothbear

I've been using the heroku_sangem 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.

我使用heroku_sangem 作为我的部署工具已经有一段时间了。这是一个很好的小型、专注于推送 + 迁移的工具。它添加了一些其他 rake 命令,使访问其他功能(如控制台)变得容易。除了不必记住数据库迁移之外,我最喜欢的功能是它的 Heroku 配置文件——所以我可以随意命名我的所有服务器(生产、暂存、playground4、shirley)——并让它们在我的脑海中清晰可见。