# Diagrams in GitLab CI/CD

> Page: https://docs.plotwork.dev/diagrams-in-gitlab-ci. Index of every page: https://docs.plotwork.dev/llms.txt

How to fail a merge request whose diagram pictures are stale, or whose diagrams made from files have drifted, with the Plotwork CI/CD component for GitLab. It is for anyone who keeps Plotwork diagrams in a GitLab project.

## TL;DR

| Question | Answer |
|---|---|
| What is the component? | `gitlab.com/plotwork/plotwork-component/plotwork`, in the GitLab CI/CD catalog. One include adds one job. |
| Is it released? | Not yet. The include below names its first version, `0.1.0`, which the catalog lists once it is released. Until then, run the command line in a job of your own, as [CI usage](https://docs.plotwork.dev/cli/ci.md#gitlab-ci) shows. |
| What does the job run? | The pinned release of the command line, `npx -y @buun_group/plotwork@0.3.0`, in the image `node:22`. It is the same check you run on your machine. |
| Which modes are there? | `check` fails on a stale picture under a `diagram` fence. `drift` fails when a diagram made from files differs from what its files make now. `generate` writes the diagrams again and keeps a patch in the job's artifacts. |
| How does a drift show in a merge request? | As a failed test in the merge request's test report, one test per generated diagram. |
| Does it need a key? | No. Only `report-drift` signs in to Plotwork: with an organisation key in the masked CI/CD variable `PLOTWORK_API_KEY`, or with no key at all through a [trusted publisher](https://docs.plotwork.dev/trusted-publishers.md#7-gitlab-cicd) and `keyless: true`. |
| Does it send my files anywhere? | No. The command line reads the checkout and makes no request. `report-drift` sends a run's metadata, never a diagram or a file. |
| What if I cannot use the catalog? | Run the command line in a job of your own, as [CI usage](https://docs.plotwork.dev/cli/ci.md#gitlab-ci) shows. |

## 1. Check every merge request

Add the component to `.gitlab-ci.yml`:

```yaml
include:
  - component: gitlab.com/plotwork/plotwork-component/plotwork@0.1.0
    inputs:
      paths: 'README.md docs/**/*.md'

plotwork-diagrams:
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
```

The job is named by the input `job-name`, `plotwork-diagrams` by default, so a job of that name in your own file adds `rules`, `tags`, or `needs` to it. Without `rules`, the job runs in every pipeline.

A stale picture fails the job, and the log names the file and the line of the fence:

```text
stale: docs/architecture.md needs sync
  line 3: This diagram has no picture under it.
```

To fix it, run `npx -y @buun_group/plotwork@0.3.0 sync` on the same files and commit the Markdown and the SVGs it writes.

## 2. Fail a merge request on drift

When diagrams are made from Terraform, OpenAPI, Compose and other files, name them in `sources` of `plotwork.config.json`, as [Diagrams as code](https://docs.plotwork.dev/diagrams-as-code.md) describes. Then add the component a second time in `drift` mode:

```yaml
include:
  - component: gitlab.com/plotwork/plotwork-component/plotwork@0.1.0
    inputs:
      job-name: diagrams-drift
      mode: drift

diagrams-drift:
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
```

The job writes `.plotwork/junit.xml` and hands it to GitLab as a test report, so each generated diagram is a test in the merge request, failed when it drifted. The log names each change, such as `Added 1 node (logs)`.

On a large project, check only the sources whose files changed on the branch:

```yaml
include:
  - component: gitlab.com/plotwork/plotwork-component/plotwork@0.1.0
    inputs:
      job-name: diagrams-drift
      mode: drift
      since: origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME

diagrams-drift:
  variables:
    GIT_DEPTH: 0
```

## 3. Write the diagrams again

```yaml
include:
  - component: gitlab.com/plotwork/plotwork-component/plotwork@0.1.0
    inputs:
      job-name: diagrams-generate
      mode: generate

diagrams-generate:
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
```

The job makes every diagram again in its workspace and keeps `.plotwork/plotwork.patch` in its artifacts for a week. Download it, run `git apply plotwork.patch`, and commit. The component holds no token and pushes nothing; a later job of your own can commit the patch with a project access token.

## 4. Send drift runs to the dashboard

An organisation on a plan with the drift dashboard can see every project's drift in one place. Make an organisation API key in the portal, add it to the project (or the group) as the CI/CD variable `PLOTWORK_API_KEY`, masked and protected, and set `report-drift`:

```yaml
include:
  - component: gitlab.com/plotwork/plotwork-component/plotwork@0.1.0
    inputs:
      job-name: diagrams-drift
      mode: drift
      report-drift: true
```

| What is sent | What is never sent |
|---|---|
| The project path, the ref, the commit, the pipeline source, the job and merge request links | A diagram, a file, or a name of what changed |
| Per source: its name, out path, status, counts of what was added, removed, and changed, errors, and CODEOWNERS owners | The key, which GitLab masks in the log |

A refusal, such as a plan with no dashboard, is a line in the log and fails nothing. A protected variable reaches only protected branches and tags, so a merge request pipeline from another branch sends nothing unless the variable is unprotected.

The dashboard names a repository as `group/project`. A project in a subgroup, such as `acme/platform/web`, is not sent yet, and the log says so.

### With no key

A [trusted publisher](https://docs.plotwork.dev/trusted-publishers.md#7-gitlab-cicd) lets the job report with no key in the project. An owner or admin adds the project under Keys and CI, CI/CD, Add GitLab, then the include sets `keyless`:

```yaml
include:
  - component: gitlab.com/plotwork/plotwork-component/plotwork@0.1.0
    inputs:
      job-name: diagrams-drift
      mode: drift
      report-drift: true
      keyless: true
```

The job asks GitLab for an ID token with `api-url` as its audience, swaps it at the API for a token that lives 15 minutes, and sends the run with it. The ID token is taken out of the job's environment before the command line runs, and neither token is printed. A `PLOTWORK_API_KEY` that is set still wins. A refused swap is a line in the log and fails nothing.

## 5. Inputs

| Input | Default | Meaning |
|---|---|---|
| `job-name` | `plotwork-diagrams` | The name of the job. |
| `stage` | `test` | The stage the job runs in. |
| `mode` | `check` | `check`, `generate`, or `drift`. |
| `paths` | `**/*.md` | `check` only: the Markdown files, separated by spaces, as globs, files, or folders. |
| `config` | empty | The [settings file](https://docs.plotwork.dev/repository-settings.md). Empty finds `plotwork.config.json`, then `.plotwork/config.json`. |
| `working-directory` | `.` | The folder to run in. |
| `since` | empty | `drift` only: a git ref; only the sources whose files changed since it are checked. |
| `report-drift` | `false` | `drift` only: send the run's metadata to the drift dashboard with `PLOTWORK_API_KEY`, or with no key when `keyless` is on. |
| `keyless` | `false` | Sign in with the job's GitLab ID token through a trusted publisher when there is no `PLOTWORK_API_KEY`. The job always declares the ID token `PLOTWORK_ID_TOKEN`; with `keyless: false` it is removed from the environment unread. |
| `organization` | empty | The organisation to report to. Empty is the organisation of the key. |
| `api-url` | `https://api.plotwork.dev` | The Plotwork API that `report-drift` sends to, and the ID token's audience. Write its origin with no path or trailing slash. |
| `cli-version` | the release the component was tested with | The release of `@buun_group/plotwork` the job runs. |
| `image` | `node:22` | The image: Node 22 or later, `npx`, `git`, and a POSIX shell. |

The job keeps `.plotwork/` as artifacts, on failure too: `junit.xml` (drift), `report.json` (drift with `report-drift`), and `plotwork.patch` (generate).

## 6. Versions and runners

Pin the component to a release, such as `@0.1.0`, and move the pin in a change you review. Each release of the component pins a stable release of the command line in `cli-version`, so a new release of either never changes your pictures by itself. To try a newer command line before the component moves, set `cli-version`, run `sync` with that release on your machine, and commit the pictures in the same change.

The job needs a runner that runs a container image (the Docker or Kubernetes executor) and can reach the npm registry. For a runner with no access to the registry, point npm at your own mirror with the CI/CD variable `NPM_CONFIG_REGISTRY`, and set `image` to an image of your registry.

## See also

| Page | Why |
|---|---|
| [CI usage](https://docs.plotwork.dev/cli/ci.md) | The same check as a job of your own, on GitLab and every other CI |
| [Diagrams as code](https://docs.plotwork.dev/diagrams-as-code.md) | Sources, overrides, and the drift check |
| [Keep diagrams in sync in CI](https://docs.plotwork.dev/diagrams-in-ci.md) | The GitHub Action |
| [Diagrams in Azure Pipelines](https://docs.plotwork.dev/diagrams-in-azure-pipelines.md) | The same task for Azure DevOps |
| [Trusted publishers](https://docs.plotwork.dev/trusted-publishers.md#7-gitlab-cicd) | Reporting drift with no key |
| [Markdown and GitHub](https://docs.plotwork.dev/markdown-and-github.md) | What a sync writes, which GitLab shows the same way |
| [Repository settings](https://docs.plotwork.dev/repository-settings.md) | Defaults for every header, and rules a merge request must pass |
