79

I'm developing a Github actions workflow. This workflow runs on Linux, Mac, and Windows.

As part of the workflow, I have to check whether 2 environment variables are equal. If they don't - fail the job.

As described here, Github Actions support if: condition:

steps:
- run: # How can I make a cross-platform failure here?
  if: ${{ envA }} != ${{ envB }}

How can I make the job fail if the above condition is true? In the beginning, I thought of a script, but there must be a more elegant way to fail a job.

yahavi
  • 5,149
  • 4
  • 23
  • 39

3 Answers3

96

I'd do run: exit 1. That will simply exit with an exit code of 1, on all three platforms.

Proof that it's cross-platform: https://github.com/rmunn/Testing/runs/220188838 which runs the following workflow:

name: Test exiting on failure

on: [push]

jobs:
  build:

    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest, macOS-latest]
    runs-on: ${{ matrix.os }}
    
    steps:
    - uses: actions/checkout@v1
    - name: Try to fail
      run: exit 1
    - name: Print message if we don't fail
      run: echo Should not get here

(An earlier version of this answer recommended "/bin/false", but that would only work on Linux and macOS).

Timo Tijhof
  • 10,032
  • 6
  • 34
  • 48
rmunn
  • 34,942
  • 10
  • 74
  • 105
  • 11
    Is there any way to do this without causing the job to fail? i.e. to exit the job given a condition but with success? – simon Feb 01 '20 at 18:33
  • 6
    For anyone wondering, "exit 0" will end the step early without canceling the job. –  Sep 03 '20 at 18:30
  • 3
    I did use `exit 0`, but it did not work. The following steps will still run. – Yumin Gui Nov 29 '20 at 01:08
  • 1
    @YuminGui there's a distinction to be made with "`exit 0` will end the step without cancelling the job" as opposed to perhaps what you execpted which is "`exit 0` will end the job without failing the workflow". Remember a Workflow has many jobs, a Job has many steps. each step runs a shell command or uses an action. – airtonix Feb 14 '23 at 05:46
68

In 2021, there is perhaps a more graceful way to do this:

- name: A/B Check
  if: ${{ envA }} != ${{ envB }}
  uses: actions/github-script@v3
  with:
    script: |
        core.setFailed('envA and envB are not equivalent!')

Here, we use the github-script action to provide a one liner script that will fail the job. The "A/B Check" step will only run if the condition in the if line is true, so the script will only run in that case, which is what we want.

The nice thing about this approach is that you will get nicely formatted output in the Actions UI in your repo, showing that the "A/B Check" step caused the failure, and why (i.e. "envA and envB are not equivalent").

Note that if you have additional steps in the job after this, and you do NOT want them to run if the A/B check fails, you'll want to use if: success() on them to prevent them from running in that case.

Bradleycorn
  • 980
  • 6
  • 9
  • 5
    I really like this! But I actually had to change the if condition to `if: ${{ envA != envB }}` – Rafael-WO Sep 30 '21 at 17:04
  • An even faster way is to use the technique shown in an adjacent answer: https://stackoverflow.com/a/74229789/454615 – airtonix Feb 14 '23 at 05:50
14

The Github workflow commands docs gives a hint on this.

Toolkit function Equivalent workflow command
core.setFailed Used as a shortcut for ::error and exit 1

Given that, you can do the following without using any external workflows.

steps:
  - name: A/B Check
    if: ${{ envA }} != ${{ envB }}
    run: |
      echo "::error file={name},line={line},endLine={endLine},title={title}::{message}"
      exit 1
Sam Morgan
  • 2,445
  • 1
  • 16
  • 25