How to Drive Conditional Jobs From Job Outputs in CI
Job outputs are strings, so incremental gating hinges on comparing them exactly: needs.detect.outputs.flag == the string true, not a bare truthiness check.
Job outputs cross job boundaries only as strings. Compute a flag in a detect job, promote it to outputs:, and compare it as == 'true' in each dependent job. Getting the string comparison right is the whole trick.
Steps
- In the detect job, write
flag=true(or false) to$GITHUB_OUTPUT. - Map it under the job
outputs:key. - In consumers, compare
needs.detect.outputs.flag == 'true'.
Workflow
.github/workflows/ci.yml
jobs:
detect:
runs-on: ubuntu-latest
outputs:
run_e2e: ${{ steps.decide.outputs.run_e2e }}
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 }
- id: decide
run: |
if git diff --name-only origin/main...HEAD | grep -q '^src/'; then
echo "run_e2e=true" >> "$GITHUB_OUTPUT"
else
echo "run_e2e=false" >> "$GITHUB_OUTPUT"
fi
e2e:
needs: detect
if: needs.detect.outputs.run_e2e == 'true'
runs-on: ubuntu-latest
steps: [{ run: npm run test:e2e }]Gotchas
- Outputs are always strings;
if: needs.detect.outputs.run_e2e(no comparison) is truthy for any non-empty string including "false". - An empty output is treated as false, which is easy to trip over if the producing step failed silently.
Related guides
How to Run Jobs Only for Changed Paths in CIRun individual GitHub Actions jobs only when their area changed by feeding paths-filter outputs into a job-le…
How to Build a Dynamic Matrix From Changed DirectoriesGenerate a GitHub Actions job matrix at runtime from the directories that changed, using fromJSON so only aff…
How to Detect Changed Files With Plain git diff in CIDetect changed files in CI with plain git diff --name-only against a base ref, a zero-dependency way to drive…