136
votes

I'm building docker images with Github Actions and want to tags images with branch name, I found only GITHUB_REF variable, but it results in refs/heads/feature-branch-1 and I need only feature-branch-1.

17
Use this action: github.com/EthanSK/git-branch-name-action it works for both pull_request and push triggerEthan SK
IMHO stackoverflow.com/a/64210623/680454 should be the accepted answer; it deals with @ambientlight's objection to the currently accepted answer, it avoids use of now-deprecated setenv, and it doesn't use any external includes.michielbdejong
I opened up a Feature Request with GitHub to add native support for this. Many other CI providers (Travis CI, CircleCI, Semaphore CI) have native support, so there's good precedence for adding something like this. Please upvote the feature request if you'd like to see this behavior added!blimmer

17 Answers

164
votes

I added a separate step for extracting branch name from $GITHUB_REF and set it to the step output

- name: Extract branch name
  shell: bash
  run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})"
  id: extract_branch

after that, I can use it in the next steps with

- name: Push to ECR
  id: ecr
  uses: jwalton/gh-ecr-push@master
  with:
    access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
    secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
    region: us-west-2
    image: eng:${{ steps.extract_branch.outputs.branch }}
114
votes

I believe GITHUB_REF is the only environment variable that includes the branch name.

You can extract just the branch name from the rest of that string like this:

