Pipeline invalid YAML error when running for merge requests only

Problem to solve

When our pipeline runs on a branch, there are no issues. When I created the merge request, the pipeline that runs for the merge request, on the same commit, fails with “yaml invalid” error. It says that the build job does not exist and is required for a job that we run manually.

Here’s how our pipeline looks like:

stages:
  - check
  - build
  - deploy
  - push_to_alcon

checkstyle:
  tags:
    - gitlab-runner
  stage: check
  image: gradle:${GRADLE_VERSION}-jdk${JAVA_VERSION}-alpine
  before_script:
    - ..
  script:
    - ..
  artifacts:
    paths:
      - reports/checkstyle/*
    expire_in: "30 days"
    when: always

test:
  tags:
    - gitlab-runner
  stage: check
  image: gradle:${GRADLE_VERSION}-jdk${JAVA_VERSION}-alpine
  before_script:
    - ..
  script:
    - ..
  artifacts:
    paths:
      - tests/**/*
    expire_in: "30 days"
    when: always

build:
  tags:
    - gitlab-runner
  rules:
    - if: '$CI_COMMIT_BRANCH =~ /^(dev|master)/'
      when: always
    - when: manual
  stage: build
  image: gradle:${GRADLE_VERSION}-jdk${JAVA_VERSION}-alpine
  before_script:
    - ..
  script:
    - ..
  artifacts:
    paths:
      - server/docs/**/*
    expire_in: "30 days"

.base_deploy_job:
  tags:
    - gitlab-runner
  stage: deploy
  image: gradle:${GRADLE_VERSION}-jdk${JAVA_VERSION}-alpine
  needs:
    - build
    - test
  dependencies:
    - build
    - test
  before_script:
    - ..
  script:
    - ..

deploy_dev:
  extends: .base_deploy_job
  tags:
    - gitlab-runner
  rules:
    - if: '$CI_COMMIT_BRANCH == "dev"'
  stage: deploy
  image: gradle:${GRADLE_VERSION}-jdk${JAVA_VERSION}-alpine
  environment:
    name: dev

deploy_demo:
  extends: .base_deploy_job
  tags:
    - gitlab-runner-test
  rules:
    # If the build is started on a feature branch, then we automatically deploy to demo.
    - if: '$CI_COMMIT_BRANCH !~ /^(dev|master)/'
    # We only deploy to demo manually for all other branches.
    - when: manual
      allow_failure: true
  stage: deploy
  image: gradle:${GRADLE_VERSION}-jdk${JAVA_VERSION}-alpine
  environment:
    name: demo

deploy_prod:
  extends: .base_deploy_job
  rules:
    - if: '$CI_COMMIT_BRANCH == "master"'
  stage: deploy
  image: gradle:${GRADLE_VERSION}-jdk${JAVA_VERSION}-alpine
  environment:
    name: prod

Steps to reproduce

I’ve set up a project to reproduce the issue:

Configuration

Provide screenshots from the GitLab UI showing relevant configuration, if applicable.
On self-managed instances, add the relevant configuration settings or changes.

Versions

Please select whether options apply, and add the version information.

Versions

  • GitLab v16.7.4

I would recommend to use workflow: rules+rules for jobs to control push/merge pipelines, your example triggers pipeline twice: for push and merge request.
For push it might work, but for merge request yaml error appears. Test job is not run,because:

job-with-no-rules:
  script: echo "This job runs in branch pipelines."

job-with-rules:
  script: echo "This job runs in merge request pipelines."
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"

For every change pushed to the branch, duplicate pipelines run. One branch pipeline runs a single job (job-with-no-rules ), and one merge request pipeline runs the other job (job-with-rules ). Jobs with no rules default to except: merge_requests, so job-with-no-rules runs in all cases except merge request

I would suggest adding anchors with rules at yaml file and use them, smth like

.on-pull-request: &on-pull-request
  if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_OPEN_MERGE_REQUESTS

workflow:
  rules:
    - *on-pull-request
    - other rules

job1:
  stage: test
  rules:
    - *on-pull-request
    - other rules