46

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?

Yarin
  • 173,523
  • 149
  • 402
  • 512
guyaloni
  • 4,972
  • 5
  • 52
  • 92
  • Possible duplicate of [Access current git commit number from within Heroku app](http://stackoverflow.com/questions/12217645/access-current-git-commit-number-from-within-heroku-app) – Roberto Tyley Oct 26 '15 at 12:47

9 Answers9

104

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
...
dentarg
  • 1,694
  • 2
  • 12
  • 20
  • 5
    this should be the top answer – Jeff Dickey Feb 24 '16 at 20:57
  • 1
    Thanks for introducing me to the awesome `heroku labs` command! – LeZuse Apr 21 '16 at 13:06
  • 3
    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. – nfm Oct 06 '16 at 00:26
  • @nfm 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." – dentarg Oct 06 '16 at 15:22
  • 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." – dentarg Oct 06 '16 at 15:23
  • Thanks, I've been looking for this! – Till Oct 10 '16 at 17:27
  • Ruby projects can use this gem for easy access (falls back to dummy values when `ENV` doesn't have these keys): https://github.com/dentarg/dyno_metadata – dentarg Jan 05 '17 at 10:29
  • 4
    Looks like those env variables are now available to other apps, when using Heroku Pipelines to promote a build. – Guillaume Boudreau Nov 19 '18 at 14:54
  • Labs aren't available for Review apps, unfortunately – Parzh from Ukraine Mar 26 '22 at 11:31
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.

culix
  • 10,188
  • 6
  • 36
  • 52
  • 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?? – guyaloni Feb 18 '13 at 23:32
  • @guyaloni 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](https://devcenter.heroku.com/articles/slug-compiler#compilation). I have revised my answer to use git hooks and/or shell scripts. What do you think? – culix Feb 19 '13 at 07:19
  • 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: @phoet – phoet Feb 22 '15 at 10:59
  • 1
    If your deploy fails, the version would be incorrectly set to the failed commit hash. – Tina Apr 26 '18 at 18:48
  • Heroku now has a `SOURCE_VERSION` environment variable ([docs](https://devcenter.heroku.com/articles/buildpack-api)) – Matt Sanders Jan 06 '21 at 19:41
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

srtech
  • 221
  • 2
  • 2
  • This will work nicely with a buildpack postcompile step (like npm postinstall, or python's bin/post_compile: [https://github.com/heroku/heroku-buildpack-python/issues/87#issuecomment-16244184] (note: this is untested) – Claude Sep 10 '15 at 21:48
  • Note that the buildpack reference above has been forked to make it compatible with latest buildpack API. You can find the updated buildpack [here](https://github.com/tempoautomation/heroku-buildpack-sourceversion). – Greg Sadetsky Jun 06 '17 at 14:42
9

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

Community
  • 1
  • 1
Tim Scott
  • 15,106
  • 9
  • 65
  • 79
  • 1
    Yes, except the OP wants to "display the hash of the current git commit in the browser." – denishaskin Jul 12 '13 at 20:00
  • 3
    Forget the OP, this is what I needed to know. – tadasajon Mar 16 '17 at 17:29
  • 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. – Flimm Mar 04 '22 at 08:10
  • To handle the rollback case, you probably need to parse the output of `heroku releases --json` – Flimm Mar 04 '22 at 08:19
7

There is an env var on Heroku containers called SOURCE_VERSION

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

You can use that!

TVG
  • 259
  • 3
  • 8
  • 1
    Sometimes the newest answer hiding at the bottom is the best answer – CTS_AE Apr 24 '20 at 12:08
  • 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? – kiril Aug 13 '21 at 13:19
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
joshwa
  • 1,660
  • 3
  • 17
  • 26
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
Md. Farhan Memon
  • 6,055
  • 2
  • 11
  • 36
groovecoder
  • 1,551
  • 1
  • 17
  • 27
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\"}"
Beau
  • 11,267
  • 8
  • 44
  • 37
  • 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 :) – AxelTheGerman Apr 08 '20 at 04:36
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.

Roberto Tyley
  • 24,513
  • 11
  • 72
  • 101