Run GitHub actions job only if previous job has failed

I am trying to run a job in a GitHub workflow only if one (or more) of the previous jobs has failed.

So at the moment I have something like:

job1:
  steps:
    -
    -
job2:
  steps:
    -
    -
run-if-fail:
  if: ${{ always() && (needs.job1.result=='failure' || needs.job2.result=='failure') }}
  needs: [job1, job2]
  steps:
    -
    -

However, the run-if-fail job seems to run always, ignoring job1 and job2 result.

I tried a setup like yours and it works fine for me.

One of the job failing makes the run-if-failed job run:

image

With both jobs succeeding the run-if-failed job is skipped:

image

Workflow code:

name: Conditional

on:
  push:
    branches:
      - master

jobs:
  job1:
    runs-on: ubuntu-latest
    steps:
      - name: Succeed
        run: |
          exit 0
  job2:
    runs-on: ubuntu-latest
    steps:
      - name: Succeed
        run: |
          echo "ok"
  run-if-failed:
    runs-on: ubuntu-latest
    needs: [job1, job2]
    if: always() && (needs.job1.result == 'failure' || needs.job2.result == 'failure')
    steps:
      - name: Needs context
        env:
          NEEDS_CONTEXT: ${{ toJSON(needs) }}
        run: |
          echo "$NEEDS_CONTEXT"

Replace the step in job1 with the following to make it fail in order to test the other case:

      - name: Fail
        run: |
          exit 1

BTW. while the documentation about job status functions implies that they would refer to the status of previous steps in a job, they seem to work analogously for jobs. if: failure() works in my test just as well and is a lot simpler than always() && (needs.job1.result == 'failure' || needs.job2.result == 'failure'). It also doesn’t require changing the conditions should you want to add another job.

2 Likes