MR pipeline created with 0 jobs and fails despite workflow:rules blocking merge_request_event, when CI/CD Components are included

Summary

When a project uses include: component: and has workflow:rules with when: never for merge_request_event, GitLab still creates a merge_request_event pipeline when an MR is opened via the REST API by a project access token bot user. The pipeline has 0 matching jobs (all component jobs exclude merge_request_event), instantly fails, and becomes the MR's head_pipeline — showing a red on the MR even when the actual review pipeline succeeds.

Environment

  • GitLab.com SaaS (latest)
  • CI/CD Components (include: component:)

Steps to Reproduce

  1. Project A (upstream) has an import pipeline that:

    • Pushes a branch to Project B using a project access token (git push -o ci.skip)
    • Creates an MR on Project B via REST API (POST /projects/:id/merge_requests)
  2. Project B .gitlab-ci.yml:

    workflow:
      rules:
        - if: $CI_PIPELINE_SOURCE == "merge_request_event"
          when: never
        - if: $CI_PIPELINE_SOURCE == "pipeline"
        - if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
        - when: never
    
    include:
      - component: $CI_SERVER_FQDN/my-group/my-component/review@main
        inputs: { sid: "BHF" }
    
    stages: [atc, report, publish]
  3. The included component defines jobs with rules that do NOT match merge_request_event:

    .acr-rules-review:
      rules:
        - if: '$CI_PIPELINE_SOURCE == "pipeline" && $CI_COMMIT_REF_NAME =~ /^tr\//'
        - if: '$CI_PIPELINE_SOURCE =~ /^(push|api|web|trigger)$/ && $CI_COMMIT_REF_NAME =~ /^tr\//'
  4. Project A's pipeline creates the MR on Project B via API using the project access token (project_{ID}_bot_{hash} user).

Expected Behavior

  • workflow:rules with when: never for merge_request_event should prevent pipeline creation entirely
  • git push -o ci.skip should also prevent pipeline creation on push
  • No merge_request_event pipeline should appear on the MR

Actual Behavior

  • A merge_request_event pipeline IS created despite workflow:rules blocking it
  • The pipeline has 0 matching jobs (all component jobs exclude merge_request_event)
  • It instantly fails with status failed and becomes the MR's head_pipeline
  • The pipeline is created by the project access token bot user
  • Neither ci.skip push option nor workflow:rules prevents this

Attempted Workarounds (all failed)

Approach Result
workflow:rules with when: never for merge_request_event Pipeline still created
git push -o ci.skip Only prevents push pipeline, not MR pipeline
Remove merge_request_event from all job rules Pipeline created with 0 jobs, fails
API-based MR creation (no push options) MR pipeline still created
Cancel pipeline via API No-op (already failed)
Delete pipeline via API 403 (requires Owner role)
Create pipeline via POST /pipeline API 400: insufficient permission on tr/* branches

Working Workaround

Add a placeholder job that matches merge_request_event so the MR pipeline passes (green) instead of failing:

acr-mr-info:
  stage: .pre
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
  script:
    - echo "Placeholder - actual review runs via downstream pipeline"

Impact

  • The failed MR pipeline becomes head_pipeline, showing a red X on the MR even when the actual review pipeline succeeds
  • Cannot delete it (requires Owner role; project access tokens max out at Maintainer)
  • Users see confusing dual pipelines on MRs

Root Cause Hypothesis

There appear to be two possible root causes (or a combination):

  1. MR pipeline creation happens before CI config is evaluated: When a project access token bot user creates an MR via the REST API, GitLab may trigger the merge_request_event pipeline at the Git/MR level before workflow:rules are parsed and applied.

  2. include: component: interaction: When a .gitlab-ci.yml contains include: component:, GitLab may evaluate the component's job rules before applying workflow:rules, or the component inclusion causes a different pipeline creation code path that bypasses workflow:rules enforcement.

The fact that the pipeline has 0 jobs (all job rules correctly exclude merge_request_event) but the pipeline itself is still created suggests workflow:rules is not being evaluated at the pipeline creation stage — only at the job scheduling stage.

Edited by 🤖 GitLab Bot 🤖