Stages, not a pile of jobs
Jobs run in parallel unless you say otherwise. needs turns them into stages — test, then build, then deploy — and a failing stage stops everything after it. Small values (a version number, a URL) can flow from one job to the next as outputs.
needs and outputs
name: Pipeline
on: push
jobs:
lint:
runs-on: ubuntu-latest
steps:
- run: echo "linting"
test:
runs-on: ubuntu-latest
steps:
- run: echo "testing"
version:
runs-on: ubuntu-latest
outputs:
tag: ${{ steps.v.outputs.tag }}
steps:
- id: v
run: echo "tag=v1.4.${{ github.run_number }}" >> "$GITHUB_OUTPUT"
build:
needs: [lint, test, version]
runs-on: ubuntu-latest
steps:
- run: echo "Building ${{ needs.version.outputs.tag }}"
notify:
needs: build
if: failure()
runs-on: ubuntu-latest
steps:
- run: echo "Tell the team the build broke"