How to cancel existing runs when a new push happens on GitHub Actions, but only for PRs?

Viewed 1415

Based on the documentation (there's also a SO answer), I wrote this:

on:
  push
concurrency:
  # Documentation suggests ${{ github.head_ref }}, but that's only available on pull_request/pull_request_target triggers.
  group: ci-${{ github.ref }}
  cancel-in-progress: true
jobs:
  ...

This creates a separate group for each branch, and cancels builds if there's a later push/force push to a branch. Sadly, this also cancels master builds, which I don't want. On master all commits should complete running, so it's easy to see when something broke.

I'm essentially looking for a way to say:

concurrency:
  group: ci-${{ github.ref }}
  cancel-in-progress: true
  if: github.ref != 'refs/heads/master'
2 Answers

You can specify cancel-in-progress based on the default branch:

concurrency:
  group: ${{ github.ref }}
  cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}

There's no ternary operator in GitHub Actions expression syntax, but I found some workarounds: http://rickluna.com/wp/tag/fake-ternary/ is an awesome post about this.

The commit hash of the head branch is available in the github context object as github.sha.

In my case truthyness in fake ternary is not an issue, it actually always has to have a value, so I can do:

concurrency:
  # Documentation suggests ${{ github.head_ref }}, but that's only available on pull_request/pull_request_target triggers, so using ${{ github.ref }}.
  # On master, we want all builds to complete even if merging happens faster to make it easier to discover at which point something broke.
  group: ${{ github.ref == 'refs/heads/master' && format('ci-master-{0}', github.sha) || format('ci-{0}', github.ref) }}
Related