Skip to main content

Working with Job Rules and Conditions

1. Defining Job Rules

Property Values Description
rules array Array of rule objects that define when a job runs
rules[].if string Condition to evaluate using GitLab CI/CD variables and operators
rules[].when string When to run the job: on_success, on_failure, always, or never
rules[].exists array List of files or directories to check for existence
rules[].changes array List of files to check for changes since last commit
rules[].variables object Variables to set if the rule matches

Example: Basic job rules with if

deploy:
  script:
    - echo "Deploying..."
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'
      when: on_success

Example: Using changes to trigger jobs

test:
  script:
    - echo "Running tests..."
  rules:
    - if: '$CI_PIPELINE_SOURCE == "push"'
      changes:
        - src/**/*
      when: on_success

Example: Setting variables in rules

build:
  script:
    - echo "Building..."
  rules:
    - if: '$CI_COMMIT_BRANCH == "develop"'
      variables:
        ENV: development
      when: on_success
Note: Rules are evaluated in order, and the first matching rule determines whether the job runs. If no rules match, the job does not run.

2. Using if Conditionals

Condition Description Example
if Defines a condition to evaluate before running the job if: $CI_PIPELINE_SOURCE == "merge_request"
unless Defines a condition to skip the job if it evaluates to true unless: $CI_COMMIT_TAG

Example: Conditional Job Execution

deploy:
  stage: deploy
  script:
    - echo "Deploying to production"
  if: $CI_COMMIT_BRANCH == "main"
Note: The if and unless conditions support GitLab CI/CD predefined variables and custom variables.
Warning: The if condition is evaluated before the job starts, and it can be used to prevent jobs from running based on branch, tag, or custom conditions.

3. Matching File Changes

Rule Description Example
changes Triggers the job if files matching a pattern have changed in the commit.
changes:
  - src/**/*.js
  - lib/**/*.ts
exists Triggers the job if a file or directory exists in the commit.
exists:
  - config/database.yml
  - docs/**/*.md

Example: Using changes to run tests only on JS files

test_js:
  stage: test
  script:
    - npm run test:js
  rules:
    - changes:
        - src/**/*.js
        - tests/**/*.js
Note: The changes rule compares the files in the current commit with those in the previous commit. It does not consider file deletions or renames.

4. Using exists for File Detection

Rule Description Example
exists Checks if a file or directory exists in the project
script:
  - echo "File exists"

Example: Using exists in a job rule

job_with_file_check:
  script:
    - echo "Running job"
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
      exists:
        - .gitlab-ci.yml
Note: The exists rule can be used to conditionally run jobs based on the presence of files or directories in the project.

5. Controlling Job Creation

Rule Description Example
only Defines when a job runs based on branch/tag names or other conditions.
job_name:
  only:
    - main
    - /^v\d+\.\d+/
except Excludes jobs from running on specified branches/tags.
job_name:
  except:
    - develop
    - /^feature\/.*/
rules Allows defining multiple conditions with priorities and variables.
job_name:
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request"
      when: manual
    - if: $CI_COMMIT_BRANCH == "main"
      when: on_success
when Controls when a job runs (e.g., on_success, manual, never).
job_name:
  when: manual

Example: Using rules for conditional job execution

deploy_staging:
  stage: deploy
  rules:
    - if: $CI_COMMIT_BRANCH == "staging"
      when: on_success
    - if: $CI_PIPELINE_SOURCE == "merge_request"
      when: manual
  script:
    - echo "Deploying to staging environment"
Note: Rules are evaluated in order, and the first matching rule determines job behavior.

6. Setting Variables in Rules

Property Description Example
rules List of rule objects that determine when a job runs
rules:
  - if: $CI_PIPELINE_SOURCE == "merge_request"
    variables:
      MR_MERGE: "true"

Example: Setting Variables Based on Branch

job_name:
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      variables:
        ENV: "production"
    - if: $CI_COMMIT_BRANCH == "develop"
      variables:
        ENV: "staging"

Example: Conditional Variable with GitLab Variables

deploy_job:
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request"
      variables:
        DEPLOY_ENV: "staging"
        MR_ID: $CI_MERGE_REQUEST_IID
    - if: $CI_PIPELINE_SOURCE == "push"
      variables:
        DEPLOY_ENV: "production"

7. Combining Multiple Rule Conditions

Condition Description Example
rules Array of rule objects to evaluate in order
[
  {
    if: "${CI_COMMIT_BRANCH} == 'main'"
  },
  {
    if: "${CI_PIPELINE_SOURCE} == 'merge_request'"
  }
]
if Condition to evaluate using GitLab CI/CD variables ${CI_COMMIT_BRANCH} == 'main'
changes Triggers job only if files match the pattern changes: ['src/**/*']
exists Triggers job only if file exists in the repository exists: ['config.json']

Example: Combining multiple conditions in a rule

deploy:
  stage: deploy
  rules:
    - if: "${CI_COMMIT_BRANCH} == 'main'"
      changes:
        - 'src/**'
      exists:
        - 'config/deploy.yaml'
      when: on_success
    - if: "${CI_PIPELINE_SOURCE} == 'merge_request'"
      when: never
Note: Rules are evaluated in order, and the first matching rule determines whether the job runs.

8. Using allow_failure with Rules

Property Description Values Notes
allow_failure Controls whether a job should be allowed to fail without stopping the pipeline true or false When set to true, the job is marked as allowed to fail. If it fails, the pipeline continues.
rules Defines conditions under which a job should run or be skipped Array of rule objects Each rule can include if, changes, exists, or when

Example: Using allow_failure with rules

job_with_rules:
  script:
    - echo "Running job"
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request"
      allow_failure: true
    - if: $CI_COMMIT_BRANCH == "main"
      allow_failure: false
Note: allow_failure can be used in conjunction with rules to control job behavior based on conditions. When a job is allowed to fail, it does not block the pipeline from proceeding.

9. Creating Manual Jobs (when: manual)

Property Value Description
when manual Specifies that the job must be manually started from the GitLab UI.

Example: Manual Job Configuration

deploy_to_staging:
  stage: deploy
  script:
    - echo "Deploying to staging..."
  when: manual
  allow_failure: false
Note: Manual jobs can be triggered by users with appropriate permissions in the GitLab project.
Warning: Jobs configured with when: manual will not run automatically and must be started manually from the GitLab UI or API.

10. Using only and except

Directive Description Usage Notes
only Specifies which branches or tags should run the job only: Job runs only on matching branches or tags
except Specifies which branches or tags should NOT run the job except: Job is excluded from running on matching branches or tags

Example: Using only and except

deploy:
  only:
    - main
    - /^v\d+\.\d+/
  except:
    - develop
    - feature/*
Note: only and except can be used together, but only takes precedence.

Key Points

  • only and except support regex patterns
  • only is evaluated before except
  • Both directives can use branch names, tags, or regex patterns
  • Use only: to restrict jobs to specific branches or tags
  • Use except: to exclude jobs from specific branches or tags

Was this article helpful?