GitHub Actions Certification

Continuous Integration with GitHub Actions

Github Action Expressions

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.

Note

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.

Watch Video

Watch video content

Previous
Workflow Configure Code Coverage