jobs

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.

if: ${{ <expression> }}    # or bare expression

Common values / subkeys

Value / Subkey Purpose
success() Default — all previous steps/needs succeeded
always() Run even on failure/cancellation
failure() Run only if a previous step/need failed
cancelled() Run only when the workflow was cancelled

Examples

if: github.ref == 'refs/heads/main'

Branch guard (implicit expression, no braces required)

if: ${{ github.event_name == 'pull_request' && !github.event.pull_request.draft }}

Only non-draft PRs

if: ${{ always() }}

Always run — useful for cleanup/notify

if: ${{ needs.build.result == 'success' && inputs.deploy }}

Depend on upstream result and an input

Gotcha

Without `always()` / `failure()` / `!cancelled()`, `if:` implicitly ANDs with `success()`, so a bare expression won't run after a failure; on jobs, `steps.*`, `env`, and `matrix` are unavailable — only `needs`, `github`, `inputs`, `vars`, and `secrets` can be referenced from job-level `if:`.

Related keywords

← All GitHub Actions syntax · Git commands · Cron syntax