【问题标题】:Heroku + Github deployment strategiesHeroku + Github 部署策略
【发布时间】:2012-06-25 22:00:15
【问题描述】:

我正在开发一个网络应用程序,在 Github 上托管源代码并在 Heroku 上运行该应用程序。一切正常,但我有一个问题我无法解决。在部署我的代码之前,我会运行一些脚本来优化代码(缩小、连接文件等)。 heroku 应用仅使用应用的优化版本。

基本上,我有两个文件夹:devproductionDev 包含我编写的源代码,production 由我的构建脚本生成(我使用 grunt 和 requirejs)。目前,这两个文件夹都在我的 Git 存储库中,并且都被推送到 Github 和 Heroku。我宁愿在 Github 上只有 dev,在 Heroku 上只有 production。 我读了一些文章如何为 Heroku 设置不同的分支,如described in this blog。我可以设置一个生产分支,并且只有production 文件夹在其中,同时将dev 文件夹保留在我的主分支中吗?还是我需要单独的存储库?

有人试过类似的吗?我认为这不是什么不寻常的事情。

【问题讨论】:

    标签: git node.js deployment heroku


    【解决方案1】:

    您可能只想考虑使用 heroku .slugignore 文件(参考 https://devcenter.heroku.com/articles/slug-compiler)。

    此文件允许您从 heroku 部署到每个服务器实例的包中删除 dev 文件夹,同时允许您将所有代码保存在同一个存储库中。

    问题的根源在于将部署策略视为您将最终位上传到服务器的策略,其中 这些位是构建存储库的人工制品。在这种情况下,构建通常与源分开存储和归档。

    Heroku 的模型与此稍有不同,因为它假设 您的存储库是要部署的工件。差别很小,但在您的情况下,这只是意味着您需要将您希望 heroku 服务的位提交到您的存储库。

    另一种思考方式是,您可以不使用 production 文件夹,作为启动服务器的一部分,将运行脚本以生成 production 文件夹文件。这将允许您删除 production 文件夹,并以在每次启动服务器时运行此过程为代价保持您的存储库清洁。这可能被证明是非常昂贵且不可取的(Heroku 在放弃服务器之前等待服务器启动的时间是有限的),但希望有助于澄清 Heroku 和 git 的关系。

    【讨论】:

    • 这就是我现在正在做的......我创建了自己的自定义 buildpack(请参阅github.com/mbuchetics/heroku-buildpack-nodejs-grunt),它使用 Grunt 在每次部署时构建生产文件夹。它工作得很好,我可以将所有生产的东西排除在 git repo 之外。
    • 我在标准 buildpack 中使用的另一个功能是通过 NPM 支持的。您可以将"postinstall" 脚本添加到您的package.json 并以这种方式运行任意代码。 npmjs.org/doc/scripts.html
    【解决方案2】:

    这种情况有点不寻常。但这里有一些想法:

    • 我使用的流程与您引用的文章中的流程类似。
    • 如您所说,我只会创建一个应用程序。我会在您的 dev 文件夹中创建一个新的 git 存储库。
    • 然后,我会推荐一种类似于此答案中描述的部署策略:https://*.com/a/8058194/267025。我在下面进行了改编:

    创建一个rake 文件,其中包含两个任务:rake deploy:productionrake deploy:postprocess_files。这些任务可能看起来像这样:

    namespace :deploy do
    
      task :production do
        puts "turn on 'maintenance page' on heroku"
        system "heroku maintenance:on"
    
        puts "deploying to production"
        system "git push heroku-prod master"
    
        puts "post processing files..."
        system "heroku run rake production:postprocess_files"
    
        puts "take off maintenance page"
        system "heroku maintenance:off"
    
        puts "done"
      end 
    
      task :postprocess_files do
        puts "run postprocessing of files on heroku"
        ... add commands here to post process the files.
      end 
    end
    

    然后使用rake deploy:production 部署到生产环境,而不是直接使用 git 推送。 rake 文件将:

    1. 设置维护页面,
    2. 投入生产,
    3. 对文件进行后期处理,
    4. 删除维护页面。

    请注意,文件中的第二个 rake 任务具有对文件进行后处理的命令,并被第一个 rake 任务调用以在 heroku 上运行。

    作为替代方案,您可以扩展 Heroku 作为每次部署的一部分运行的 assets:precompile 任务。无论如何,这基本上就是您正在做的事情 - 准备资产以部署到生产环境。

    【讨论】:

    • 我认为这行不通。在有关一次性进程 (devcenter.heroku.com/articles/oneoff-admin-ps) 的文档中,它说“每个 dyno 都有自己的临时文件系统,不与任何其他 dyno 共享,一旦断开连接就会被丢弃。”。这适用于数据库脚本等,但不适用于修改文件系统的东西。还是我错过了什么?还有,为什么我的情况不正常?
    • 我相信你可能是对的——另外,我在写完这篇文章后意识到你正在部署 node.js 代码而不是 rails 代码。
    • 我对您的情况异常的评论是基于我假设您正在部署 Rails 代码。我对 heroku 上的 node.js 不太熟悉,所以情况可能并非如此。
    【解决方案3】:

    这有点令人困惑,因为:

    使用分支很好,仅用于隔离代码变体(在所述分支中),而不用于存储发布生成的代码。
    您的特定发布管理问题(即生成正确的交付)应由脚本(可以与您的代码一起进行版本控制)管理,并用作挂钩,例如,生成和部署正确的代码集正确的地方。

    【讨论】:

    • 'dev' 不包含生成的内容,这是我在那里写的源代码。 'production' 是相同的,但具有优化的文件。我知道分支的区别。我遇到的问题是 Heroku 部署基于 Git 存储库。我只能部署存储库中的内容。我无法区分推送到 Github 的内容和推送到 Heroku 的内容(如果不使用分支)。
    • @slurmomatic 在这种情况下,Kevin 的回答(我赞成)应该比我的(更一般的)回答更适合 Heroku 发布管理过程。
    【解决方案4】:

    【讨论】:

    • 不错!这实际上是我自己的项目。真的很高兴其他人发现它和我一样有用。