Heroku - Display hash of current commit in browser
Asked Answered
B

9

47

I want to display the hash of the current git commit in the browser so that testing team (which does not have an access to run heruko commands) will be able to include the corresponding commit hash in bug reports.

First I tried grit, but something is broken and it doesn't work on Heroku (on local it works great, I don't know why it fails on Heroku).

So I found out that there are two environment variables on Heroku:

ENV["COMMIT_HASH"]
ENV["LAST_COMMIT_BY"]

But neither of them is available (both are nil).

I also checked with:

heroku config

But again, neither is set.

Is there a way to retrieve the hash information? Is there any way to have more git information, such as date for example?

Bellhop answered 29/1, 2013 at 12:47 Comment(1)
Possible duplicate of Access current git commit number from within Heroku appCosenza
S
25

Firstly, since heroku "remove[s] unused files, including the .git directory" during slug compilation, you won't be able to execute some git commands from inside your app's directory (on the heroku dyno). This includes things like git rev-parse HEAD, which is normally an easy way to get the current hash.

Secondly, trying to retrieve information with git ls-remote on the heroku dyno will invoke ssh, and you'll see messages that say The authenticity of host 'heroku.com (50.19.85.132)' can't be established, since the heroku public key is not installed on heroku dynos. You won't have permission to install the heroku public key.

You still have at least two options.

  1. Add a post-commit hook to update the hash value.

    a) Create or edit the file .git/hooks/post-commit
    b) Add some shell script code like this:

    hash_name=HEAD_HASH
    hash=$(git rev-parse HEAD)
    echo Setting $hash_name to $hash
    heroku config:set $hash_name=$hash --app yourappname

    (you can use whatever code you want for git hooks; this is just one option)

    Explanation:

    • HEAD_HASH is the name of the heroku environment variable. Call it whatever you want. You'll look this up in your main app and display it on the page.
    • git rev-parse HEAD grabs the hash of the current HEAD commit. Customize this line for whatever you want to display.


    Now when you make commits to git the HEAD_HASH env var will be updated each time. This works, but might be a bit slow, as you'll be waiting for heroku to set the env var each time you commit. If your network connection is out etc. the variable won't be updated. Rumour is that git 1.8.2 will allow a 'pre-push' hook where you could put this code instead.

  2. Use a script to push your code

    Instead of typing git push heroku master to push your code, you could write a shell script that contains the lines from option 1. and adds git push heroku master at the end. Then to deploy your code you run this shell script. This will update the HEAD_HASH only before pushing (instead of after each git commit), and it nicely keeps everything in one place. You'll probably want to add the script to your .slugignore file too.

Squirmy answered 17/2, 2013 at 19:9 Comment(5)
hmmm... I do heroku run git rev-parse HEAD and get fatal: Not a git repository (or any of the parent directories): .git - what is wrong??Bellhop
@Bellhop It looks like you can't execute some git commands on the dyno itself, since part of heroku's compilation process deletes the .git depo. I have revised my answer to use git hooks and/or shell scripts. What do you think?Squirmy
I'm building an heroku addon to provide this funtionality. If you are interested in testing the alpha, please get in contact with me on twitter: @BeauteousBeauteous
If your deploy fails, the version would be incorrectly set to the failed commit hash.Beggs
Heroku now has a SOURCE_VERSION environment variable (docs)Kailakaile
W
105

It's now possible to try the Heroku feature Roberto wrote about in his answer, without contacting Heroku. It's called Heroku Labs: Dyno Metadata and you can enable it by

heroku labs:enable runtime-dyno-metadata -a <app name>

and then the information is available (on the next deploy) as environment variables:

