72

I am creating a workflow in GitHub which creates and uses a docker image. Therefore I have started my workflow file with a global environment variable for this docker image which is visible for all the jobs in my workflow:

name: continuous integration
on:
  push:
    branches:
      - '**'

env:
  IMAGE: docker.pkg.github.com/${{ github.repository }}/jactor-persistence:${{ github.sha }}

I want to replace ${{ github.sha }} with the short sha of the head commit, the same as the result of the following command git rev-parse --short HEAD

Is this possible?

Cœur
  • 37,241
  • 25
  • 195
  • 267
jactor-rises
  • 2,395
  • 2
  • 22
  • 44

5 Answers5

92

As VonC mentioned, you can just compute the string yourself in a previous step.

      - name: Set outputs
        id: vars
        run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
      - name: Check outputs
        run: echo ${{ steps.vars.outputs.sha_short }}
peterevans
  • 34,297
  • 7
  • 84
  • 83
  • 1
    Good addition to my answer. The problem is knowing that 7 is short enough, and not too short: https://stackoverflow.com/a/21015031/6309 – VonC Jan 20 '20 at 08:50
  • Does `git rev-parse --short` vary to make it unique? I can't quite tell from the documentation. – peterevans Jan 20 '20 at 09:06
  • 1
    Yet it does: that is what https://stackoverflow.com/a/21015031/6309 documents/illustrates. – VonC Jan 20 '20 at 09:42
  • Thanks. I've made that the answer instead of selecting the first 7 characters. – peterevans Jan 20 '20 at 09:47
  • 1
    Great answer, but this fails to work correctly when run on windows. Need to quote the echo string. `echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"` – MaxGhost Mar 21 '20 at 23:41
  • 1
    Thanks @MaxGhost. Updated the answer. – peterevans Mar 22 '20 at 00:52
  • 1
    Oh also - worth mentioning that the commit hash on HEAD during a PR will actually refer to a merge commit that is the result of merging the PR branch into the target branch. CI runs on that merge to ensure that the build wouldn't be broken even when taking into account possible merge conflicts. It's the right commit hash when CI is run on the mainline branch though. Usually not a problem, but it might be for you depending on the usecase. – MaxGhost Mar 22 '20 at 00:58
  • 7
    In addition to @MaxGhost's comment, if you want latest commit's hash of the branch instead of merge commit: `echo "::set-output name=sha_short::$(git rev-parse --short ${{ github.event.pull_request.head.sha }})"` – Yoon-Jae Jeong Aug 10 '21 at 03:48
  • BE CAREFUL! The HEAD will be changed when you merge a branch to other branches (like merge hotfix/ to both `main` and `develop`) branches. In my case: The `sha_short` was "9b2aaa1" The `GITHUB_SHA` was "715a576" The `github.sha` was "715a576" – CK.Nguyen Aug 24 '22 at 12:12
  • 2
    set-output is deprecated. use this instead: `echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT` – Coder1 Nov 02 '22 at 20:21
  • Also as @Coder1 mentioned, set-output will be [potentially] deprecated on 31st May 2023. You can also set new envvars like `echo "{name}={value}" >> $GITHUB_OUTPUT` to reference them as outputs. `echo "{name}={value}" >> $GITHUB_ENV` to reference them as env vars. – Enin Kaduk Dec 19 '22 at 15:23
  • `echo "SHORT=$(echo ${{ github.sha }} | cut -c1-7)" >> $GITHUB_OUTPUT` seems the cleanist. – rekarnar Apr 04 '23 at 07:53
  • Just in case I'm not misunderstanding things here. If I would like to get the latest short commit SHA from a Pull request within gh-actions would I use the example @Yoon-JaeJeong provided? – Andre_601 Apr 08 '23 at 00:04
41

You can also set an environment variable with the short sha:

    - name: Add SHORT_SHA env property with commit short sha
      run: echo "SHORT_SHA=`echo ${GITHUB_SHA} | cut -c1-8`" >> $GITHUB_ENV

SHORT_SHA can then be used like any other environment variable, e.g. like this:

    - name: My step
      run: myscript ${SHORT_SHA}
Lars Grammel
  • 1,999
  • 16
  • 21
  • 7
    I liked this approach, but used rev-parse instead `run: echo "SHORT_SHA=\`git rev-parse --short HEAD\`" >> $GITHUB_ENV` – Gilberto Treviño Sep 23 '21 at 13:18
  • 2
    I ended up using this approach because `git rev-parse --short HEAD` stopped working for me and was blank. I used `${{ github.sha }}` instead as well. – Chad Jun 13 '22 at 18:48
33

Found a possible solution here, using bash's parameter substitution

- name: Step
  run: echo ${GITHUB_SHA::7}
ushuz
  • 493
  • 5
  • 12
  • 1
    this is still something (it seems) that you need to run in a step somehow... even though it seems quite simple, it seems that it is not possible to do as a global variable... – jactor-rises Sep 08 '21 at 09:08
  • 1
    @jactor-rises what you are looking for is not possible at the moment, unless github adds short sha to variable/context, so currently, shortest is the best IMO – ushuz Sep 18 '21 at 02:08
5

This works on Windows:

- name: Get short SHA
  run: echo "SHORT_SHA=$("${{ github.sha }}".SubString(0, 8))" >> $env:GITHUB_ENV

- name: Print short SHA
  run: echo "Short SHA is ${{ env.SHORT_SHA }}"
PEK
  • 3,688
  • 2
  • 31
  • 49
3

It does not seem to be available: the github context only includes github.sha as the full commit sha (that triggered the workflow run)

You would need to somehow compute the string you want (by selecting only the first n characters of ${{ github.sha }}.

That means you can:

  • define a variable as shown in peterevans's answer
  • write it to the disk
  • cat $my_var to use your VAR in every step

See actions/starter-workflows issue 68 and examples.

But since Oct. 2019, you now have "Env at the workflow and job level"

It is common to need define a set of environment variables that are used in multiple steps in a job and even multiple jobs in a workflow.

Now you can add an env map at both the workflow and job level.
Those environment variables will be merged with the env defined at any step lower in the hierarchy.

See:

Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • yes... this is what I came to a conclusion myself. But is this possible to do in a expression in the global variable (in here somewhere`${{ github.sha }}`), to avoid to duplicate this all places which is in need of the variable – jactor-rises Jan 21 '20 at 08:11
  • @jactor-rises Sure sure about global, but peterevans's [answer](https://stackoverflow.com/a/59819441/6309) uses a variable. – VonC Jan 21 '20 at 08:17
  • .... I now that, but I would like to have a global env. variable to avoid duplicating code in my jobs... – jactor-rises Jan 21 '20 at 12:31
  • @jactor-rises That would be using an env map: see my edited answer above. – VonC Jan 21 '20 at 12:47
  • yes... and I am using workflow environment (`env` at the top of the workflow file) so it is available to all my jobs in the workflow. But at the workflow stage, is it possible to manipulate `${{ github.sha }}` to be the short sha, or do I have to duplicate this logic in my jobs? – jactor-rises Jan 22 '20 at 07:51