Back to Blog
Lesson 29 of the CI/CD: Continuous Integration from Scratch course
DevOpsAugust 4, 20264 min read

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.

github actionsci/cdautomationdevopsworkflowlogic
Close-up of PHP code on a monitor, highlighting development and programming concepts.

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 github context (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

Close-up of notebook with SEO terms and keywords, highlighting digital marketing strategy.

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:

YAML
jobs:
  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.

YAML
steps:
  - name: Run Tests
    id: test
    run: npm test

  - name: Notify on failure
    if: failure()
    run: echo "The tests failed, sending alert..."

Hands-on Exercise

  1. Open your existing workflow file in .github/workflows/.
  2. Add a new step to your existing job that prints "This is the main branch!"
  3. Use the if condition so that this step only runs when github.ref equals 'refs/heads/main'.
  4. Commit and push this change.
  5. 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 if condition for string literals. Using if: github.ref == refs/heads/main (without quotes) will cause a parse error. Always use if: 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 need this 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

Team members presenting a project in a modern office setting with a focus on collaboration.

Conditional execution turns your static YAML file into a dynamic, responsive pipeline. By using the if keyword, you can:

  • Use github.ref to restrict jobs to specific branches.
  • Use failure() or success() 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.

Similar Posts