# Command line in CI

> Page: https://docs.plotwork.dev/cli/ci. Index of every page: https://docs.plotwork.dev/llms.txt

The pipeline step that fails a build when a diagram picture is stale or a generated diagram has drifted, for GitHub Actions, GitLab CI, Azure Pipelines, Jenkins, and CircleCI. Each runs the pinned release with `npx`, so the job installs nothing beyond Node 22.

## TL;DR

| Question | Answer |
|---|---|
| Which check do I run? | `sync --check` for the pictures under diagram fences. Add `generate --check` when diagrams are made from Terraform, OpenAPI or other files, and `check` when the repository has style rules. |
| What fails the job? | Exit code 1 for a problem in a diagram, 2 for a mistake in the command. Both fail a step in every CI system. |
| Does it need a key or a token? | No. Only `check --org` reads a key, from `PLOTWORK_API_KEY`. |
| Does it send my diagrams anywhere? | No. The check reads the checked-out files and writes nothing. |
| On GitHub, should I use this or the Action? | Either. The [GitHub Action](https://docs.plotwork.dev/diagrams-in-ci.md) runs the same engine without Node and adds a job summary. The command line is the same step on every other CI. |
| How do I fix a failure? | Run `npx -y @buun_group/plotwork@0.1.0 sync` on the same files, then commit the Markdown and the SVGs it wrote. |

Every sample pins the release. Move the pin in a change you review, and run `sync` in the same change, so the pictures are drawn by the release the check runs.

## The commands

| Step | Command | Fails when |
|---|---|---|
| Pictures | `npx -y @buun_group/plotwork@0.1.0 sync --check "**/*.md"` | A picture is missing or stale, or a diagram has a mistake |
| Generated diagrams | `npx -y @buun_group/plotwork@0.1.0 generate --check` | A diagram drifted from the files it is made from |
| Style rules | `npx -y @buun_group/plotwork@0.1.0 check "**/*.md"` | A rule at level error is broken |

`generate --check` exits 2 when the settings have no `sources`, so add its step only to a repository that makes diagrams from files. `check` exits 2 when there are no rules, in the same way.

`"**/*.md"` never looks in `node_modules`, `.git`, or build output. Narrow it to the folders that hold diagrams, such as `README.md "docs/**/*.md"`, on a large repository.

`generate --check --since <ref>` checks only the sources whose files changed since that ref, which keeps a large repository's check short. The job needs the history up to the ref: fetch it in the checkout step.

## GitHub Actions

```yaml
name: diagrams

on:
  pull_request:
    paths: ['**/*.md', '**/*.diagram', 'plotwork.config.json']

permissions:
  contents: read

jobs:
  diagrams:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
        with:
          persist-credentials: false
      - uses: actions/setup-node@v6
        with:
          node-version: 22
      - run: npx -y @buun_group/plotwork@0.1.0 sync --check --format github "**/*.md"
```

`--format github` prints each stale fence and each mistake as an annotation on its line of the pull request. To report drift to code scanning, add a step that runs `generate --check --format sarif --out plotwork.sarif` with `if: always()`, then uploads the file with `github/codeql-action/upload-sarif`.

## GitLab CI

```yaml
diagrams:
  image: node:22
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
  script:
    - npx -y @buun_group/plotwork@0.1.0 sync --check "**/*.md"
    - npx -y @buun_group/plotwork@0.1.0 generate --check --format junit --out plotwork-junit.xml
  artifacts:
    when: always
    reports:
      junit: plotwork-junit.xml
```

The JUnit report shows each generated diagram as a test in the merge request, failed when it drifted.

## Azure Pipelines

```yaml
trigger: none
pr:
  branches:
    include: [main]

pool:
  vmImage: ubuntu-latest

steps:
  - task: NodeTool@0
    inputs:
      versionSpec: '22.x'
  - script: npx -y @buun_group/plotwork@0.1.0 sync --check "**/*.md"
    displayName: Diagram pictures are current
  - script: npx -y @buun_group/plotwork@0.1.0 generate --check --format junit --out $(Build.ArtifactStagingDirectory)/plotwork-junit.xml
    displayName: Generated diagrams have not drifted
  - task: PublishTestResults@2
    condition: always()
    inputs:
      testResultsFormat: JUnit
      testResultsFiles: $(Build.ArtifactStagingDirectory)/plotwork-junit.xml
```

## Jenkins

```groovy
pipeline {
  agent { docker { image 'node:22' } }
  stages {
    stage('Diagrams') {
      steps {
        sh 'npx -y @buun_group/plotwork@0.1.0 sync --check "**/*.md"'
        sh 'npx -y @buun_group/plotwork@0.1.0 generate --check --format junit --out plotwork-junit.xml'
      }
    }
  }
  post {
    always {
      junit allowEmptyResults: true, testResults: 'plotwork-junit.xml'
    }
  }
}
```

## CircleCI

```yaml
version: 2.1

jobs:
  diagrams:
    docker:
      - image: cimg/node:22.20.0
    steps:
      - checkout
      - run: npx -y @buun_group/plotwork@0.1.0 sync --check "**/*.md"
      - run: mkdir -p reports && npx -y @buun_group/plotwork@0.1.0 generate --check --format junit --out reports/plotwork-junit.xml
      - store_test_results:
          path: reports

workflows:
  diagrams:
    jobs:
      - diagrams
```

## Other CI systems

Any system that runs a command and reads its exit code runs the check: install Node 22, then run the command. Exit code 0 passes; 1 and 2 fail. For a runner with no access to the npm registry, mirror the package into your own registry or cache, as you would any other dependency. It is one file with no dependencies to fetch, and the checks make no request.

## See also

| Doc | Why |
|---|---|
| [Keep diagrams in sync in CI](https://docs.plotwork.dev/diagrams-in-ci.md) | The GitHub Action, its inputs, and opening a pull request with the redrawn pictures |
| [Diagrams as code](https://docs.plotwork.dev/diagrams-as-code.md) | Sources, overrides, and the drift check |
| [Exit codes and output formats](https://docs.plotwork.dev/cli/exit-codes-and-output.md) | What `github`, `json`, `sarif`, and `junit` print |
| [Enterprise rollout](https://docs.plotwork.dev/enterprise-rollout.md) | Reusable workflows, required checks, and air-gapped runners |
