Chapter 36Lesson 03~120 minutes

Compliance Pipelines, Pipeline Execution Policies, Governance, Audit Evidence, and Enterprise Controls: Configuration, Design Choices, and Tradeoffs

Choose central enforcement, reusable components, preventive or detective controls, and exception models using explicit trust and evidence tradeoffs.

Design tradeoffsPolicy scopeVariable controlMigration

Learning objectives

  • Choose between inject_policy and override_project_ci from ownership requirements.
  • Separate voluntary reuse from enforced configuration.
  • Design preventive and detective controls with measurable rollout evidence.
  • Model expiring waivers separately from raw policy scope.
  • Plan a compliance-pipeline migration without double enforcement.

Design rule: Governance strength is not proportional to centralization. Centralize the invariant that must not be removable, expose its origin, and leave harmless project choices local whenever they cannot weaken the control.

1. Four decisions, four different ownership boundaries

Before adding a policy, classify the need. Is it a non-negotiable invariant, reusable implementation, observation, or exception? That answer determines the proper layer.

Central enforcement vs autonomy

Enforce only controls that projects must not remove; leave ordinary build/test choices with teams.

Mandatory jobs vs reusable components

A component standardizes reuse by agreement. A policy enforces behavior even when the project would not opt in.

Preventive vs detective

Preventive controls stop later work; detective controls measure and retain evidence while allowing the pipeline to continue.

Permanent exclusion vs expiring waiver

A permanent exclusion becomes an alternate policy. Prefer owner, approver, reason, expiry, and reconciliation.

2. Choose pipeline strategy from the ownership model

Current pipeline execution policy documentation centers new designs on inject_policy and override_project_ci. The older inject_ci strategy is deprecated.

Strategy Configuration ownership Best fit Evidence/risk
inject_policy Project CI remains; policy CI is injected as isolated policy configuration. Mandatory gates while preserving project-owned build/test/deploy. Prove policy job origin, stage, collision handling, variable visibility, and policy ref.
override_project_ci Policy-controlled configuration defines the resulting pipeline; project CI is included deliberately if desired. Stronger organization control of the entire configuration surface. Higher coupling and blast radius; prove exact included project SHA/config path.
inject_ci Legacy injection behavior. Migration archaeology only. Deprecated; do not make it the new default.

3. Central enforcement versus project autonomy

Suppose every service must produce a governance proof but teams may choose pytest, Maven, Gradle, or another test stack. Put only the governance proof in policy. Application teams keep their test jobs. This minimizes the policy blast radius, keeps feedback local, and makes separation of duties understandable.

Central policy still has operational cost: one bad change can affect every linked descendant. Roll out to a small test scope first, protect the policy project default branch, require review, and retain a last-known-good policy ref.

4. Versioned reuse is not the same as enforcement

Question Reusable include/component Pipeline execution policy
Who chooses it? Project/template author. Policy owner and scope.
Can project remove it? Usually yes by editing project YAML. Not while the project remains in scope and the policy is active.
What to version? Component/include ref or digest. Policy project revision + referenced policy CI revision.
What proves use? Compiled YAML and project source SHA. Policy origin/scope plus effective job graph and pipeline evidence.
Rollback unit Project reference change. Reviewed policy revision/scope change with potentially wider blast radius.

5. Preventive and detective controls are complementary

Use a blocking .pipeline-policy-pre job when violating the invariant must prevent later work. Use a non-blocking detective job when you are measuring adoption, learning false-positive rates, or preparing a rollout.

policy:detect-duplicate-scan:
  stage: .pipeline-policy-pre
  allow_failure: true
  script:
    - ./detect-duplicate-scan.sh
  artifacts:
    when: always
    paths: [governance-evidence/duplicate-scan.json]

policy:required-governance-proof:
  stage: .pipeline-policy-pre
  allow_failure: false
  script:
    - ./verify-governance-proof.sh

Do not call a detective control “enforced” merely because the job exists. The observable state includes whether its failure blocks later execution.

6. A waiver is governed data, not a forgotten exclusion

A project exclusion in policy_scope is technical scope. It does not inherently encode the business lifecycle of a waiver. Store that lifecycle separately and reconcile it.

{
  "id": "EX-CH36-042",
  "project_id": 456,
  "control": "governance-proof",
  "owner": "service-owner@example.invalid",
  "approved_by": "governance@example.invalid",
  "reason": "temporary migration window",
  "created_at": "2026-09-13T00:00:00Z",
  "expires_at": "2026-09-20T00:00:00Z",
  "policy_version_requested_against": "ch36-policy-v1.0.0",
  "ticket": "SIM-CH36-42"
}

