Diagrams in GitLab CI/CD
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.
- GitLab
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 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 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 shows. |
1. Check every merge request
Add the component to .gitlab-ci.yml:
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:
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 describes. Then add the component a second time in drift mode:
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:
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: 03. Write the diagrams again
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_BRANCHThe 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:
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 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:
include: - component: gitlab.com/plotwork/plotwork-component/plotwork@0.1.0 inputs: job-name: diagrams-drift mode: drift report-drift: true keyless: trueThe 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. 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 | The same check as a job of your own, on GitLab and every other CI |
| Diagrams as code | Sources, overrides, and the drift check |
| Keep diagrams in sync in CI | The GitHub Action |
| Diagrams in Azure Pipelines | The same task for Azure DevOps |
| Trusted publishers | Reporting drift with no key |
| Markdown and GitHub | What a sync writes, which GitLab shows the same way |
| Repository settings | Defaults for every header, and rules a merge request must pass |