GitLab CI/CD: Pipeline Workflow Rules with if Condition & when Keyword
Mastering pipeline workflow rules allows you to take complete programmatic control over your GitLab CI/CD pipelines. Instead of letting every push or event trigger a build blindly, you can evaluate environmental variables, branch names, commit messages, and trigger sources to decide precisely when a pipeline should run or be aborted entirely.
1. Why Do We Need Pipeline Workflow Rules?
In real-world software engineering, teams work with multiple branches (main, feature/*, release/*, hotfix/*) and various integration triggers (merge requests, scheduled jobs, web UI manual triggers, and git pushes).
Without workflow rules, every single code push triggers a full, expensive CI/CD pipeline—even for minor documentation tweaks, work-in-progress drafts, or non-production branches. This wastes runner minutes, clutters the UI, and delays critical feedback loops.
- Resource Optimization: Prevent unnecessary pipeline executions on feature branches or draft commits.
- Security & Compliance: Restrict production deployments exclusively to protected branches (e.g.,
mainor tagged releases). - Automation Flexibility: Handle scheduled nightly builds differently from standard developer pushes.
2. Core Mental Model: The Pipeline Gatekeeper
Think of the workflow: rules block as a strict security gatekeeper standing at the entrance of your GitLab CI/CD pipeline.
When a pipeline is triggered, GitLab evaluates the workflow: rules from top to bottom. The first rule that matches determines the fate of the entire pipeline. If no rules match, the default behavior applies.
3. GitLab Predefined CI/CD Variables
GitLab automatically injects a rich set of environment variables into every pipeline execution. You never need to declare these manually; they are populated by GitLab based on the context of the commit, branch, or trigger source.
Essential Predefined Variables Table
Note: GitLab provides an extensive official documentation page detailing all available predefined variables, their descriptions, and exact behaviors. Always consult the official reference when looking for niche pipeline telemetry.
4. Syntax & Structure of workflow: rules
To implement workflow rules in your .gitlab-ci.yml file, you use the top-level workflow: keyword combined with a list of rules. Each rule contains an if condition and a when directive.
Naive vs. Controlled Pipeline Configuration
Naive Approach (No Workflow Rules):
# Every push, tag, and manual action triggers this pipeline
stages:
- build
- test
build_job:
stage: build
script:
- echo "Building application..."
Controlled Approach (Using Workflow Rules):
stages:
- build
- test
workflow:
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: always
- when: never
5. Step-by-Step Evolution of Practical Workflow Rules
Let's examine how workflow rules evolve from simple branch restrictions to complex multi-condition filters.
Example A: Restricting Pipelines Exclusively to the main Branch
If you want your repository to run pipelines only when code is pushed to the main branch, you can evaluate CI_COMMIT_BRANCH:
workflow:
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
- Behavior: If the branch is
main, the pipeline proceeds. If any developer pushes to a feature branch (e.g.,feature/login), GitLab evaluates the rule, finds no match, skips default execution, and displays:Pipeline cannot be run because the pipeline did not run. Review the workflow rules configuration.
Example B: Ignoring Draft Commits
Developers often push work-in-progress code with commit messages ending in --draft or containing draft tags. We can instruct GitLab to skip pipeline creation for these commits:
workflow:
rules:
- if: '$CI_COMMIT_MESSAGE =~ /-draft$/'
when: never
- if: '$CI_COMMIT_BRANCH == "main"'
when: always
- Explanation:
- The first rule checks if the commit message ends with
-draft. If true,when: neverimmediately aborts the pipeline. - The second rule ensures that standard commits on
mainexecute normally.
- The first rule checks if the commit message ends with
Example C: Handling Pipeline Sources (push vs. web vs. schedule)
You can control pipelines based on how they were initiated using CI_PIPELINE_SOURCE.
workflow:
rules:
# Block manual web triggers if desired, or block schedules
- if: '$CI_PIPELINE_SOURCE == "schedule"'
when: never
- if: '$CI_PIPELINE_SOURCE == "push"'
when: always
6. Advanced Pattern Matching with Feature Branches & Negation
In larger enterprise workflows, you may want to allow specific branch naming conventions while excluding others, or vice versa.
Branch Prefix Rule Configuration
Consider a scenario where you want to allow feature branches starting with feature/ while ensuring strict control over production branches:
workflow:
rules:
# Rule 1: Never run pipelines if the branch starts with feature- and we explicitly want to block it
- if: '$CI_COMMIT_BRANCH =~ /^feature-/'
when: never
# Rule 2: Always run if it's the main branch
- if: '$CI_COMMIT_BRANCH == "main"'
when: always
# Rule 3: Allow pushes for general branches
- if: '$CI_PIPELINE_SOURCE == "push"'
when: always
7. Real-World Practical Pitfalls & Debugging Mindset
When writing and testing workflow rules, engineers frequently encounter specific traps:
- The "Pipeline Cannot Be Run" Error: If a user clicks Run Pipeline manually in the GitLab Web UI but your workflow rules strictly require
$CI_COMMIT_BRANCH == "main"while the user selected a feature branch, GitLab blocks execution. Always ensure your manual testing branch matches yourifconditions. - Order of Evaluation Matters: GitLab evaluates rules sequentially from top to bottom. If a broad rule (like
when: alwaysfor pushes) is placed above a specific restriction rule (likewhen: neverfor draft commits), the broad rule matches first, and the restriction is ignored. Always place restrictivewhen: neverrules at the top. - Implicit
when: on_success: If anifcondition matches but no explicitwhenkeyword is provided, GitLab defaults towhen: on_success(which functions aswhen: alwaysat the workflow level).
8. Summary and Key Takeaways
- Centralized Control:
workflow: rulesgive you absolute authority over whether a pipeline is instantiated, saving runner minutes and enforcing deployment governance. - Top-to-Bottom Evaluation: Rules are evaluated sequentially; the first matching rule dictates the pipeline's fate.
- Predefined Variables: Leverage GitLab's built-in variables like
CI_COMMIT_BRANCH,CI_COMMIT_MESSAGE,CI_COMMIT_TAG, andCI_PIPELINE_SOURCEwithout manual declaration. - The Power of
when: never: Usewhen: neverat the top of your rules block to filter out unwanted executions such as draft commits, scheduled runs, or unauthorized branch pushes. - Branch Protection: Combine
CI_COMMIT_PROTECTEDand branch name checks to secure production and staging deployment pipelines. - Next Steps: While workflow rules control the entire pipeline, upcoming advanced modules explore job-wise rules (
rulesinside individual jobs) for granular stage-level control.