An expiry timestamp nobody reconciles is documentation, not enforcement. A production process should alert or fail when a record is expired but the technical exclusion still exists.

7. Variable precedence and protection are part of the control design

Pipeline execution policies can control whether user-defined variables influence policy jobs with variables_override. An allowlist model is easier to reason about than “allow everything except the few names we remembered.”

variables_override:
  allowed: false
  exceptions:
    - CH36_NON_SECRET_MODE

Secret rule: never store a credential value directly in the policy repository. Policy files are reviewable plaintext. Use an appropriate protected/external secret mechanism and prove only the minimum variable/provider path reaches the policy job.

8. Tier, offering, and trust prerequisites

Capability Current availability Trust prerequisite Mandatory free path
Pipeline execution policies Ultimate; GitLab.com, Self-Managed, Dedicated Authorized policy owners; linked policy project; readable referenced CI config or supported automatic access. Local simulator.
Security policy projects Ultimate Owner or custom policy-link permission; review/protected branch recommended. Local policy directory in Git.
Compliance frameworks Premium/Ultimate; policy enforcement can require Ultimate Top-level/group compliance governance. Synthetic framework/scope metadata.
Project/group audit events API Premium/Ultimate Appropriate role/API authentication; protect exports. Local evidence/audit JSON.
CI Lint API Free/Premium/Ultimate Project visibility/authentication as required. Local config inspection or optional disposable project.
Instance-wide policy management groups Ultimate on Self-Managed/Dedicated Administrator-level governance and separation of duties. Simulate central policy ownership only.

9. Migrate old compliance pipelines without double enforcement

Compliance pipelines are deprecated. Before migration, capture a representative old pipeline: source SHA, effective jobs, variable behavior, reports/artifacts, framework association, and evidence. Create the replacement pipeline execution policy in a narrow test scope. Compare old and new results, including duplicate jobs and exception behavior. Only then remove the old mechanism.

Do not run both mechanisms broadly and call duplication “defense in depth.” GitLab explicitly warns that mixing them can cause duplicated jobs, failures, or missing checks.

10. Worked decision: one control across four teams

Decision Choice Reason Observable proof
Enforcement inject_policy pre-job Only the compliance invariant must be centralized. Policy ref + policy job in every in-scope pipeline.
Implementation Central policy-ci.yml pinned by ref One reviewable implementation; origin remains visible. Referenced project/file/ref + content digest.
Rollout Detective for 48h, then blocking Measure false positives and queue cost first. Report counts, then reviewed policy change.
Legacy service Two-week waiver with temporary scope exclusion Exception has owner/reason/expiry instead of hidden bypass. Exception record + scope diff + reconciliation.
Runners Keep team runners unless the control requires a trusted pool Avoid unnecessary central execution coupling. Runner ID/tags/protection/executor in policy job evidence.

11. Rollback restores a known-good policy state and preserves history

Rollback through a reviewed policy change that restores the last known-good policy/CI ref or disables/narrows the broken policy. Preserve failed pipelines and audit evidence. Deleting the bad history destroys the data needed to explain the incident.

Next lesson

Next: Compliance Pipelines, Pipeline Execution Policies, Governance, Audit Evidence, and Enterprise Controls: Diagnostics, Failure Modes, Security, and Performance

Diagnose overrides, duplicate scans, unmanaged waivers, variable leaks, and missing source-to-audit correlation.

Knowledge check

What must be recorded before claiming that a policy governed a project pipeline?

A project pipeline is green, but the expected enforced job is absent. Which layer should you inspect first?

Why should an exception have an owner, reason, scope, and expiry?

Version and compatibility note

GitLab and GitLab Runner evolve continuously. Treat version-sensitive YAML, runner/executor behavior, APIs, security features, policy controls, tiers, and deprecations as assumptions to verify against the current official GitLab documentation before production use. Preserve the exact project/ref/SHA, compiled configuration, pipeline/job IDs, runner/tool versions, and external target evidence used for any reproducible lab or incident record.

Official references and version notes

Further reading — current official GitLab sources

Behavior and tier assumptions in this chapter were checked against the current documentation on 2026-09-13. Re-check these pages before applying the optional enterprise path because policy schemas and product tiers evolve.

Current assumptions used in this chapter: Version-sensitive YAML, Runner/executor behavior, APIs, security features, policy controls, tiers, and deprecations must be verified against the exact GitLab, GitLab Runner, tool, and external-system versions used in production. Preserve the exact project/ref/SHA, compiled configuration, pipeline/job IDs, runner/tool versions, and external target evidence used for reproducible work.

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this address.