Skip work that doesn't apply
Both jobs and steps support an if: expression. The expression evaluates to truthy / falsy; falsy means skip.
Common patterns:
- Branch-specific:
if: github.ref == 'refs/heads/main' - Tag-specific:
if: startsWith(github.ref, 'refs/tags/v') - Event-specific:
if: github.event_name == 'push' - Label-specific:
if: contains(github.event.pull_request.labels.*.name, 'deploy') - Path-specific: use
paths:filter at workflow level instead. - Status-specific:
if: failure(),if: cancelled(),if: always()
Skipped vs failed
An if: that evaluates to false produces skipped, not failed. Skipped jobs don't fail the workflow. They also don't satisfy required status checks if you have branch protection enabled — be careful to not gate a required check behind a conditional, or PRs from a feature branch will hang.