Lesson 8 / 25

Job Dependencies With needs

Build a pipeline graph.

Parallel by default, ordered by needs

Jobs run in parallel unless needs: says one depends on another; a job with needs: [test, lint] waits for both and is skipped if either fails (unless its if uses always() or similar status functions). This forms a directed graph: run fast checks in parallel, then build, then deploy. Mistakes in needs (typos, cycles) are caught by linting before a run is attempted, as the cron example in the previous section showed.

A pipeline graph

Not linted or run here; check the GitHub Actions documentation for current syntax.

jobs:
  lint:      { runs-on: ubuntu-latest, steps: [ { run: npm run lint } ] }
  test:      { runs-on: ubuntu-latest, steps: [ { run: npm test } ] }
  build:
    needs: [lint, test]               # waits for both
    runs-on: ubuntu-latest
    steps: [ { run: npm run build } ]
  notify:
    needs: build
    if: ${{ always() }}                # runs even if build failed
    runs-on: ubuntu-latest
    steps: [ { run: echo "build result ${{ needs.build.result }}" } ]

Fail fast with cheap jobs first

Put quick checks (lint, type check) in early parallel jobs so obvious problems fail within a minute.

Quick check: What happens to a job whose needs dependency failed?

  • It retries forever
  • It runs anyway
  • It is skipped, unless its if condition uses a status function such as always()
  • It deletes the workflow
Answer

It is skipped, unless its if condition uses a status function such as always() — Dependencies gate execution.