~ $ env
HEROKU_APP_ID:                   9daa2797-e49b-4624-932f-ec3f9688e3da
HEROKU_APP_NAME:                 example-app
HEROKU_DYNO_ID:                  1vac4117-c29f-4312-521e-ba4d8638c1ac
HEROKU_RELEASE_VERSION:          v42
HEROKU_SLUG_COMMIT:              2c3a0b24069af49b3de35b8e8c26765c1dba9ff0
HEROKU_SLUG_DESCRIPTION:         Deploy 2c3a0b2
...
Wont answered 30/12, 2015 at 19:58 Comment(9)
this should be the top answerBellda
Thanks for introducing me to the awesome heroku labs command!Oidea
Unfortunately, this doesn't seem to work if you're using Heroku Pipelines. The HEROKU_SLUG_COMMIT only seems to be initialized/updated when you do a git-push based deploy.Laodicean
@Laodicean True, I actually asked Heroku about it 1 month ago, here's their reply: "I'm afraid that since dyno metadata is currently a labs feature there is no way fold child apps to inherit the variables. However there is one exception, HEROKU_APP_NAME has a little workaround. If you add it to the env object (leave the value blank) we will automatically populate it with the correct parent app name."Wont
The reply from Heroku ended with: "Sorry that I don't have better news for you on this. It's something that's requested regularly though so I know it's on the mind of the teams that works on these products. Give that a shot and let us know if you have any other questions."Wont
Thanks, I've been looking for this!Imide
Ruby projects can use this gem for easy access (falls back to dummy values when ENV doesn't have these keys): github.com/dentarg/dyno_metadataWont
Looks like those env variables are now available to other apps, when using Heroku Pipelines to promote a build.Admiralty
Labs aren't available for Review apps, unfortunatelyDeandreadeane
S
25

Firstly, since heroku "remove[s] unused files, including the .git directory" during slug compilation, you won't be able to execute some git commands from inside your app's directory (on the heroku dyno). This includes things like git rev-parse HEAD, which is normally an easy way to get the current hash.

Secondly, trying to retrieve information with git ls-remote on the heroku dyno will invoke ssh, and you'll see messages that say The authenticity of host 'heroku.com (50.19.85.132)' can't be established, since the heroku public key is not installed on heroku dynos. You won't have permission to install the heroku public key.

You still have at least two options.

  1. Add a post-commit hook to update the hash value.

    a) Create or edit the file .git/hooks/post-commit
    b) Add some shell script code like this:

    hash_name=HEAD_HASH
    hash=$(git rev-parse HEAD)
    echo Setting $hash_name to $hash
    heroku config:set $hash_name=$hash --app yourappname

    (you can use whatever code you want for git hooks; this is just one option)

    Explanation:

    • HEAD_HASH is the name of the heroku environment variable. Call it whatever you want. You'll look this up in your main app and display it on the page.
    • git rev-parse HEAD grabs the hash of the current HEAD commit. Customize this line for whatever you want to display.


    Now when you make commits to git the HEAD_HASH env var will be updated each time. This works, but might be a bit slow, as you'll be waiting for heroku to set the env var each time you commit. If your network connection is out etc. the variable won't be updated. Rumour is that git 1.8.2 will allow a 'pre-push' hook where you could put this code instead.

  2. Use a script to push your code

    Instead of typing git push heroku master to push your code, you could write a shell script that contains the lines from option 1. and adds git push heroku master at the end. Then to deploy your code you run this shell script. This will update the HEAD_HASH only before pushing (instead of after each git commit), and it nicely keeps everything in one place. You'll probably want to add the script to your .slugignore file too.

Squirmy answered 17/2, 2013 at 19:9 Comment(5)
hmmm... I do heroku run git rev-parse HEAD and get fatal: Not a git repository (or any of the parent directories): .git - what is wrong??Bellhop
@Bellhop It looks like you can't execute some git commands on the dyno itself, since part of heroku's compilation process deletes the .git depo. I have revised my answer to use git hooks and/or shell scripts. What do you think?Squirmy
I'm building an heroku addon to provide this funtionality. If you are interested in testing the alpha, please get in contact with me on twitter: @BeauteousBeauteous
If your deploy fails, the version would be incorrectly set to the failed commit hash.Beggs
Heroku now has a SOURCE_VERSION environment variable (docs)Kailakaile
W
22

As of 2015-04-01, the Git SHA is now available within the build process as the environment variable SOURCE_VERSION. See: https://devcenter.heroku.com/changelog-items/630

Note that it is not available to the running app, only during the compile step. You could add a custom buildpack to write this to a file that persists in the slug, and then read the file from your application.

I'm testing that approach and have an experimental buildpack here: https://github.com/sreid/heroku-buildpack-sourceversion

