Skip to content

Latest commit

 

History

33 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@miragon/bpmnlint-plugin-rules

npm version CI License: MIT

A bpmnlint plugin that keeps BPMN diagrams clean: a few Miragon naming and layout conventions, plus the standard structural rules and the Camunda 7 / 8 deployability rules bundled in — so you don't wire up bpmnlint's plugins yourself.

Why

A BPMN diagram can be well-formed and still be wrong — a missing start event, a construct the engine rejects at deploy, or forty tasks named Activity_0049ryx that no reviewer can read. Linting catches that automatically, wherever BPMN is written:

  • In the modeler — live feedback while you draw, so a mistake is flagged the moment you make it.
  • In CI — a merge/deploy gate, so a broken model never ships.
  • For AI — agents emit valid-but-off models (machine IDs, orphan nodes, engine-invalid constructs); lint their output and block on error, instead of hoping a human catches it.

Most teams already have these conventions — in a wiki, or in one reviewer's head. This plugin makes them executable.

Install

Install the plugin together with bpmnlint (its peer dependency):

npm install --save-dev @miragon/bpmnlint-plugin-rules bpmnlint

Use it (the bpmnlint way)

Add the plugin to your .bpmnlintrc and extend one of its configs, like any other plugin:

// .bpmnlintrc
{
  "extends": [
    "bpmnlint:recommended", // standard structural rules
    "plugin:@miragon/rules/recommended-for-<scope>", // the Miragon layer — pick a scope below
    // "plugin:camunda-compat/camunda-cloud-8-10", // optional: Camunda engine rules — see below
  ],
}

It ships three configs — pick one by who's modeling and why:

  • plugin:@miragon/rules/recommended-for-modeling — for purely business/technical models, and for modeler applications that surface linting to their users. Layout hints only: bpmnlint's standard-size and the layout rules at warn, the naming/id rules off — a modeler is never blocked on execution-only conventions.
  • plugin:@miragon/rules/recommended-for-automation — for developers automating processes, locally and in CI, on models wired up to a Camunda engine. Every Miragon rule on but as a non-blocking warn (standard-size too), so ids and layout get flagged without failing the build.
  • plugin:@miragon/rules/all — every Miragon rule at error, engine-agnostic. The strict gate to opt into when you want findings to fail the build.

Then lint a diagram:

npx bpmnlint diagram.bpmn

Rules

The Miragon conventions this plugin adds — each with a docs page and a good/bad example:

Rule What it catches
@miragon/rules/no-generated-ids IDs generated rather than chosen (Activity_0049ryx, StartEvent_1)
@miragon/rules/element-id-naming IDs that don't follow the type-prefix + case convention
@miragon/rules/flow-through-element A sequence flow routed through an unrelated shape's body
@miragon/rules/flow-connection-side A sequence flow docked onto the wrong side of a shape
@miragon/rules/flow-target-alignment A flow's target drawn off the row, sloping the main path
@miragon/rules/flow-crossing Two sequence flows whose drawn paths cross each other
@miragon/rules/flow-orthogonal A sequence flow that runs diagonally instead of horizontal and vertical

Turn any of them on individually, the usual way:

{
  "extends": ["bpmnlint:recommended", "plugin:@miragon/rules/recommended-for-modeling"],
  "rules": {
    "@miragon/rules/no-generated-ids": "error",
    "@miragon/rules/element-id-naming": "warn",
  },
}

Structural checks — start/end events, connectivity, element sizing — come from bpmnlint's own bpmnlint:recommended. The Miragon set grows over time; see CONTRIBUTING.md to propose a rule.

In CI

Lint every model as a merge gate — bpmnlint exits non-zero on a finding, failing the build:

npx bpmnlint 'models/**/*.bpmn'

Camunda engine rules

Deploying to a Camunda engine? Add its deployability layer (bundled — no separate install) to your extends. These rules read engine-specific properties, so bpmnlint must also parse them with the matching moddle extension — pick the config for your engine below.

The moddleExtensions line is not optional. Without it the parser doesn't recognize the engine namespace, so those properties are invisible to the rules — they then report false findings (for example a service task flagged as missing its task definition even though it has one). A modeler loads the moddle already; it's the bare npx bpmnlint CLI that needs this line. Prefer to skip the wiring? The programmatic getDefaultLintConfig({ engine }) below sets up both the layer and its moddle extension for you.

Camunda 7

// .bpmnlintrc
{
  "extends": [
    "bpmnlint:recommended",
    "plugin:@miragon/rules/recommended-for-automation",
    "plugin:camunda-compat/camunda-platform-7-24",
  ],
  "moddleExtensions": { "camunda": "camunda-bpmn-moddle/resources/camunda.json" },
}

Camunda 8 (Zeebe)

// .bpmnlintrc
{
  "extends": [
    "bpmnlint:recommended",
    "plugin:@miragon/rules/recommended-for-automation",
    "plugin:camunda-compat/camunda-cloud-8-10",
  ],
  "moddleExtensions": { "zeebe": "zeebe-bpmn-moddle/resources/zeebe.json" },
}

Programmatic use

Building a linter in code — a modeler, a CI script, an agent loop? Skip .bpmnlintrc and use the bundled resolver. It carries every layer (structural + Camunda + Miragon), so there's nothing else to wire up, and it works offline:

import BpmnModdle from 'bpmn-moddle';
import Linter from 'bpmnlint/lib/linter';
import { createBundledResolver, getDefaultLintConfig } from '@miragon/bpmnlint-plugin-rules';

const { rootElement } = await new BpmnModdle().fromXML(xml);

const linter = new Linter({
  config: getDefaultLintConfig({ engine: 'c8' }), // 'c7' | 'c8' — omit for structural-only
  resolver: createBundledResolver(),
});

const results = await linter.lint(rootElement);

engine picks the Camunda deployability layer + typed moddle; preset picks the Miragon opinion layer independently — 'modeling' (layout hints only, safe on hand-drawn diagrams) or 'automation' (every Miragon rule at error). When preset is omitted it defaults to 'automation' for an engine-bound config and 'modeling' otherwise. Pass both to decouple them — e.g. a modeler that wants Camunda 8's typed properties and deployability checks but the relaxed modeling opinion layer:

getDefaultLintConfig({ engine: 'c8', preset: 'modeling' });

Results are keyed by rule; each finding has a category (error | warn). Block on any error — a CI gate, or the reject signal that sends an AI agent back to fix its output:

const errors = Object.values(results)
  .flat()
  .filter((finding) => finding.category === 'error');

if (errors.length) process.exit(1);

Every rule factory, rule-set and helper is exported from the package root as well.

Alternatives

bpmnlint lints one model at a time, so it is the right fit for anything stylistic or about the correctness of a single diagram. It checks naming conventions, layout, structural soundness, and whether a construct is deployable to a given engine.

However, it cannot answer engine- and automation-specific questions that span a running process, because those depend on more than the diagram in front of it. Whether a call activity passes every variable its child process needs, or whether the technical wiring is correct, is something a model-in-isolation linter simply cannot see. For those cases, and when you want to keep such tests alongside your model in the same build (for example a Gradle task), Miragon/bpmn-to-code and its process testing are the better tool.

Where it is used

  • Miragon BPMN Modeler — in-editor linting via the programmatic API, flagging issues live while you model.

Contributing

See CONTRIBUTING.md.

License

MIT © Miragon GmbH.

About

Keep BPMN models clean and consistent — a bpmnlint plugin that guards diagram quality in the modeler, in CI, and as a guardrail for AI-generated BPMN ✅

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages