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.
- Log in to vigilmon.online and click Add Monitor.
- Choose Cron Heartbeat.
- Set the expected ping interval to match how often your CI runs lint (e.g.
60minutes for every push,1440for daily scheduled runs). - 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:
- Click Add Monitor → HTTP / HTTPS.
- Enter:
https://spectral.internal/health - Set Check interval to
5 minutes. - Set Expected HTTP status to
200. - 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
- In Vigilmon, open the heartbeat monitor from Step 1.
- Click Alerting → Add Alert Channel.
- Add Slack (for the API governance team channel) and Email (for the API platform lead).
- Set trigger: missed 1 heartbeat.
- 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.