chore(selfhost): validate Grafana dashboard JSON and Prometheus alert-rule syntax#2659
Conversation
…-rule syntax (#1943) Completes the last unverified deliverable from #1943 -- the rest (dashboard panels, alert rules, troubleshooting runbooks) was audited and found already comprehensive or shipped in #2638. Grafana and Prometheus both fail OPEN on a malformed dashboard/rule file (skip it, log a warning), so nothing else catches this until an operator notices a panel or alert is simply missing. scripts/validate-observability-configs.mjs checks every grafana/dashboards/*.json file parses and has a title + panels array, and prometheus/rules/alerts.yml parses and every rule has alert/expr/labels.severity/annotations.summary. Wired into test:ci. 12 unit tests cover both validators' happy paths and failure modes.
|
Warning 🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨 ⏸️ Gittensory review result - manual review recommendedReview updated: 2026-07-03 01:53:02 UTC
⏸️ Suggested Action - Manual Review
Review summary Nits — 6 non-blocking
Review context
Contributor next steps
Signal definitions
🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.
|
…rashing the validator Gate review caught a real bug: valid JSON/YAML that parses to a non-object (a dashboard file containing literally "null", or a YAML sequence entry like "- null") crashed the validator with a TypeError instead of producing the structured validation error it exists to provide -- the one failure mode it's explicitly meant to catch cleanly. Added an isObject() guard before every dereference (dashboard, group, rule) and 4 new regression tests covering null/array/string/primitive-at-each-level.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2659 +/- ##
=======================================
Coverage 96.10% 96.10%
=======================================
Files 237 237
Lines 26505 26505
Branches 9614 9614
=======================================
Hits 25472 25472
Misses 424 424
Partials 609 609 🚀 New features to boost your workflow:
|
…t import Gate review correctly noted the validator claimed to check "alert rule syntax" but only verified expr was a non-empty string -- malformed PromQL like "up ==" passed silently. Added a lightweight (not a real parser -- no promtool/PromQL-grammar dependency, out of scope for this "if available" deliverable) sanity check: balanced brackets and no dangling trailing binary operator. Verified zero false positives against all 21 real rules in prometheus/rules/alerts.yml. Also dropped an unused mkdirSync import the gate flagged as a nit.
…L sanity check
Gate review caught a real bug: a plain depth counter only checks net nesting
count, so "sum(foo[5m))" -- opened with "(" and "[", closed with ")" and ")" --
nets to depth 0 and wrongly passes as balanced, even though the second ")"
doesn't match the "[" it's supposed to close. Switched to a stack that checks
each closer against the delimiter it actually needs to match. Verified against
the real alerts.yml (still zero false positives) and added a regression test
for the exact mismatched-type case the gate identified.
Closes #1943
Summary
PR #2638 (this session) audited every deliverable in #1943 against the actual code and found dashboards (6), alert rules (13 groups, ~21 rules), and metrics already comprehensive — the genuine gap was 5 missing troubleshooting runbooks, which shipped there. The one deliverable left unverified was "add validation for dashboard JSON / alert rule syntax if available."
scripts/validate-observability-configs.mjscloses that gap: Grafana and Prometheus both fail OPEN on a malformed dashboard/rule file (skip it, log a warning), so nothing else catches a broken file until an operator notices a panel or alert is simply missing.grafana/dashboards/*.jsonfile parses as JSON and has a non-emptytitle+ apanelsarray.prometheus/rules/alerts.ymlparses as YAML and every rule hasalert,expr,labels.severity, andannotations.summary.test:ciasselfhost:validate-observability.Test plan
npm run selfhost:validate-observability— passes against the real dashboards/rulesnpm run typecheck,npm run test:coverage— clean; 12 new unit tests cover both validators' happy paths and failure modes (invalid JSON/YAML, missing fields, empty directory, unreadable path)npm run test:ci(full local gate, unsharded) — greennpm audit --audit-level=moderate— 0 vulnerabilities