ci: nothing validates the 49 vmalert rules before they reach production #439
Etiketter
Inga etiketter
area/backups
area/ci
area/control-panel
area/identity
area/infra
area/observability
area/payments
area/security
area/storage
area/web
blocked
needs-info
needs-triage
ready-for-implementation
type
bug
type
chore
type
docs
type
epic
type
feature
type
task
wontfix
Ingen milstolpe
Inget projekt
Inga tilldelade
1 deltagare
Notiser
Förfallodatum
Inget förfallodatum satt.
Beroenden
Inga beroenden satta
Referens
bitborg/bitborg-infra#439
Läser in…
Hänvisa till i nytt ärende
Ingen beskrivning angiven.
Ta bort grenen "%!s()"
Borttagning av en gren är permanent. Även om den borttagna grenen kan fortsätta existera en kort tid innan den faktiskt tas bort, kan det INTE ångras i de flesta fall. Vill du fortsätta?
The gap
ansible/roles/monitoring/templates/alert-rules.yml.j2renders 49 alert rules. Nothing checks thatthey parse.
grep -rn promtoolover the whole repo returns nothing, and theRender alert rulestask carries no
validate:.The deploy path is that template task, then
notify: Restart vmalert. There is no gate anywherebetween a typo and production.
Blast radius
vmalert parses and validates the rule file at startup, and the unit does not pass
-rule.validateExpressions=false. A parse error is fatal for the whole file, not for the one rule.Measured against the pinned
vmalert_image_tag(v1.147.0), with a single extra(in theDiskUsageWarningexpression:So one unbalanced paren stops all 49 rules.
vmalert.container.j2setsRestart=always, so theresult is a crash loop rather than a stopped unit.
Nothing currently notices. The
Watchdogdead-man's switch exists (vector(1), severitynone),but its Alertmanager receiver deliberately has no integrations yet: it only protects against vmalert
death once an external monitor consumes it and alarms on silence. Until that lands, vmalert dying is
silent, and so is the loss of every other alert.
Proposed gate
A step in
.forgejo/workflows/ci.ymlgated onsteps.changes.outputs.ansible, alongside theexisting python checks. Two stages, because they catch different failures.
Stage 1: render with real variables, under
StrictUndefinedEvery variable the template uses resolves with no vault password:
roles/monitoring/defaults/main.ymlgroup_vars/all/vars.yml(bitborg_domain,web_healthcheck_path,forgejo_oidc_source_name,backup_retention_days)ansible_managed, which can be any stringSo nothing needs faking. Use
jinja2.StrictUndefinedand the real values.Do not substitute a placeholder for undefined variables. A placeholder renders
> 1, whichparses, so the guard would pass on precisely the bug most likely to occur. A role default renamed
out from under the template is the realistic failure here, and only strict mode catches it.
PyYAML and Jinja2 both ship with the
ansiblealready baked into thecirunner image (#65), sothis installs nothing new. Invoke it with ansible's own interpreter, not a bare
python3.Stage 2: validate with vmalert, not promtool
promtool check rulesdoes work on the rendered file today. It is still the wrong engine. vmalertis VictoriaMetrics: it accepts MetricsQL and vmalert-specific fields that promtool rejects, so
promtool can only ever approximate, and it drifts toward false failures as rules use more MetricsQL.
vmalert -dryRunat the pinned tag is the exact consumer, needs no datasource, and returns 255 onfailure.
Negative controls
Proven locally, with real exit codes:
(inDiskUsageWarningalert_disk_warn_pctrenamed in role defaultsjinja2 UndefinedErrorWire these into the check itself, the way
test_renovate_dashboard_exporter.pycarries its ownnegative controls. A validator nobody has watched fail is not evidence.
Notes
roles/monitoring/defaults/main.yml. Do not pin a second literal in CI:a duplicated literal drifts, and the drift is invisible.
--user 0is needed when the rendered file sits on a bind mount the container user cannot read.cmd | tailin the CI step.$?then reportstail, and the gate is green forever.Watchdogheartbeat an external consumer is a separate and larger gap. It is what makesthis one silent, and it does not appear to be tracked yet.
Acceptance
mainunchanged, reporting 49 rules.