Skip to main content

Workflow

So far we've controlled pipeline jobs using rules in each job, but it's possible to define when the entire pipeline should run through workflow.

It sits at the top of .gitlab-ci.yml and is useful for preventing GitLab from wasting resources running unnecessary pipelines.

Basic example:

workflow:
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: always
- when: never

This example says: only run the pipeline if the branch is main, otherwise do nothing. Don't confuse with job rules. workflow.rules controls the entire pipeline, while rules: in jobs controls individual jobs.

Workflow rules take precedence over job rules.

If the workflow blocks the pipeline, no jobs will run, even if job rules allow them to run.

In GitLab, pipeline execution follows two decision layers:

  1. Workflow (workflow.rules):

    • Decides if the entire pipeline should be created.
    • If no rule is satisfied → the pipeline won't even be created.
  2. Jobs (rules, only, except):

    • Once the pipeline is created, these rules define which jobs will run inside it.

In other words, if we were to create a workflow for our project that wouldn't interfere with our job rules, we would need to cover everything.

If we have this in our .gitlab-ci.yml:

workflow:
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
when: always # Allowed for any merge request
- if: '$CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "develop"' # Allowed for commits on these branches
when: always
- when: never

The first rule allows the pipeline in merge requests, but the jobs in pre-check and check stages won't trigger, because despite being a merge event, one of the job rules ensures it should only target develop or main branches.

.rules-only-mr-main-develop:
rules:
- if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "main"'
when: always
- if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop"'
when: always

Using workflow helps:

  • Avoid unnecessary pipelines. Forgetting to add a rule to a job would make it trigger for any reason.
  • Define pipeline intent. At a glance you can tell it's for merge requests and specific branches and not for tags, or vice versa.