Configurable fallback behavior for Pipeline Execution Policies

Release notes

Pipeline Execution Policies now support configurable empty pipeline behavior to prevent duplicate pipelines. The new empty_pipeline_behavior option allows policy authors to control when policies apply to empty pipelines, enabling broad adoption across large organizations without requiring opinionated workflow:rules that conflict with project configurations.

Problem to solve

Pipeline Execution Policies with pipeline_config_strategy:inject_policy need to be more adaptive to support broad adoption in large organizations. The existing fallback strategy for empty pipelines inevitably results in duplicate branch and merge request pipelines on merge requests, regardless of which pipeline source the project prefers to use with their merge requests.

The problematic interaction can be summarized as follows:

  • On push to the source branch of a merge request, GitLab attempts several pipeline creations, relying on pipeline workflow:rules and rules for deduplication:
    • 1 branch push pipeline
    • N merge request pipelines (one for each open MR with the branch as its source)
  • PEPs without opinionated rules always apply to a pipeline, even if it's empty, and regardless of the source. As a result, even properly configured projects end up with two pipelines.
  • PEPs with opinionated rules can avoid the duplicate pipeline problem but only if every affected project aligns with their rules. Otherwise, they still get duplicate pipelines.

Proposal

First, observe that:

  1. PEPs with opinionated workflow:rules/rules are bad for large scale adoption. As our goal is to not be opinionated about project configuration, the recommendation for PEPs should be as adaptive as possible.
  2. In the absence of opinionated workflow:rules/rules, the duplication is caused by what is internally referred to as the fallback config source.

The implemented solution makes the fallback behavior configurable by allowing pipeline_config_strategy to be an object with an empty_pipeline_behavior option that specifies what should happen when the project pipeline would have been empty:

pipeline_config_strategy: 
  type: inject_policy
  empty_pipeline_behavior: always_apply | apply_if_no_config | never_apply

The empty_pipeline_behavior option has the following possible values:

  • always_apply: Current default. Always applies policies to empty pipelines.
  • apply_if_no_config: Only applies when the project has no CI config. For projects with CI config, only applies if the project creates a pipeline (requires "Pipelines must succeed" setting to ensure PEPs run).
  • never_apply: Never applies policies to empty pipelines. Projects fully control when CI runs.

Backward compatibility: The pipeline_config_strategy field accepts either a string (for backward compatibility) or an object with type and empty_pipeline_behavior fields. When using the string format, the default empty_pipeline_behavior is always_apply.

Multiple policies: When multiple policies have different empty_pipeline_behavior settings, the most restrictive setting applies (always_apply > apply_if_no_config > never_apply). "Restrictive" means most limiting to project freedom.

Example configuration

# .gitlab/security-policies/policy.yml
---
pipeline_execution_policy:
- name: Enforce SAST on created pipelines
  description: ''
  enabled: true
  pipeline_config_strategy: 
    type: inject_policy
    empty_pipeline_behavior: apply_if_no_config
  content:
    include:
    - project: pep-sast/pep-sast-security-policy-project
      file: .gitlab/ci/sast.yml
  skip_ci:
    allowed: false
  variables_override:
    allowed: false
    exceptions: []

Intended users

Feature Usage Metrics

Track usage through:

  • Count of Pipeline Execution Policies using each empty_pipeline_behavior value (always_apply, apply_if_no_config, never_apply)
  • Number of pipelines created via policy fallback, segmented by empty_pipeline_behavior option
  • Reduction in duplicate pipeline creation after switching from always_apply to apply_if_no_config

Does this feature require an audit event?

No. Changes to Pipeline Execution Policy configuration are already captured in existing policy audit events.

Edited by Hordur Freyr Yngvason