Worcester answered 3/4, 2015 at 4:0 Comment(2)
This will work nicely with a buildpack postcompile step (like npm postinstall, or python's bin/post_compile: [github.com/heroku/heroku-buildpack-python/issues/… (note: this is untested)Cyrie
Note that the buildpack reference above has been forked to make it compatible with latest buildpack API. You can find the updated buildpack here.Lazes
M
9

git ls-remote heroku works for me. I got this from an answer to a duplicate question here.

Motorway answered 12/7, 2013 at 14:13 Comment(4)
Yes, except the OP wants to "display the hash of the current git commit in the browser."Hendrick
Forget the OP, this is what I needed to know.Tatting
This actually breaks if rollback. After running heroku releases:rollback v42, the output of git ls-remote heroku remains the same even though that is not the current commit in production on Heroku.Fleet
To handle the rollback case, you probably need to parse the output of heroku releases --jsonFleet
K
7

There is an env var on Heroku containers called SOURCE_VERSION

https://devcenter.heroku.com/articles/buildpack-api

You can use that!

Kelvin answered 6/3, 2019 at 19:29 Comment(2)
Sometimes the newest answer hiding at the bottom is the best answer 👍Llama
This is only available in build-time, right. Although it is a useul answer, it won't be possible to use it to show commit in the browser, tight?Rodomontade
T
6

Git >1.8.2 now supports a pre-push hook, which is a better match for our usecase. Here's my current hook script:

#!/bin/sh

remote="$1"
url="$2"

if [[ $url =~ heroku ]] ; then

    if [[ $url =~ staging ]] ; then
        appname=YOUR_APP_NAME_STAGING
    else
        appname=YOUR_APP_NAME
    fi

    hash_name=COMMIT_HASH
    hash=$(git rev-parse HEAD)
    echo Setting $hash_name to $hash
    heroku config:set $hash_name=$hash --app $appname
fi
exit 0
Tetrarch answered 28/3, 2014 at 1:2 Comment(0)
G
3

Both culix and joshwa have great answers. If you name your heroku git remotes the same as your corresponding heroku apps you can have an even shorter and more robust .git/hooks/pre-push hook:

#!/bin/bash

remote="$1"
url="$2"

if [[ $url =~ heroku ]] ; then
    hash_name=COMMIT_HASH
    hash=$(git rev-parse HEAD)
    echo Setting $hash_name to $hash on app $remote
    heroku config:set $hash_name=$hash --app $remote
fi

exit 0
Gimel answered 15/7, 2014 at 4:30 Comment(0)
L
3

It's also possible to use the Heroku API directly if you're using CI and don't have access to the Heroku client there.

This is the solution I used on codeship.com (which provides the hash in the environment as $CI_COMMIT_ID:

# you can use `heroku auth:token` to generate this
HEROKU_API_KEY="" 

APP_NAME="glorious-flying-birds"

curl -n -X PATCH "https://api.heroku.com/apps/$APP_NAME/config-vars" \
  -H "Authorization: Bearer $HEROKU_API_KEY" \
  -H "Accept: application/vnd.heroku+json; version=3" \
  -H "Content-Type: application/json" \
  -d "{\"GIT_COMMIT_HASH\": \"$CI_COMMIT_ID\"}"
Landloper answered 20/3, 2015 at 22:34 Comment(1)
this is super helpful for any small tweaks you want to do to your app from CI. much appreciate pointing out tools that are (almost) always available - curl :)Wellesley
C
3

Heroku has new functionality to support dyno metadata, if you email support you can probably get added to the beta. Here's a place where Heroku themselves are using it:

https://github.com/heroku/fix/blob/6c8ab7a/lib/heroku_dyno_metadata.rb

The additional functionality writes out a JSON file to /etc/heroku/dyno - the contents look like this:

{
   "dyno":{
      "physical_id":"161bfad9-9e83-40b7-b385-78305db2f168",
      "size":1,
      "name":"run.7145"
   },
   "app":{
      "id":null
   },
   "release":{
      "id":50,
      "commit":"2c3a0b24069af49b3de35b8e8c26765c1dba9ff0",
      "description":null
   }
}

..so release.commit is the field you're after.

Cosenza answered 21/10, 2015 at 12:38 Comment(1)
No such file for me. heroku-18 stack. /etc/heroku is empty.Folkmoot

© 2022 - 2024 — McMap. All rights reserved.