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

Posted

技术标签:

【中文标题】Rails 3 和 Heroku:推送时自动“rake db:migrate”?【英文标题】:Rails 3 and Heroku: automatically "rake db:migrate" on push? 【发布时间】:2011-08-23 09:41:27 【问题描述】:

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

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

必须有一种方法可以更改部署过程以在部署过程中自动运行rake db:migrate,但我无法解决。

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

【问题讨论】:

直到现在我才使用heroku restart,几个月后使用它;D @PeterWong 你当时在做“push-migrate-push”吗?或者更聪明的东西?实际上我认为这甚至行不通,因为第二次推送将拒绝进行,因为没有任何变化。 我只是“推送迁移”。只是不需要重新启动。 ***.com/questions/2560845/… 的副本 @PeterWong - 我以为我试过了,但迁移中动态生成的字段不在应用程序中,因此导致错误。也许是我想象的…… 【参考方案1】:

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

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

Rails >= 5 示例

release: bundle exec rails db:migrate

Rails

release: bundle exec rake db:migrate

【讨论】:

给了 +1。我不得不把它改成rake db:migrate 是的,Rails 5 将rake 全局替换为rails 二进制文件。我会更新我的答案。 为此干杯。尚未迁移到 Rails 5。 docs: devcenter.heroku.com/articles/release-phase 注意发布阶段处于 Beta 阶段,命令在创建新版本时运行(即 1. 应用程序构建 2. 管道提升 3. 配置变量更改 4.回滚 5. 通过平台 API 发布)【参考方案2】:

这个简单的命令链解决方案怎么样:

git push heroku master && heroku run rake db:migrate

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

【讨论】:

如果迁移失败,这会让你有点混乱。 如果迁移失败,回滚上一个版本。否则,请重启应用以使用新的架构更改。 如果您在 git remotes 中引用了多个应用程序,请不要忘记添加 -a appname【参考方案3】:

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

https://gist.github.com/362873

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

【讨论】:

我更喜欢提到的要点的面向对象版本:gist.github.com/jfeaver/9820478 这很棒,它看起来.. 几乎和我用的一模一样。 =) 我认为这个要点现在可能有点过时了 - 代码似乎来自 heroku 早期的时候,在推送后需要更多的手动干预【参考方案4】:

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

要将它与您的应用程序一起使用,您可以这样做:

heroku config:set BUILDPACK_URL=https://github.com/dtao/rake-db-migrate-buildpack

另请注意,为了使其正常工作,您需要启用 user-env-compile Heroku Labs 功能。这样做的方法如下:

heroku labs:enable user-env-compile

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

【讨论】:

是的。设置工作需要 10 秒,这正是我想要的。至少就我的目的而言,比这里的其他答案要好得多。谢谢。 我的建议是分叉项目并使用分叉作为部署过程。因为在这里您信任 Github 存储库来部署您的生产代码。 好点。但是,这个 repo 无论如何都不再起作用了,因为它所依赖的 user-env-compile 已被删除。 :(【参考方案5】:

也许您可以尝试将架构提交(迁移等)提交与代码提交(模型、验证等)分开。

(请注意,以下假设您的迁移更改没有破坏性,因为您已经指出涵盖了您的大部分用例。)

您的部署过程可能是:

    将架构更改推送到 Heroku 迁移 将应用程序代码推送到 Heroku

这当然远非最佳,但在您描述的情况下是避免停机的有效方法:当应用收到动态字段的代码时,数据库已经迁移。

(当然,最简单的解决方案是在老板外出吃午饭时简单地推送和迁移;-D)

否则,即使架构修改是自动进行的,您仍然会冒在迁移运行之前请求通过的风险。

【讨论】:

【参考方案6】:

对于像我这样使用谷歌搜索的人,我想在这里给出一个简单的解决方案。

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

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

# in lib/tasks/assets_clean_enhance.rake
Rake::Task['assets:clean'].enhance do
  Rake::Task['db:migrate'].invoke
end

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

【讨论】:

不要这样做,在 Heroku 上,您的数据库连接可能在部署过程中的特定时间点还没有准备好。【参考方案7】:

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

【讨论】:

恐怕这并不令人满意:我希望能够随时部署,而不必担心我的老板是否正在向客户演示站点或其他什么(此时出现维护页面将意味着一个非常愤怒的老板)。感谢您的回答:) 你真的想在你的短线老板演示的时候进行部署吗?我不确定heroku是否提供此功能!目前最好的办法是在此期间无需人工等待。 我不想,但这是不可避免的 :) 在我的非 Heroku 应用程序中,只要迁移是非破坏性的就可以了,它几乎总是如此(即它们通常要添加新字段或新表,而不是删除任何东西)。因此,您有一个过渡时期,旧代码使用新模式运行,这通常很好(因为模式只包含添加),然后在迁移完成后滚动重启 mongrels/unicorns happpen,它几乎没有如果有任何明显的停机时间/减速。 在 Paul(下)发布了一个实际的 rake 任务后,我最终采用了您的解决方案。猜猜我只是懒得写自己的。谢谢:)【参考方案8】:

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

考虑到这里的其他解决方案,这个 buildpack 有 3 个优势:

    无需维护模式 无需在最后插入迁移的过时的 ruby​​ buildpack 分叉 无需一直运行迁移,仅当自上次部署以来检测到新迁移时才会显示警告

【讨论】:

【参考方案9】:

我认为 David Sulc 的方法是唯一能确保在应用程序处于故障状态时避免请求通过的方法。

这有点痛苦,但在某些情况下可能是必要的。

正如他所说,它确实要求数据库迁移是非破坏性的。

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

如果您还没有这样做,仍然可以使用临时分支来执行此操作:

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

git branch <branchname> <revnum-or-tag>

查看那个分支:

git checkout <branchname>

如果您的数据库迁移提交仅包含迁移,并且没有代码更改,请挑选包含数据库更改的提交:

git cherry-pick <revnum1> <revnum2>...

如果您在包含代码更改的修订版中提交了数据库更改,则可以使用不会自动提交的“git cherry-pick -n”;使用 'git reset HEAD' 从将要提交的内容集中删除不是 db 更改的文件。一旦你得到了 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,这将使您的其余代码更改完成。

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

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

【讨论】:

您可以强制推送到 heroku,这样您就可以跳过所有这些合并,并在运行迁移后强制推送主服务器。【参考方案10】:

一段时间以来,我一直使用heroku_san gem 作为我的部署工具。它是一个不错的小而专注的推送+迁移工具。它添加了一些其他 rake 命令,使访问其他功能(如控制台)变得容易。除了不必记住数据库迁移之外,我最喜欢的功能是它的 Heroku 配置文件——所以我可以随意命名我所有的服务器(生产、登台、playground4、shirley)——并将它们牢记在心。

【讨论】:

heroku_san 有一段时间没有更新了,但我在 Rails 4.2 项目上使用它没有问题。

以上是关于Rails 3 和 Heroku:推送时自动“rake db:migrate”?的主要内容,如果未能解决你的问题,请参考以下文章

在代理后面的heroku上推送rails应用程序时出现问题

Heroku 推送错误:“无法检测到 rake 任务”(Rails 6.1)

向初学者解释 Heroku 推送之前的 Rails 预编译?

Rails 5.2 和 webpacker 3.4.3:部署到 Heroku 时资产未编译

我无法上传到 Heroku RUBY ON RAILS

Heroku 推送被拒绝,未检测到 Cedar 支持的应用程序