Heroku控制台显示来自Git部署的最新SHA哈希。

8
我有一个开发分支托管在Heroku上,我们有一些人使用此分支查找错误,因此最好显示部署在Heroku上的最新提交的SHA-1哈希,以便我们知道哪些错误属于哪个提交。
但我根本找不到任何方法来获取这些信息。在Heroku运行控制台中没有环境变量。尽管"heroku releases"会显示部署信息列表,包括SHA-1哈希的前几个字符,这让我想Heroku一定在某个地方存储它,但我就是找不到。有人知道吗?
我意识到我没有清楚地提出问题:我的意思是在Heroku上的Rails中找到SHA-1哈希。就像我可以做这样的事情:
<h1><%= ENV['REV']</h1>

谢谢您!


我必须问一下为什么?你说“我们有几个人使用这个分支来查找错误”,我不是在恶意挑衅,但我想知道为什么你不会在dev中分支错误,上传它让其他人查看,然后在“批准”或者你们需要他们查看Heroku上的特定分支时合并。 - pjammer
完全没有问题,我不认为这是恶意挑衅——也许我的方法并不是最优的思考方式,但如果他们只在本地机器上测试应用程序,我就无法放心地想到它会在Heroku上以完全相同的方式工作。 - Nik So
但这就是暂存环境的作用,对吧?你们有多少人在代码里胡闹呢?我的意思是,如果出现了一个 bug,一个人从主分支创建一个新分支,修复它,更新暂存环境。你批准它。然后将其合并到主分支并推送到生产环境。这样你就可以好好休息了。 - pjammer
两个人,他们不在代码中搞破坏,只进行表面测试。 - Nik So
可以Heroku应用程序的运行时知道其提交ID吗? - Roberto Tyley
3个回答

11

将 Heroku 视为任何其他远程 Git 存储库 - 您可以使用 git ls-remote:

git ls-remote heroku

(这里的 heroku 是远程名称)

更新:

由于原帖实际上是要在 Ruby 环境中获取 SHA,一种可能的方法是使用自定义 Buildpack

要开始,前往Heroku 的 Ruby Buildpack并 fork 它以便您可以制作自己的变体。现在克隆您的 fork 并查看lib/language_pack/ruby.rb。添加一个新方法,例如:

def get_SHA
    #get SHA
    #save SHA to ENV, ala: ENV['SHA'] = retrieved_sha
end

如何获取SHA就取决于你了。你可以执行一个git命令并使用返回的结果:

git log -1 --format="%H"

或者你可以使用@avaynshtok的建议,使用Heroku gem使用releases方法。

然后,一旦你有了SHA,将其设置为ENV变量。

接下来,在ruby.rb中找到compile方法,并在其末尾添加get_sha方法:

def compile
    Dir.chdir(build_path)
    install_ruby
    setup_language_pack_environment
    allow_git do
        install_language_pack_gems
        build_bundler
        create_database_yml
        install_binaries
        run_assets_precompile_rake_task
        get_sha #your additional method
    end
end

将更改推送回 GitHub,然后前往命令行。您需要为 Heroku 应用程序添加一个新的配置变量:

heroku config:add BUILDPACK_URL=git@github.com:<your GitHub username>/heroku-buildpack-ruby.git

请注意,您需要确保已将<your GitHub username>替换为您自己的 GitHub 用户名,以便指向您分叉的存储库。

最后,执行一个启用 Heroku 实验功能 的命令,该功能允许 slug 编译器访问用户变量:

heroku labs:enable user_env_compile

现在,您应该已经准备好了。那么现在会发生什么呢?当您推送到 Heroku 时,Heroku 将接收更改,然后看到您设置了自定义构建包 url。因此,它将从 GitHub 获取您的自定义构建包,然后使用它来创建 slug 。这意味着一旦它运行完所有默认编译命令,它将以您的 get_sha 方法结束,该方法应将 ENV 变量 SHA 设置为适当的 SHA。现在,您应该可以从 Ruby 中访问该 ENV 变量,并根据需要使用它。


