Conditional Execution: Mastering Logic in GitHub Actions
Learn how to use the 'if' keyword to add conditional logic to your CI/CD workflow. Control your pipeline steps based on branch names, events, and results.

Previously in this course, we explored how to run tests in parallel using mastering-matrix-builds-multi-version-testing-in-ci-cd. While running everything at once is efficient, real-world pipelines often require smarter decision-making—like skipping a deployment job on a feature branch or only running specialized security scans on the main branch. In this lesson, we add that control using conditional execution.
Understanding Conditional Execution
In programming, we use if statements to handle different scenarios; GitHub Actions brings this same power to your pipeline YAML. By using the if keyword, you can tell the runner: "Only execute this specific task if this condition is true."
This prevents "pipeline clutter"—where logs are filled with redundant steps—and saves you compute minutes by skipping unnecessary actions. You can evaluate conditions based on:
- Contexts: The
githubcontext (e.g., branch name, event type). - Status checks: Whether the previous step succeeded or failed.
- Secrets: Whether a specific secret is present.
The 'if' Keyword in Practice

The most common use case for conditional logic is protecting production-only steps. For example, you might want to run a database migration script only when code is pushed to the main branch.
Worked Example: Branch-Specific Deployment
Imagine your workflow has a "Build" job and a "Deploy" job. You don't want to deploy feature branches to production. Here is how you apply that logic:
YAMLjobs: build: runs-on: ubuntu-latest steps: - run: echo "Building the application..." deploy: needs: build runs-on: ubuntu-latest # Only run this job if the branch is main if: github.ref == 'refs/heads/main' steps: - run: echo "Deploying to production!"
In this example, if you push to a branch named feature-login, the deploy job will be marked as "skipped" in the GitHub Actions UI. It doesn't fail; it simply doesn't run, which is exactly what we want.
Handling Step-Level Conditions
You aren't limited to job-level control. You can also apply if to individual steps. This is useful for "cleanup" tasks that should only run if a previous step failed.
YAMLsteps: - name: Run Tests id: test run: npm test - name: Notify on failure if: failure() run: echo "The tests failed, sending alert..."
Hands-on Exercise
- Open your existing workflow file in
.github/workflows/. - Add a new step to your existing job that prints "This is the main branch!"
- Use the
ifcondition so that this step only runs whengithub.refequals'refs/heads/main'. - Commit and push this change.
- Check your "Actions" tab in GitHub. You should see the step listed but marked as skipped if you are currently on a different branch.
Common Pitfalls
- Syntax Errors: GitHub Actions requires single quotes inside the
ifcondition for string literals. Usingif: github.ref == refs/heads/main(without quotes) will cause a parse error. Always useif: github.ref == 'refs/heads/main'. - The "Skipped" Trap: Remember that a skipped job is technically "successful" in terms of workflow status. If you have other jobs that
needthis job, they will still run unless you explicitly handle the dependency logic. - Over-Engineering: Don't turn your YAML into a programming language. If your logic becomes too complex (e.g., deeply nested conditions), it is better to move that logic into a script (like a Python or Bash script) and call that script from the step instead.
FAQ
Q: Can I use else in GitHub Actions?
A: No, GitHub Actions doesn't support an else keyword. If you need an if-else structure, you typically define two separate steps with opposing conditions (e.g., one that runs if a variable is true, and one that runs if it's false).
Q: Does a skipped job count against my billing? A: No, skipped jobs are not executed, so they do not consume your allocated GitHub Actions minutes.
Q: What is always()?
A: always() is a special function you can use in an if condition to force a step to run even if a previous step failed or was cancelled. It’s perfect for cleanup tasks.
Recap

Conditional execution turns your static YAML file into a dynamic, responsive pipeline. By using the if keyword, you can:
- Use
github.refto restrict jobs to specific branches. - Use
failure()orsuccess()to handle pipeline outcomes gracefully. - Save resources and keep your logs clean by skipping unnecessary tasks.
Up next: We will learn how to abstract these complex steps into Custom Actions, allowing you to reuse your code across multiple workflows.
Work with me

CI/CD Pipeline & Docker Containerization
Ship with confidence: automated CI/CD pipelines and Docker setups so every push is tested and deployed — no more manual, error-prone releases.

AI Automation & Agentic Workflow Development
Automate the repetitive work eating your time — content pipelines, data workflows, and agentic AI tasks that run themselves.


