Skip to main content
This article explores how to use expressions in GitHub Actions to control the execution flow of steps and jobs. We cover:
  • Conditional execution with if
  • Ignoring failures using continue-on-error
  • Built-in status check functions

Sample Workflow

The following workflow runs tests on both Ubuntu and Windows, uploads a report to AWS S3 (failing intentionally), and then deploys if the report step completes.
on: push

jobs:
  testing:
    strategy:
      matrix:
        os: ['windows-latest', 'ubuntu-latest']
    runs-on: ${{ matrix.os }}
    steps:
      - name: Testing on Ubuntu
        run: |
          export apikey=3$CuR3-t0k3N
          echo "Running Tests on Ubuntu..."

      - name: Testing on Windows
        run: |
          Set-Variable -Name "apikey" -Value "3$CuR3-t0k3N"
          echo "Running Tests on Windows..."

  reports:
    needs: testing
    runs-on: ubuntu-latest
    steps:
      - name: Upload Report to AWS S3
        run: |
          echo "Uploading reports..." && exit 1

  deploy:
    needs: reports
    runs-on: ubuntu-latest
    steps:
      - name: Deploy Application
        run: echo "Deploying application..."
In this example:
  • Ubuntu tests pass.
  • Windows commands fail on Linux, causing the testing job to abort.
  • As a result, reports and deploy are skipped.

Conditional Execution with if

Use if to run steps or jobs only when a condition is met. You can reference contexts like runner.os, literals, and functions:
jobs:
  testing:
    strategy:
      matrix:
        os: ['windows-latest', 'ubuntu-latest']
    runs-on: ${{ matrix.os }}
    steps:
      - name: Testing on Ubuntu
        if: runner.os == 'Linux'
        run: |
          export apikey=3$CuR3-t0k3N
          echo "Running Tests on Ubuntu..."

      - name: Testing on Windows
        if: runner.os == 'Windows'
        run: |
          Set-Variable -Name "apikey" -Value "3$CuR3-t0k3N"
          echo "Running Tests on Windows..."
Each step only executes on its intended OS, preventing unsupported commands from running.

Ignoring Failures with continue-on-error

By default, a failed step aborts its job. To let a job succeed even if a step fails, set continue-on-error: true. Downstream jobs defined with needs will still run if the parent job completes.
The continue-on-error attribute applies at the step level, not at the job level.
on: push

jobs:
  testing:
    strategy:
      matrix:
        os: ['windows-latest', 'ubuntu-latest']
    runs-on: ${{ matrix.os }}
    steps:
      - name: Testing on Linux
        if: runner.os == 'Linux'
        run: |
          export apikey=3$CuR3-t0k3N
          echo "Running Tests on Ubuntu..."

      - name: Testing on Windows
        if: runner.os == 'Windows'
        run: |
          Set-Variable -Name "apikey" -Value "3$CuR3-t0k3N"
          echo "Running Tests on Windows..."

  reports:
    needs: testing
    runs-on: ubuntu-latest
    steps:
      - name: Upload Report to AWS S3
        run: |
          echo "Uploading reports..." && exit 1
        continue-on-error: true

  deploy:
    needs: reports
    runs-on: ubuntu-latest
    steps:
      - name: Deploy Application
        run: echo "Deploying application..."
Here, even though the upload step fails, reports completes successfully and triggers the deploy job.

Status Check Functions

GitHub Actions provides built-in functions to inspect previous outcomes:
FunctionReturns true when…
success()all prior steps and jobs have succeeded
failure()any prior step or job has failed
cancelled()the workflow run was cancelled
always()always (useful for cleanup steps)
Example:
jobs:
  build-and-test:
    runs-on: ubuntu-latest
    steps:
      - name: Build
        run: npm run build

      - name: Test
        run: npm test
        if: success()

      - name: Notify on Failure
        run: echo "Tests failed!"
        if: failure()

      - name: Cleanup
        run: echo "Cleaning up environment..."
        if: always()
These functions help you create resilient, conditional workflows that adapt to your CI/CD pipeline’s status.