Job-level conditions
Section titled “Job-level conditions”Only want to deploy when code hits the main branch? Use GitHub’s ref context:
jobs: deploy: if: github.ref == 'refs/heads/main' runs-on: ubuntu-latest steps: - run: echo "Deploying to production"Smart job dependencies
Section titled “Smart job dependencies”Sometimes you want jobs to run even when their dependencies are skipped. Here’s how to handle a deployment that should run when tests are skipped (but not when they fail):
jobs: test: if: github.event_name != 'workflow_dispatch' # Skip tests on manual trigger runs-on: ubuntu-latest steps: - run: echo "Running tests"
deploy: needs: test if: ${{ !failure() && !cancelled() }} runs-on: ubuntu-latest steps: - run: echo "Deploying since tests passed or were skipped"Step-level conditions
Section titled “Step-level conditions”Control step execution based on previous outputs - useful for multi-stage deployments:
steps: - id: check_env run: | echo "status=ready" >> $GITHUB_OUTPUT
- if: ${{ steps.check_env.outputs.status == 'ready' }} run: echo "Environment is ready for deployment"Key contexts for conditions
Section titled “Key contexts for conditions”github- Access branch names, event types, commit infoneeds- Check status of dependent jobssteps- Read previous step outputs and statusenv- Use environment variablesjob- Get info about current jobrunner- Access runner environment details
Status check functions
Section titled “Status check functions”success()- Green light - previous steps passedfailure()- Red light - something failed upstreamcancelled()- Someone hit the cancel buttonalways()- Run regardless of previous status (use carefully!)
Expression syntax
Section titled “Expression syntax”Expressions use ${{ <expression> }} syntax (optional in if conditions). Chain conditions with && (AND) and || (OR):
steps: - if: | github.ref == 'refs/heads/main' && github.event_name == 'push' && success() run: echo "Running production deploy on main branch push"