PEP Scoped Implicit Merge Check
Problem Statement
When Pipeline Execution Policies inject security scans into merge request pipelines, customers with existing branch pipelines end up with duplicate pipelines. The current mergeability check only evaluates the MR pipeline (with security scans), ignoring the branch pipeline where functional tests may be failing, allowing broken code to be merged
See https://gitlab.com/gitlab-com/account-management/emea/natwest/natwest-dedicated-collaboration/-/work_items/608 and https://docs.google.com/document/d/1MxGxqukTG1EierhtIuzN-Avkdrjt5FGMAMfvVIqBDUc/edit?tab=t.0 for specific customer impact
Proposal
Introduce a PEP/SEP-specific merge check that activates when Pipeline Execution Policies or Scan Execution Policies have injected jobs into the pipeline for the latest commit on the merge request, requiring both branch and merge request pipelines to succeed before allowing merge. This approach creates a separate, independent check from CI status, giving Security policies more power and flexibility while avoiding the introduction of new user-facing settings.
Important: This check activates regardless of the "Pipelines must succeed" setting. The setting only affects enforcement behavior (hard block vs. warning).
How It Works
Trigger Condition:
The merge check activates when ALL of the following are true:
- Project has Pipeline Execution Policies or Scan Execution Policies configured and enabled
- At least one pipeline exists for the latest commit on the merge request
- A branch pipeline exist and PEP jobs were injected into the MR pipeline for the latest commit on the merge request
Behavior:
- Introduce a new merge check: "Security Policy Pipeline Check"
- This check is separate from and independent of the existing "Pipelines must succeed" CI status check
- Merge check waits for pipelines only if they're in non-terminal state (running, pending, created)
- Once pipelines are complete (terminal state), evaluates their results
- The merge check evaluates:
- Latest branch pipeline status (push source)
- Latest merge request pipeline status (merge_request_event source)
- This check applies to both manual merge and auto-merge
- Note on pipeline configurations:
- Works with a single pipeline (branch OR MR only)
- Works with duplicate pipelines (branch AND MR)
Pipeline Source Grouping:
Pipelines are grouped into two categories:
-
MR pipelines: Any pipeline with a merge request ID
- Source: merge_request_event
-
Branch pipelines: All other CI pipelines, including:
- Push pipelines (source: push)
- Web-triggered pipelines (source: web)
- API-triggered pipelines (source: api)
- Scheduled pipelines (source: schedule)
The check evaluates the latest MR pipeline and latest branch pipeline (regardless of which specific source triggered the branch pipeline).
Important: External commit statuses published via the Commit Status API are NOT GitLab pipelines and are not included in this check
When NOT to apply:
- Projects without Pipeline Execution Policies/Scan Execution Policies and/or
- PEP/SEP is configured BUT no jobs were injected into any pipeline for the latest commit (e.g., PEP rules didn't match this branch/MR) and/or
- No pipelines exist for the latest commit
User Experience (Proposed)
When "Pipelines Must Succeed" is DISABLED
Soft block with warning modal:
- PEP check evaluates pipelines
- If any pipeline fails, warning modal appears when user attempts to merge
- User can choose to merge despite failures
For Users WITH PEP/SEP:
Automatic behavior: both (branch pipelines and merge request pipeline) must succeed
If "Pipelines must succeed" is ENABLED:
- PEP check evaluates pipelines
- PEP check blocks the merge button
- Cannot merge until all evaluated pipelines pass
If "Pipelines must succeed" is DISABLED:
- PEP check evaluates pipelines
- If any pipeline fails, warning modal appears when user attempts to merge
- User can choose to merge despite failures
Visible in the merge request widget as a Security Policy Pipeline Merge Check Status
No settings to configure
If they need jobs to fail but still merge: Use allow_failure: true in job config
For Users WITHOUT PEP/SEP:
- No change to current behavior
- Check never applied
- No impact