Check that a job called all depends on every other job in the workflow, so
branch protection only needs a single required status check.
GitHub branch protection wants an explicit list of required status checks.
Keeping that list in sync with your CI jobs is tedious, so a common pattern is
a single gate job that needs: everything:
all:
name: All jobs finished
if: ${{ !cancelled() }}
needs: [build, lint, test]
runs-on: ubuntu-slim
steps:
- run: |
if ${{ contains(needs.*.result, 'failure') }}; then exit 1; fi
if ! ${{ contains(needs.*.result, 'success') }}; then exit 1; fiBranch protection then only requires all. But now the needs: list is the
thing that silently rots: add a job, forget to list it, and the new job no
longer gates merges. This action fails CI when that happens.
Add an 'all' job in the workflow, after checking out the repository:
all:
name: All jobs finished
if: ${{ !cancelled() }}
needs: [your-job-1, your-job-2]
runs-on: ubuntu-slim
steps:
- uses: actions/checkout@v6
- uses: clash-lang/all-jobs-ok@v2
with:
needs: ${{ toJSON(needs) }}The action checks that the workflow it runs in has a job called all whose
needs: lists exactly every other job. Given the needs input, it also
performs the result check from the shell snippet above, so no extra run:
step is needed: the action fails when any needed job failed, or when none
succeeded (e.g. all were skipped). It fails with one error per problem:
Not all jobs mentioned in all.needs: {...}— jobs missing from the gateNon-existing jobs found in all.needs: {...}— stale entriesExcluded jobs found in all.needs: {...}— excluded jobs that are listed anywayNeeded jobs failed: {...}— a job the gate depends on failedNo needed job succeeded (...)— nothing failed, but nothing succeeded either
Errors are annotated on the workflow file in pull requests.
| Input | Default | Description |
|---|---|---|
workflow-file |
the workflow of the current run | Path to the workflow file to check, relative to the repository root. |
exclude |
empty | Newline-separated job ids that must not be in all.needs, e.g. jobs that run after all to react to its result. |
needs |
empty | The needs context, passed verbatim as ${{ toJSON(needs) }}. When set, the action also checks the results of the needed jobs. |
Example with all of them:
- uses: clash-lang/all-jobs-ok@v2
with:
workflow-file: .github/workflows/ci.yml
exclude: |
notify-slack
needs: ${{ toJSON(needs) }}- The gate job must be called
all. This is deliberate: a convention, not a configuration knob. - Without the
needsinput, this action only checks theneeds:list, and thealljob itself must still fail when a dependency fails — see thecontains(needs.*.result, ...)pattern above. With theneedsinput, the action does that check itself. Either way, give the jobif: ${{ !cancelled() }}so it also runs when a dependency failed. dist/index.jsis a bundle of our BSD-2-Clause code together with the npm packages@actions/core(MIT) andyaml(ISC).
A Nix flake provides the development environment:
nix develop
npm ci
npm test
npm run build # refresh dist/index.js (committed; CI checks it is current)This action grew out of the all_check.py script in
bittide-hardware, originally
written for Google LLC.
BSD-2-Clause. This repository is REUSE compliant.