${GITHUB_REF##*/}

Example:

$ GITHUB_REF=refs/heads/feature-branch-1
$ echo ${GITHUB_REF##*/}
feature-branch-1

Update: Added a complete workflow example.

Workflow

name: CI
on: push
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Git checkout
        uses: actions/checkout@v1
      - name: Branch name
        run: echo running on branch ${GITHUB_REF##*/}
      - name: Build
        run: docker build -t tedmiston/tag-example:${GITHUB_REF##*/} .

Source: https://github.com/tedmiston/x/blob/master/.github/workflows/workflow.yml

Sample output - master branch

Run docker build -t tedmiston/tag-example:${GITHUB_REF##*/} .
  docker build -t tedmiston/tag-example:${GITHUB_REF##*/} .
  shell: /bin/bash -e {0}
Sending build context to Docker daemon  146.9kB

Step 1/1 : FROM alpine
latest: Pulling from library/alpine
9d48c3bd43c5: Pulling fs layer
9d48c3bd43c5: Verifying Checksum
9d48c3bd43c5: Download complete
9d48c3bd43c5: Pull complete
Digest: sha256:72c42ed48c3a2db31b7dafe17d275b634664a708d901ec9fd57b1529280f01fb
Status: Downloaded newer image for alpine:latest
 ---> 961769676411
Successfully built 961769676411
Successfully tagged tedmiston/tag-example:master

Log: https://github.com/tedmiston/x/commit/cdcc58a908e41d3d90c39ab3bf6fef1ad2c4238a/checks#step:4:16

Sample output - non-master branch

Run docker build -t tedmiston/tag-example:${GITHUB_REF##*/} .
  docker build -t tedmiston/tag-example:${GITHUB_REF##*/} .
  shell: /bin/bash -e {0}
Sending build context to Docker daemon  144.9kB

Step 1/1 : FROM alpine
latest: Pulling from library/alpine
9d48c3bd43c5: Pulling fs layer
9d48c3bd43c5: Verifying Checksum
9d48c3bd43c5: Download complete
9d48c3bd43c5: Pull complete
Digest: sha256:72c42ed48c3a2db31b7dafe17d275b634664a708d901ec9fd57b1529280f01fb
Status: Downloaded newer image for alpine:latest
 ---> 961769676411
Successfully built 961769676411
Successfully tagged tedmiston/tag-example:branch-name-test

Log: https://github.com/tedmiston/x/commit/4e8d31259f861aaa2c30375756fc081c3659bddf/checks#step:4:16


See this answer for more on parameter expansion syntax.

For reference the page Virtual environments for GitHub Actions lists all of the environment variables available in the execution environment.

80
votes

Be aware that if you are executing your GitHub action on pull request trigger, then GITHUB_REF variable will contain something like refs/pull/421/merge so if you will try to git push to that name it will most likely fail.

What you can use though are references on the GitHub context in your YAML. Something like: ${{ github.head_ref }}

https://help.github.com/en/actions/automating-your-workflow-with-github-actions/contexts-and-expression-syntax-for-github-actions#github-context

Github action context refs

27
votes

You could use https://github.com/rlespinasse/github-slug-action

# Just add this  => 
- name: Inject slug/short variables
  uses: rlespinasse/[email protected]



# And you get this  => 
- name: Print slug/short variables
  run: |
    echo "Slug variables"
    echo " - ${{ env.GITHUB_REF_SLUG }}"    
    echo " - ${{ env.GITHUB_HEAD_REF_SLUG }}"
    echo " - ${{ env.GITHUB_BASE_REF_SLUG }}"
    echo " - ${{ env.GITHUB_REPOSITORY_SLUG }}"
    # output e.g. : master feat-new-feature v1.0.0 product-1.0.0-rc.2 new-awesome-product
    echo "Slug URL variables"
    echo " - ${{ env.GITHUB_REF_SLUG_URL }}"
    echo " - ${{ env.GITHUB_HEAD_REF_SLUG_URL }}"
    echo " - ${{ env.GITHUB_BASE_REF_SLUG_URL }}"
    echo " - ${{ env.GITHUB_REPOSITORY_SLUG_URL }}"
    # output e.g. : master feat-new-feature v1-0-0 product-1-0-0-rc-2 new-awesome-product
    echo "Short SHA variables"
    echo " - ${{ env.GITHUB_SHA_SHORT }}"
    # output e.g. : ffac537e
23
votes

Using setenv is now deprecated. It is advised to use environment files. Building on @youjin's answer, while still allowing feature/ branches (replacing all occurences of / with -), I am now using this:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Get branch name (merge)
        if: github.event_name != 'pull_request'
        shell: bash
        run: echo "BRANCH_NAME=$(echo ${GITHUB_REF#refs/heads/} | tr / -)" >> $GITHUB_ENV

      - name: Get branch name (pull request)
        if: github.event_name == 'pull_request'
        shell: bash
        run: echo "BRANCH_NAME=$(echo ${GITHUB_HEAD_REF} | tr / -)" >> $GITHUB_ENV

      - name: Debug
        run: echo ${{ env.BRANCH_NAME }}
11
votes

to set it as an en variable, I use this syntax:

- name: Extract branch name
  shell: bash
  run: echo "::set-env name=BRANCH_NAME::$(echo ${GITHUB_REF#refs/heads/} | sed 's/\//_/g')"
- name: Test
  run: echo "${BRANCH_NAME}"

I found this syntax here: Github actions - starter worflows#How to define env variable? #68

Rmq: the sed 's/\//_/g' is to replace / by _ in the branch name

10
votes

I just made a simple test within GitHub Actions using a bash script:

#!/bin/bash

echo Reserved for REPO_NAME=${GITHUB_REPOSITORY##*/}
echo GITHUB_REF=${GITHUB_REF}
echo EXTRACT_GITHUB_REF=${GITHUB_REF##*/}
echo EXTRACT_GITHUB_REF_HEADS=$(echo ${GITHUB_REF#refs/heads/})

cd $REPO_NAME
git checkout ${GITHUB_REF##*/}
git checkout $(echo ${GITHUB_REF#refs/heads/})

Here is screenshot of the output:

enter image description here So both ${GITHUB_REF##*/} and $(echo ${GITHUB_REF#refs/heads/}) are correct

10
votes

How to get the current branch within Github Actions?

Assuming ${{ github.ref }} is something like refs/heads/mybranch, you can extract the branch name using the following method:

steps:
  - name: Prints the current branch name
    run: echo "${GITHUB_BRANCH##*/}"
    env:
      GITHUB_BRANCH: ${{ github.ref }}

If your branch includes slashes (such as feature/foo), use the following syntax:

steps:
  - name: Prints the current branch name
    run: echo "${GITHUB_REF#refs/heads/}"

Credits: @rmunn comment

Or use the method from the accepted answer, here is much shorter version (lint friendly):

steps:
  - name: Get the current branch name
    shell: bash
    run: echo "::set-output name=branch::${GITHUB_REF#refs/heads/}"
    id: myref

Then refer in other steps as ${{ steps.myref.outputs.branch }}.

Notes:

10
votes

The GitHub Action FranzDiebold/github-env-vars-action exposes several useful environment variables, such as current branch name and their slug values. I made this action exactly for this use case.

Usage

steps:
  - uses: FranzDiebold/[email protected]
  - name: Print environment variables
    run: |
      echo "GITHUB_REPOSITORY_SLUG=$GITHUB_REPOSITORY_SLUG"
      echo "GITHUB_REPOSITORY_OWNER=$GITHUB_REPOSITORY_OWNER"
      echo "GITHUB_REPOSITORY_OWNER_SLUG=$GITHUB_REPOSITORY_OWNER_SLUG"
      echo "GITHUB_REPOSITORY_NAME=$GITHUB_REPOSITORY_NAME"
      echo "GITHUB_REPOSITORY_NAME_SLUG=$GITHUB_REPOSITORY_NAME_SLUG"
      echo "GITHUB_REF_SLUG=$GITHUB_REF_SLUG"
      echo "GITHUB_REF_NAME=$GITHUB_REF_NAME"
      echo "GITHUB_REF_NAME_SLUG=$GITHUB_REF_NAME_SLUG"
      echo "GITHUB_SHA_SHORT=$GITHUB_SHA_SHORT"

enter image description here

A demo for all Operating systems (Linux, macOS and Windows) is also available in the demo workflows file of the repository!

7
votes

Heres a complete workflow that works for both push and pull_request events

name: whichBranch
on: [pull_request, push]

jobs:
  which_branch:
    runs-on: ubuntu-latest
    steps:
      # extract branch name
      - name: Extract branch name
        if: github.event_name != 'pull_request'
        shell: bash
        run: echo "::set-env name=BRANCH_NAME::$(echo ${GITHUB_REF#refs/heads/})"
        id: extract_branch

      # extract branch name on pull request
      - name: Print branch name
        if: github.event_name == 'pull_request'
        run: echo "::set-env name=BRANCH_NAME::$(echo ${GITHUB_HEAD_REF})"

      # print branch name
      - name: Get branch name
        run: echo 'The branch name is' $BRANCH_NAME
1
votes
if: github.ref == 'refs/heads/integration' && github.event_name == 'push' 

You can use the above command and replace whatever branch or event you want to run for.

1
votes

Use branch name on GitHub actions

Convenience action for using current branch name. Usage

name: build
on: push

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1
    - run: npm ci
    - uses: nelonoel/branch-name@v1
    # Use branch name for whatever purpose
    - run: echo ${BRANCH_NAME}
1
votes

For people using Windows image to run actions, a few key points to know about:

  1. It's incorrect to assume that GitHub actions use CMD shell. They use PowerShell by default.
  2. You can specify the shell to use the following way:
- run: |
    ...
  shell: cmd
  1. You can use the value 'bash' to execute a command in the context of a bash shell.

So, all in all, you don't need to waste potentially hours trying to figure out how to do things in dilapidated cmd way (like I did).

And for the simple purpose of getting the name of the current branch, you can either use the popular solutions while setting the shell to 'bash', or use for example the following simple way to set a variable in the default PowerShell shell:

$branchName = $Env:GITHUB_REF -replace "refs/heads/", ""
1
votes

I made an action that gets the branch name regardless of pull_request trigger or not. https://github.com/EthanSK/git-branch-name-action

0
votes

Running on Windows?. Windows default command is a PowerShell terminal.

  - name: SET CURRENT_BRANCH
    run: |
      $branchName = "${{github.ref}}".Split("/")["${{github.ref}}".Split("/").Length -1]
      echo "::set-env name=CURRENT_BRANCH::$(echo $branchName)"
0
votes

If you're using V2 of actions/checkout then you can always just run git branch --show-current to just get the name of the branch currently checked out.

0
votes

Here's a snippet which set's an environment variable based on $GITHUB_REF, which defaults to dev if not present.

Adjust the sed command as per your requirements.

export GIT_BRANCH=$(echo ${GITHUB_REF:-dev} | sed s/.*\\///g)