Conditionally Run GitHub Actions Based on PR Labels

1 min read#dev#github

Sometimes you want a GitHub Actions job to run only in specific cases. For example, you deploy a Node.js app on every push to main, but on pull requests you only want to deploy when the PR has a deploy label.

The simple way

A job’s if: condition can read the github context, which includes the labels of the pull request. So you can write the condition directly on the job:

name: Node.js CI

on:
  push:
    branches: [main]
  pull_request:
    types: [labeled, opened, synchronize, reopened]

jobs:
  release:
    name: Create GitHub Release
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'deploy')
    steps:
      - run: echo 'deploy'

Reusing the condition across jobs

If several jobs need the same condition, you might want to define it once as a workflow-level env variable. Unfortunately, this does not work: the env context is not available in a job’s if:.

The workaround is a small job that turns the value into an output. Other jobs can then read it with needs.<job>.outputs.<name>:

env:
  SHOULD_RELEASE: ${{ github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'deploy') }}

jobs:
  prepare:
    runs-on: ubuntu-latest
    outputs:
      should_release: ${{ env.SHOULD_RELEASE }}
    steps:
      - run: echo "SHOULD_RELEASE=${{ env.SHOULD_RELEASE }}"

  release:
    name: Create GitHub Release
    runs-on: ubuntu-latest
    needs: [prepare]
    if: needs.prepare.outputs.should_release == 'true'
    steps:
      - run: echo 'deploy'

Outputs are always strings, so compare with 'true', not true.

For one or two jobs, I would keep the condition on the job itself. The extra job adds a few seconds to every run and one more thing to read.


Thoughts? Reply via emailSuggest an edit


NewerEfficient API Polling in Redux RTK Query with EtagCacherOlderMerging Coverage from Jest and Cypress