40

Is there any smart way to determine the default branch in GitHub actions?

Now I need to write something like:

on:
  push:
    branches:
      - master

is there a way to write something like the code below?

on:
  push:
    branches:
      - $default-branch

I tried to google but found nothing

friederbluemle
  • 33,549
  • 14
  • 108
  • 109
kharandziuk
  • 12,020
  • 17
  • 63
  • 121

9 Answers9

50

I accidentally found a really nice way to solve this. That evalutes to the branch name, e.g. master.

${{ github.event.repository.default_branch }}

Also, found out the hard way that that always() is side-effecting: my job was getting skipped if always() was not called even though the other clause was true.

This works to run a job only when running on default branch

  if: ${{ always() && format('refs/heads/{0}', ) == github.ref }}
antonmos
  • 796
  • 6
  • 9
  • This should be the accepted answer. No need for an additional step or other crazy workarounds. – Eydamos Aug 23 '21 at 13:12
  • Updating to this method in https://github.com/manubot/rootstock/pull/452. I just hope the github.event context contains this field for all potential event types. – Daniel Himmelstein Nov 30 '21 at 02:32
  • 12
    The `${{ github.event.repository.default_branch }}` expression can be used inside jobs, but not to define an event trigger under the `on:` statement as this question requests – ddelange Feb 01 '22 at 08:20
  • 1
    This seems not to work with schedule triggers. – felipecrs Apr 11 '22 at 20:25
  • FYI GitHub [fixed](https://github.com/community/community/discussions/12269#discussioncomment-3747667) the scheduled workflow context on 2022-07-27. You can see that `scheduled` jobs now contain the full `github.event.repository` context in [this dump actions context job](https://github.com/dhimmel/dump-actions-context/actions/runs/3283984929/jobs/5409384642#step:2:41). – Daniel Himmelstein Oct 21 '22 at 11:48
  • This approach worked for me without the `always()`. Just `if: github.ref == format('refs/heads/{0}', github.event.repository.default_branch)`. – Gus Nov 28 '22 at 10:26
30

$default-branch can be used in Workflow templates, but not in Workflows. The branch will become hard-coded in the Workflow upon initialization, and will have to be manually maintained. [1]

Blog post: https://github.blog/changelog/2020-07-22-github-actions-better-support-for-alternative-default-branch-names/

ddelange
  • 1,037
  • 10
  • 24
11
- if: github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
  run: echo "On the default branch"
- if: github.ref != format('refs/heads/{0}', github.event.repository.default_branch)
  run: echo "Not on the default branch"
friederbluemle
  • 33,549
  • 14
  • 108
  • 109
  • Oddly, I looked at the example docs to print out the context and it looks like this is found in github.event.repository.master_branch – Chris Knoll Jan 26 '22 at 18:22
  • @ChrisKnoll - Do you have a link to the build? That does sound odd indeed. – friederbluemle Jan 27 '22 at 02:16
  • Sorry for late reply, but I'm having trouble finding the reference in the doucmentation, however, to inspect what was in the payload object, I 'echoed' the contents of the github.event JSON and found the element in the object graph. – Chris Knoll Apr 19 '22 at 18:59
3

This is not possible at the moment. Please check this topic on github community

You simply can reach variable at this level

The workflow is not valid. .github/workflows/so-004-variables-in-trigger.yaml (Line: 7, Col: 9): Unrecognized named-value: 'env'. Located at position 1 within expression: env.default-branch

You may consider addition filterint based on the branch name like here but at the moment you can't do what you want.

Krzysztof Madej
  • 32,704
  • 10
  • 78
  • 107
3

You can use $default-branch in a template, and then when that template is rendered into a new repo, it will be replaced with the (then) default branch name for the repo, but that is a very limited use case and still does not help you when the name of the default branch changes. The best I have come up with is to list the all the default branch names in the organization, like this:

on:
  push:
    branches:
      - master
      - main
      - root
      - default
      - production

and then you can either trust that the repos will not have non-default branches with those names, or start the jobs and then filter them by adding an if condition like

if: github.event.push.ref == format('refs/heads/{}', github.event.repository.default_branch)

Side note

For most events

${{ github.event.repository.default_branch }}

is available and works fine, but not when running schedule events via cron. When github.event_name == "schedule" the only element in github.event is schedule (the cron string that triggered the run).

When running inside a GitHub action on at GitHub runner with gh available, this more reliably gets you the default branch name:

gh repo view --json defaultBranchRef --jq .defaultBranchRef.name

However, this does not help the OP when you want to make the default branch the target that triggers the run.

Old Pro
  • 24,624
  • 7
  • 58
  • 106
1

Add this step to your job:

    - name: Determine default branch
      run: |
        DEFAULT_BRANCH=$(git remote show origin | awk '/HEAD branch/ {print $NF}')
        echo "default_branch=$DEFAULT_BRANCH" >> $GITHUB_ENV
        echo "default_branch_ref=refs/heads/$DEFAULT_BRANCH" >> $GITHUB_ENV

That will add a default_branch and a default_branch_ref variable to the env enivronment variables. You can then access the default branch name with ${{ env.default_branch }} in subsequent steps. The default_branch_ref variable is useful for directly comparing against github.ref to determine whether you are on the default branch.

This method uses the current method of setting environment variables to use in later steps [1] and JoeLinux's method for determining the default branch name [2].

Full example workflow:

name: ci

on: [push, pull_request]

jobs:
  ci:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2

    - name: Determine default branch
      run: |
        DEFAULT_BRANCH=$(git remote show origin | awk '/HEAD branch/ {print $NF}')
        echo "default_branch=$DEFAULT_BRANCH" >> $GITHUB_ENV
        echo "default_branch_ref=refs/heads/$DEFAULT_BRANCH" >> $GITHUB_ENV

    - name: debug
      run: echo ${{ env.default_branch }}

    - name: Deploy
      if: github.ref == env.default_branch_ref
      run: echo "Run!"
scottclowe
  • 2,015
  • 19
  • 20
1

Even though this does not work in the specific code of the question, it does cover the title and main question written.

The easier thing you can do, is just specify an environment variable:

env:
  DEFAULT_BRANCH: refs/heads/${{ github.event.repository.default_branch }}
froblesmartin
  • 1,527
  • 18
  • 25
1

You can run jobs conditionally on the default branch:

jobs:
  job-one:
    if: github.ref_name == github.event.repository.default_branch
    ...

You can run steps conditionally on the default branch:

jobs:
  job-one:
    steps:
      - name: step one
        if: github.ref_name == github.event.repository.default_branch
        ...
0

Hopefully, there will be a better way to do this in the future. Until then, you can use the GitHub API and save the result in a named step output.

e.g.

    - name: Extract default branch name
      shell: bash
      run: |
        owner="my-org"
        repo="repo_x"
        branch=$(curl -L -H 'authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' \
            https://api.github.com/repos/${owner}/${repo} \
            | jq .default_branch)
        echo "##[set-output name=default_branch;]$(echo ${branch})"
      id: repo_x
...
${{ steps.repo_x.outputs.default_branch }}
soberg
  • 1