tutorial

How to Monitor Spectral with Vigilmon

Spectral lints your OpenAPI and AsyncAPI specs in CI — but when your linting pipeline silently stops running, API governance breaks down. Here's how to monitor Spectral with Vigilmon.

Spectral is the open-source JSON/YAML linter from Stoplight that enforces API style guides against your OpenAPI, AsyncAPI, or any JSON Schema document. It's the guard rail that keeps your API contracts consistent. But Spectral runs in CI — and CI pipelines fail silently all the time. A skipped lint step, a misconfigured rule file, or a broken CI trigger means your API governance is off and nobody notices until a poorly designed endpoint makes it to production. Vigilmon gives you the monitoring layer to know when Spectral stops running.

What You'll Set Up

  • Cron heartbeat monitoring for Spectral lint pipeline runs
  • HTTP monitor for a Spectral-as-a-service endpoint (if using a shared linting service)
  • Alerting when the lint pipeline goes stale

Prerequisites

  • Spectral CLI installed (npm install -g @stoplight/spectral-cli) or used via CI action
  • OpenAPI or AsyncAPI specification files in your repo
  • A free Vigilmon account

Step 1: Heartbeat Monitor for Your Spectral CI Job

The primary Spectral failure mode is the lint job not running at all — workflow trigger misconfiguration, skipped jobs, or a broken path filter that excludes spec files. A Vigilmon cron heartbeat detects this immediately.

  1. Log in to vigilmon.online and click Add Monitor.
  2. Choose Cron Heartbeat.
  3. Set the expected ping interval to match how often your CI runs lint (e.g. 60 minutes for every push, 1440 for daily scheduled runs).
  4. Copy the heartbeat URL (e.g. https://vigilmon.online/heartbeat/abc123).

GitHub Actions

# .github/workflows/api-lint.yml
name: API Lint

on:
  push:
    paths:
      - 'api/**'
      - '.spectral.yaml'
  schedule:
    - cron: '0 8 * * *'  # daily at 8am

jobs:
  spectral:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install Spectral
        run: npm install -g @stoplight/spectral-cli

      - name: Lint OpenAPI spec
        run: spectral lint api/openapi.yaml --ruleset .spectral.yaml

      - name: Ping Vigilmon heartbeat
        if: success()
        run: curl -fsS --max-time 10 https://vigilmon.online/heartbeat/abc123

The if: success() guard ensures the heartbeat only fires when linting actually passed — not when the job errored before reaching the lint step.

GitLab CI

# .gitlab-ci.yml
spectral-lint:
  image: node:20-alpine
  stage: test
  script:
    - npm install -g @stoplight/spectral-cli
    - spectral lint api/openapi.yaml --ruleset .spectral.yaml
    - curl -fsS --max-time 10 https://vigilmon.online/heartbeat/abc123
  only:
    changes:
      - api/**
      - .spectral.yaml

Step 2: Monitor a Shared Spectral Service

Some teams run Spectral as a centralised HTTP service so spec files can be linted on demand from multiple pipelines. If you're running a Spectral API wrapper, add an HTTP uptime monitor.

A minimal Express wrapper around Spectral:

// spectral-service.js
const express = require('express');
const { Spectral } = require('@stoplight/spectral-core');
const { bundleAndLoadRuleset } = require('@stoplight/spectral-ruleset-bundler/with-loader');

const app = express();
app.use(express.json({ limit: '2mb' }));

app.get('/health', (req, res) => res.json({ status: 'ok' }));

app.post('/lint', async (req, res) => {
  try {
    const spectral = new Spectral();
    const ruleset = await bundleAndLoadRuleset('/etc/spectral/.spectral.yaml');
    spectral.setRuleset(ruleset);
    const results = await spectral.run(req.body.document);
    const errors = results.filter(r => r.severity === 0);
    res.json({ issues: results.length, errors: errors.length, results });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

app.listen(3000, () => console.log('Spectral service listening on :3000'));

Add a Vigilmon HTTP monitor for this service:

  1. Click Add MonitorHTTP / HTTPS.
  2. Enter: https://spectral.internal/health
  3. Set Check interval to 5 minutes.
  4. Set Expected HTTP status to 200.
  5. Click Save.

Step 3: Track Spectral Rule Violations Over Time

Beyond uptime, you can track how many lint violations your specs accumulate. Expose a metrics endpoint from your Spectral service or post stats to Vigilmon's status endpoint after each CI run.

Store and expose violation counts:

// After running Spectral in CI, post a summary
const violations = await runSpectral('api/openapi.yaml');
const summary = {
  errors: violations.filter(v => v.severity === 0).length,
  warnings: violations.filter(v => v.severity === 1).length,
  timestamp: new Date().toISOString(),
};

// Write to a file for a status server, or POST to your observability stack
fs.writeFileSync('/var/run/spectral-status.json', JSON.stringify(summary));

Serve it via a lightweight status endpoint that Vigilmon probes:

app.get('/health', (req, res) => {
  const status = JSON.parse(fs.readFileSync('/var/run/spectral-status.json'));
  const age = Date.now() - new Date(status.timestamp).getTime();
  const stale = age > 25 * 60 * 60 * 1000; // over 25 hours since last run
  if (stale || status.errors > 0) {
    return res.status(503).json({ ...status, stale, reason: stale ? 'no_recent_run' : 'lint_errors' });
  }
  res.json({ ...status, stale: false });
});

Step 4: Alert on Rule File Changes That Break Linting

Spectral ruleset files (.spectral.yaml) can introduce syntax errors that cause Spectral to exit with an error before checking any spec. This looks identical to a "no spec files changed" skip at the pipeline level — both result in no heartbeat being sent.

Add a ruleset validation step before linting:

# validate-ruleset.sh
spectral lint --ruleset .spectral.yaml --format json . 2>&1 | head -5
if [ ${PIPESTATUS[0]} -eq 2 ]; then
  echo "Ruleset syntax error — Spectral cannot load .spectral.yaml"
  exit 1
fi

Run this as a separate CI job that blocks the lint job. That way a broken ruleset fails loudly rather than silently skipping all lint checks.


Step 5: Set Up Alerting

  1. In Vigilmon, open the heartbeat monitor from Step 1.
  2. Click AlertingAdd Alert Channel.
  3. Add Slack (for the API governance team channel) and Email (for the API platform lead).
  4. Set trigger: missed 1 heartbeat.
  5. Click Save.

For the HTTP service monitor:

  • Set trigger: down for 2 minutes.
  • Route alerts to the infrastructure on-call channel.
  • Set a separate email alert for the API platform team so they know the shared service is unavailable.

Conclusion

Spectral is your API governance enforcement layer — when it stops running, your API contracts start drifting without anyone noticing. A missed CI trigger, a broken ruleset, or a silent pipeline failure can mean weeks of ungoverned API changes. Vigilmon's cron heartbeats give you a dead-man's switch: if Spectral doesn't report in on schedule, you know immediately.

Start with the heartbeat monitor on your CI lint job — it's the highest-value monitor and takes five minutes to set up. Add the Spectral service HTTP monitor if you run a shared linting service, and route alerts to the team responsible for your API style guide. Your API governance posture depends on Spectral actually running — now you'll know when it doesn't.

Monitor your app with Vigilmon

Free plan — 5 monitors, no credit card required. Up and running in 60 seconds.

Start free →