GitLab CI/CD Associate study materials
GitLab CI/CD Associate study resources

No merge request pipeline, a rule that never matches, and an external contributor

GitLab CI/CD Associate · Put your knowledge to work in context.

All case studies

No merge request pipeline, a rule that never matches, and an external contributor

A contributor pushes feature/PROJ-812 to the project (not a fork) and opens a merge request into main. The pipeline list shows exactly one pipeline, source push. The unit job uses rules: - if: $CI_COMMIT_BRANCH == "main", so it is expectedly absent. But smoke, whose only rule is - if: $CI_PIPELINE_SOURCE == "merge_request_event", never appears either, and any job that prints $CI_MERGE_REQUEST_IID shows an empty value. The root .gitlab-ci.yml starts with a workflow: block containing a single rule, - if: $CI_PIPELINE_SOURCE == "push", added months ago to silence scheduled pipelines. Later, an external contributor's MR from a fork gets no pipeline in the parent project, and a maintainer asks whether that fork pipeline would receive the protected DEPLOY_KEY variable used by deploy:review.

1. Why is there no merge request pipeline even though `smoke` has a matching job rule? What change creates one, and how do you avoid reintroducing duplicates?

Read the worked answer

workflow:rules is evaluated before jobs are examined, and it acts as a gate on pipeline creation. With only - if: $CI_PIPELINE_SOURCE == "push", every non-push context - merge request events, schedules, tags, web-triggered runs - is rejected outright, so smoke's job-level rule never gets a chance to match and the MR variables ($CI_MERGE_REQUEST_IID, $CI_MERGE_REQUEST_TARGET_BRANCH_NAME) are never defined. The job rule is correct; the gate above it is wrong.

workflow:
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
      when: never
    - if: $CI_COMMIT_BRANCH
    - if: $CI_PIPELINE_SOURCE == "schedule"
      when: never

Diagnose this by reading the pipeline source badge and by comparing behaviour across contexts: a job whose rule looks right but never appears usually means the pipeline itself was never created. Use CI Lint with simulated refs to test the workflow block, and remember the failure mode - if no workflow rule matches, nothing runs at all and no error is shown on the commit.

2. The team wants the MR-rules to run only when the merge request targets `main`. Why does `$CI_COMMIT_BRANCH == "main"` fail, and what should replace it?

Read the worked answer

Merge request pipelines for branches run on a detached ref, so $CI_COMMIT_BRANCH is not defined there. A rule comparing it to "main" evaluates false in every MR pipeline, which is why the job silently disappears rather than failing - a very common source of "the rule is correct but the job never runs".

Use the MR-specific predefined variables:

review:
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "main"
    - when: never

$CI_MERGE_REQUEST_TARGET_BRANCH_NAME and $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME exist in merge request pipelines and merged-results pipelines. Note the difference in scope: $CI_COMMIT_BRANCH is defined in branch pipelines, $CI_COMMIT_TAG in tag pipelines, and $CI_COMMIT_REF_NAME is defined in both but holds the branch name in branch pipelines and the source branch name in MR pipelines - do not use it as a substitute for $CI_COMMIT_BRANCH in rules.

For merge trains and merged-results pipelines, also expect $CI_MERGE_REQUEST_EVENT_TYPE and a temporary merge ref; the target-branch variable still refers to the real target branch, which is what you want for gating.

3. Why does the fork's merge request produce no pipeline in the parent project, and would `DEPLOY_KEY` be available if it did?

Read the worked answer

For merge requests from forks, GitLab runs the pipeline in the fork project by default, using the fork's .gitlab-ci.yml and the fork's CI/CD variables. The parent project shows the MR but no pipeline of its own, which is what the maintainer is seeing. Running pipelines in the parent project is an explicit setting (Settings > CI/CD > "Run pipelines in the parent project for merge requests from a fork") and is off by default for good reason.

On the variable question: no. Fork merge request pipelines are treated as untrusted. Project-level variables from the parent project are not exposed to them, and even when the pipeline runs in the parent project, protected variables such as DEPLOY_KEY are not made available to fork-sourced pipelines, nor are protected runners. That is precisely the defence against an external contributor editing .gitlab-ci.yml in a fork and exfiltrating a deploy key by echoing it.

Recommended setup: run fork pipelines in the parent so cache and container registry are shared and results are visible, keep deploy jobs gated on $CI_PIPELINE_SOURCE == "merge_request_event" with environment: review only, use a manual approval job plus protected environments for anything touching production, and never give a review job access to production credentials - pass environment-scoped, non-protected review credentials at most.