我明白了。太糟糕了,我真的希望他们在某个地方存储了SHA。我的意思是,它是从“heroku releases”命令中检索到的,这表明他们在某个地方有它... - Nik So
是的,但您正在尝试从运行在隔离 slug 中的 Ruby 服务器内部访问该信息,而不是从 repo 中访问。因此,除非 Heroku 手动将该信息传递给服务器本身(我怀疑),否则它不会存在。不过,您可以通过使用自定义构建包并在 slug 编译期间设置 ENV 变量来自己完成。如果您愿意,我可以更新我的答案并提供更多详细信息。 - redhotvengeance
更新了。我的更新中还包含了指向构建包文档等链接。如果您有任何问题,请告诉我。 - redhotvengeance
1
另外,@avaynstok提到了部署钩子 - 这也可以有创意地利用。您可以在应用程序中设置一个简单的Web API路由来接收POST,然后在应用程序上启用部署钩子:heroku addons:add deployhooks:http url=http://yourapp.com/deployhookroute。当该路由接收到POST时,它可以将该信息设置为整个应用程序可用。唯一的缺点是,恶意人员可能会欺骗信息,因此如果需要锁定和安全,这可能不是最佳选择。如果您愿意,我也可以更新我的答案。 - redhotvengeance
运行 git ls-remote heroku 并不能总是给出生产实例正在运行的提交。在回滚后会出现问题。在运行 heroku releases:rollback v42 后,git ls-remote heroku 的输出与回滚之前相同,尽管这不是 Heroku 上当前生产环境中的提交。 - Flimm
显示剩余7条评论

3

您可以使用Heroku gem来获取发布信息:https://github.com/heroku/heroku

c = Heroku::Client.new <LOGIN>, <PASSWORD>
c.releases(<APPNAME>).last['commit']

或者,您可以使用您的API密钥进行身份验证:

c = Heroku::Client.new '', <API_KEY>

缺点是你需要在某个地方存储登录/密码组合(或API密钥)(可以在应用程序或Heroku环境中存储)。您还可以使用部署挂钩来获取此信息:https://devcenter.heroku.com/articles/deploy-hooks

钩子和客户端看起来都很有前途,我选择使用Buildpack,因为它似乎比我之前想象的要简单得多,并且似乎具有ENV变量可以避免每次想查看SHA时都调用Heroku客户端(我打算像邮戳一样放在每个页面上)。虽然部署钩子将通过将其存储在某个数据库表中而消除此问题。所以如果Buildpack不起作用,我可能不得不采取这种方法。谢谢Avaynshtok。 - Nik So

1
我最终使用Heroku平台API宝石来完成这个。这是一个有点冗长的宝石,但是它被记忆化了,所以每次部署只需要执行一次,可以避免使用自定义构建包(麻烦)和部署挂钩(不安全)的麻烦。
def current_sha
  @current_sha ||= begin
    heroku = PlatformAPI.connect_oauth(ENV['HEROKU_TOKEN'])
    slug_id = heroku.release.list(ENV['HEROKU_APP']).last["slug"]["id"]
    heroku.slug.info(ENV['HEROKU_APP'], slug_id)["commit"]
  end
end

确实是个好建议。我发现Heroku的HTTP部署钩子有时会出现问题。 - Nik So
这不给我正确的提交。它返回一个短sha,但我不确定它是什么,并且在重复调用时不会更新。“last”方法在发布列表中定义在哪里? - justingordon
问题是,只有在您的git提交少于200次时才有效!https://discussion.heroku.com/t/can-a-custom-buildpack-put-the-current-git-commit-sha-into-apps-env/932。超过200次后,每次都会得到相同的发布版本!必须有一种更有效地请求最新发布版本的方法。 - justingordon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接