Operations 6 min read

Using only/except and rules in GitLab CI for Job Control

This tutorial explains how to use GitLab CI's only/except parameters and the newer rules syntax—including if, changes, exists, and allow_failure clauses—to control job execution, configure branch restrictions, and define workflow-level pipeline creation, illustrated with comprehensive YAML examples.

DevOps Cloud Academy
DevOps Cloud Academy
DevOps Cloud Academy
Using only/except and rules in GitLab CI for Job Control

This article is part of a "GitLab CI Practice" tutorial and demonstrates how to limit job execution using the only and except keywords, which specify which branches or tags a job should run on or be excluded from.

It then introduces the newer rules syntax, which evaluates a list of rule objects in order until one matches, and notes that rules cannot be combined with only / except . Available rule clauses include if (similar to only:variables ), changes (similar to only:changes ), and exists .

rules:if example shows a manual run when a variable DOMAIN matches a value, otherwise the job runs on success; multiple conditions can be combined with && or || .

variables:
  DOMAIN: example.com
codescan:
  stage: codescan
  tags:
    - build
  script:
    - echo "codescan"
    - sleep 5;
  #parallel: 5
  rules:
    - if: '$DOMAIN == "example.com"'
      when: manual
    - when: on_success

rules:changes triggers when specified files (e.g., Jenkinsfile ) change in a commit.

codescan:
  stage: codescan
  tags:
    - build
  script:
    - echo "codescan"
    - sleep 5;
  #parallel: 5
  rules:
    - changes:
        - Jenkinsfile
      when: manual
    - if: '$DOMAIN == "example.com"'
      when: on_success
    - when: on_success

rules:exists runs when a listed file exists in the repository.

codescan:
  stage: codescan
  tags:
    - build
  script:
    - echo "codescan"
    - sleep 5;
  #parallel: 5
  rules:
    - exists:
        - Jenkinsfile
      when: manual
    - changes:
        - Jenkinsfile
      when: on_success
    - if: '$DOMAIN == "example.com"'
      when: on_success
    - when: on_success

rules:allow_failure permits a job to fail without stopping the pipeline, optionally making it manual.

job:
  script: "echo Hello, Rules!"
  rules:
    - if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"'
      when: manual
      allow_failure: true

When the first rule matches, the job runs manually and failures are ignored.

The top‑level workflow:rules keyword determines whether a pipeline is created at all, with when set to always or never (default always ).

variables:
  DOMAIN: example.com
workflow:
  rules:
    - if: '$DOMAIN == "example.com"'
    - when: always

A comprehensive YAML example combines all concepts: global variables, workflow rules, stages (build, test, codescan, deploy), and jobs that use only , rules , exists , changes , allow_failure , when , start_in , retry , and timeout settings.

before_script:
  - echo "before-script!!"
variables:
  DOMAIN: example.com
workflow:
  rules:
    - if: '$DOMAIN == "example.com"'
      when: always
    - when: never
stages:
  - build
  - test
  - codescan
  - deploy
build:
  before_script:
    - echo "before-script in job"
  stage: build
  script:
    - echo "mvn clean "
    - echo "mvn install"
    - ech "$DOMAIN"
  after_script:
    - echo "after script in buildjob"
  rules:
    - exists:
        - Dockerfile
      when: on_success
      allow_failure: true
    - changes:
        - Dockerfile
      when: manual
    - when: on_failure
unittest:
  stage: test
  script:
    - ech "run test"
  when: delayed
  start_in: '5'
  allow_failure: true
  retry:
    max: 1
    when:
      - script_failure
  timeout: 1 hours 10 minutes
deploy:
  stage: deploy
  script:
    - echo "hello deploy"
    - sleep 2;
  rules:
    - if: '$DOMAIN == "example.com"'
      when: manual
    - if: '$DOMAIN == "aexample.com"'
      when: delayed
      start_in: '5'
    - when: on_failure
codescan:
  stage: codescan
  script:
    - echo "codescan"
    - sleep 5;
  when: on_success
  parallel: 5
after_script:
  - echo "after-script"
  - ech

The article concludes with promotional messages encouraging readers to join a technical group and share the content.

CI/CDworkflowGitLab CIPipelinerulesexceptonly
DevOps Cloud Academy
Written by

DevOps Cloud Academy

Exploring industry DevOps practices and technical expertise.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.