Skip to content

Importing Spectral results

If your team already lints OpenAPI documents with Spectral, thymian report convert imports those results into Thymian reporting: Spectral findings become first-class Thymian findings that render, format, and gate CI exactly like native lint results.

Use it when you have existing Spectral output and want it in the Thymian pipeline:

  • you are migrating from Spectral and want both result sets in one report format
  • your CI already runs Spectral and you want Thymian’s formatters (markdown, CSV, JSON) and exit-code gating on those results
  • you want Spectral findings mapped onto the endpoints of your API description
  • The Spectral CLI and a Spectral ruleset (.spectral.yaml) — or an already-generated Spectral JSON report
  • Optionally, the OpenAPI description Spectral linted, for endpoint mapping

The converter accepts exactly one format: the JSON array produced by Spectral’s json formatter (spectral lint -f json). Each result carries code, message, severity (0–3), path, and range, plus source and documentationUrl when Spectral knows them.

Spectral’s other output formats — stylish, text, JUnit, SARIF, and friends — are not supported. Re-run Spectral with -f json if you have something else.

Run Spectral as usual, choosing the JSON formatter and writing to a file. Spectral needs a ruleset (.spectral.yaml, e.g. extends: ["spectral:oas"]) next to your project:

Terminal window
npx @stoplight/spectral-cli lint -f json -o report.json api.yaml

This happens entirely outside Thymian — in CI, keep your existing Spectral step and just persist the JSON output. Note that spectral lint itself exits non-zero when it finds error-severity problems: let that step continue (for example with continue-on-error or || true) so the Thymian conversion in the next step performs the gating.

Pass the report as a typed input. The <type>:<location> syntax splits on the first colon, so locations may themselves contain colons (URLs, Windows paths); bare paths without a type are rejected:

Terminal window
npx thymian report convert --report spectral:./report.json --spec openapi:./api.yaml

The --spec input is optional. When you provide it, Thymian loads the API description and maps findings onto its endpoints where possible; findings it cannot map keep their file locations from the Spectral report.

The converted report renders like any other Thymian report. Rule ids are namespaced spectral/<code> so they never collide with Thymian rules, and each finding keeps its Spectral message, severity, and source location:

Terminal window
@thymian/plugin-spectral · lint · ──────────────────────────────────────────────
api.yaml:2:6
⚠ warn: Info object must have "contact" object.
› spectral/info-contact
⚠ warn: Info "description" must be present and non-empty string.
› spectral/info-description
Summary: 0 errors, 2 warnings, 0 hints, 0 infos.

Severities map one-to-one: Spectral 0/1/2/3 become error/warn/info/hint. Group headings show the finding’s source exactly as Spectral emitted it — typically an absolute path (shortened to api.yaml above for readability).

Exit codes follow the same policy as every Thymian workflow, applied to the converted findings:

  • 1 — the converted report contains failed findings (even though the conversion itself succeeded)
  • 0 — the converted report is clean
  • 2 — usage or tool error: the report file is missing or malformed, or a --report type no installed plugin claims

Severity never affects the exit code: a converted report containing only warnings or hints still exits 1, because every Spectral finding is a failed execution.

An unclaimed type fails fast before anything renders, naming the input — and, when other inputs in the same run were claimed, listing the supported report types.

Step 5: Save the inputs in your configuration file

Section titled “Step 5: Save the inputs in your configuration file”

Both inputs can live in thymian.config.yaml instead of flags, mirroring how specifications works:

reports:
- type: spectral
location: ./report.json
specifications:
- type: openapi
location: ./api.yaml
plugins:
'@thymian/plugin-openapi': {}
'@thymian/plugin-spectral': {}
'@thymian/plugin-reporter':
options:
formatters:
markdown: {}

With that in place, a bare npx thymian report convert does the same conversion. When starting a config from scratch, thymian generate config --for-spec openapi:./api.yaml --for-report spectral:./report.json generates one that already includes the entries.

Flags take precedence: --report replaces the config file’s reports entirely, exactly like --spec replaces specifications. See the Configuration File reference for the full precedence rules.

Step 6: Add file formatters if you want artifacts

Section titled “Step 6: Add file formatters if you want artifacts”

The standard report formatters apply unchanged — configure @thymian/plugin-reporter (or pass --option overrides) and the converted report is written as markdown, CSV, or JSON like any other run.

  • Every Spectral finding becomes a lint finding — the converted report is a lint report.
  • Messages, severities, rule codes, and source locations survive the conversion; documentationUrl becomes the rule’s help link.
  • Endpoint mapping via --spec is best-effort: findings positioned at or after an endpoint’s location in the same source file attach to that endpoint; findings with a source that cannot be mapped fall back to a file:line:column location; findings without a source fall back to their JSON path (for example paths./users.get).
  • Unknown severity numbers convert conservatively as error (with a warning) — findings are never dropped.

Combining Spectral Results with Other Reports

Section titled “Combining Spectral Results with Other Reports”

To fold converted Spectral results and existing Thymian reports into one consolidated document, see Merging reportsthymian report merge accepts the same typed --report inputs and converts external formats on the way in.