# Reusable GitLab Includes and Components

![Reusable GitLab Includes and Components](/files/HCkGLnOztC2KZb1TaVUc)

> **Intro:** Shared pipeline logic is powerful because it eliminates drift. It is also risky because it creates a dependency chain that can silently change how dozens of pipelines behave. Treat reusable pipeline configuration the way you treat shared libraries: version it, review it, and pin it intentionally.
>
> **What this page includes**
>
> * how `include` and components fit into GitLab pipeline design
> * examples of reusable security scanner jobs
> * safer consumption patterns for platform-owned pipeline building blocks
> * comments on pinning, trust, secrets, and runner isolation
>
> **Working assumptions**
>
> * shared pipeline code should reduce duplication without hiding security logic from the teams that consume it

## Reuse options at a glance

| Mechanism           | Best use                         | Security note                                                        |
| ------------------- | -------------------------------- | -------------------------------------------------------------------- |
| `include:local`     | reuse within the same repo       | easiest to review in one MR                                          |
| `include:project`   | central platform-owned templates | protect the source project and ref                                   |
| `include:remote`    | public external YAML             | highest integrity risk; prefer pinned or internally mirrored sources |
| `include:template`  | GitLab-provided templates        | review before adopting blindly                                       |
| `include:component` | versioned reusable catalog items | pin to a specific version or SHA-like stable reference               |

## Example: local include for shared scanner jobs

Root `.gitlab-ci.yml`:

```yaml
include:
  - local: .gitlab/ci/security.yml

stages:
  - build
  - security
  - deploy
```

`.gitlab/ci/security.yml`:

```yaml
semgrep_scan:
  stage: security
  image: semgrep/semgrep:latest
  script:
    - semgrep scan --config p/default --json --output semgrep.json
  artifacts:
    paths: [semgrep.json]

bandit_scan:
  stage: security
  image: python:3.12-alpine
  script:
    - pip install bandit
    - bandit -r app -f json -o bandit.json
  artifacts:
    paths: [bandit.json]
```

Local include is simple and transparent. Use it first before building a central platform abstraction.

## Example: project include for a platform-managed gate

```yaml
include:
  - project: platform/ci-templates
    ref: v2.3.1
    file:
      - /security/common-gates.yml
      - /security/release-evidence.yml
```

Why it is useful:

* one team maintains common patterns centrally;
* consuming repos pin to an explicit version;
* upgrades can be tested and rolled out deliberately.

## Example: component include with inputs

```yaml
include:
  - component: $CI_SERVER_FQDN/platform/security-components/semgrep-gate@1.4.0
    inputs:
      stage: security
      config: p/default
      fail_on_severity: high
```

Components are useful when you want a reusable unit with parameters instead of a monolithic shared YAML file.

## Security review checklist for reused pipeline logic

Before consuming a shared include or component, check:

* where the source repo lives and who can change it;
* whether you pin a stable version;
* whether the included jobs request secrets, tokens, or privileged runners;
* whether the included jobs publish artifacts externally;
* whether any remote scripts or images are pulled at runtime;
* whether the component changes merge behavior, deploy behavior, or environment targeting.

## Example: a reusable Semgrep component contract

Consumer-side usage:

```yaml
include:
  - project: platform/security-components
    ref: v1.0.4
    file: /components/semgrep.yml

variables:
  SEMGREP_RULESET: "p/default"

semgrep_gate:
  extends: .platform_semgrep_gate
```

Platform-side component:

```yaml
.platform_semgrep_gate:
  stage: security
  image: semgrep/semgrep:1.84.0
  script:
    - semgrep scan --config "${SEMGREP_RULESET:-p/default}" --json --output semgrep.json
  artifacts:
    paths: [semgrep.json]
    expire_in: 14 days
```

This keeps the consumer YAML thin without making behavior mysterious.

## Conditional include example

```yaml
include:
  - local: .gitlab/ci/python-security.yml
    rules:
      - exists:
          - requirements.txt
          - pyproject.toml
```

This lets a monorepo or mixed-codebase project include only the relevant pipeline logic.

## Safe versioning guidance

Prefer:

* exact release tags for internal, trusted component projects;
* commit-SHA-style pinning when the source is especially sensitive;
* explicit upgrade MRs rather than silent drift.

Avoid:

* `latest`;
* remote includes from uncontrolled locations;
* hidden dependency changes that alter release or security semantics.

## Secret and token discipline

A shared component should not assume broad secret access.

Safer patterns:

* require inputs rather than hardcoding environment names;
* scope variables to protected refs and environments;
* keep deploy credentials outside generic scanner components;
* document required runner tags and environment expectations.

## Example: release evidence component pack

```yaml
include:
  - project: platform/security-components
    ref: v1.2.0
    file: /components/release-evidence.yml

release_evidence:
  extends: .platform_release_evidence
  variables:
    EVIDENCE_FILES: "semgrep.json,bandit.json,dependency-check-report.xml,zap-report.json"
```

The component can standardize packaging and evidence collection while each repo decides which reports to produce.

## Component governance model

A healthy ownership model usually includes:

* protected default and release branches in the component project;
* mandatory merge request approvals;
* signed commits or at least stricter provenance checks;
* changelog entries for user-facing behavior changes;
* a test project that validates the component before release.

## Cross-links

* [GitLab CI YAML Deep Dive](/devsecops-cicd-and-supply-chain/index-1/gitlab-ci-yaml-deep-dive.md)
* [Runner Isolation and Trust Boundaries](/devsecops-cicd-and-supply-chain/index-1/runner-isolation-and-trust-boundaries.md)
* [Gate Aggregation Scripts](/devsecops-cicd-and-supply-chain/index-1/gate-aggregation-scripts.md)
* [GitLab Release Evidence](/devsecops-cicd-and-supply-chain/index-1/gitlab-release-evidence.md)

![Footer](/files/fQNzMAKOWjRP989toSYF)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.product-security.expert/devsecops-cicd-and-supply-chain/index-1/reusable-gitlab-includes-and-components.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
