jobs
needs:
Declares job dependencies so the current job waits for the listed jobs to complete successfully. Also exposes their outputs via `needs.<job_id>.outputs.<name>` and their result via `needs.<job_id>.result`.
needs: <job_id> | [job_id1, job_id2] Common values / subkeys
| Value / Subkey | Purpose |
|---|---|
| single job_id | Wait for one job |
| list of job_ids | Wait for multiple jobs (all must succeed unless `if:` overrides) |
| needs.<id>.outputs.<name> | Read a declared output from an upstream job |
| needs.<id>.result | success | failure | cancelled | skipped |
Examples
jobs:
deploy:
needs: build deploy runs after build succeeds
jobs:
publish:
needs: [build, test] Wait for both build and test
jobs:
cleanup:
needs: [build, test]
if: ${{ always() }} Run cleanup even if predecessors failed or were skipped
run: echo "${{ needs.build.outputs.artifact }}" Read an output from an upstream job
Gotcha
A skipped upstream job normally causes downstream jobs to skip as well — use `if: ${{ always() }}` or `if: ${{ !cancelled() }}` to force downstream to run.
Related keywords
jobs:
Top-level map of jobs that run in parallel by default. Each job has an ID (used by `needs:` and outputs) and either a `steps:` list or a `uses:` reference to a reusable workflow.
outputs:
Declares values a job exposes to downstream jobs that `needs:` it. Values are usually pulled from step outputs written to `$GITHUB_OUTPUT`.
if:
Conditional expression that controls whether a job or step runs. On a job it gates the entire job; on a step it gates only that step, and both automatically wrap the value in an implicit `${{ }}` if omitted.
runs-on:
Selects the runner (or runner group) that will execute the job. Accepts a single label, an array to match multiple labels (self-hosted), or an object form for larger runners and runner groups.