from __future__ import annotations import subprocess import sys from pathlib import Path import yaml ROOT = Path(__file__).resolve().parents[3] CHECKER = ROOT / "scripts" / "ops" / "backup-alert-label-contract-check.py" RULES = ROOT / "ops" / "monitoring" / "alerts-unified.yml" BASELINE = ROOT / "ops" / "reboot-recovery" / "full-stack-backup-baseline.yml" def _run(rules: Path) -> subprocess.CompletedProcess[str]: return subprocess.run( [ sys.executable, str(CHECKER), "--rules", str(rules), "--baseline", str(BASELINE), ], cwd=ROOT, capture_output=True, text=True, check=False, ) def test_checker_accepts_firing_only_receipt_contract() -> None: result = _run(RULES) assert result.returncode == 0, result.stderr assert "requires receipts only for actively firing backup/Gitea alerts" in result.stdout assert "BACKUP_ALERT_LABEL_CONTRACT_OK" in result.stdout def test_checker_rejects_non_firing_receipt_selector(tmp_path: Path) -> None: payload = yaml.safe_load(RULES.read_text(encoding="utf-8")) for group in payload["groups"]: for rule in group.get("rules", []): if rule.get("alert") == "BackupAlertReceiptStageMissing": rule["expr"] = str(rule["expr"]).replace( 'alertstate="firing"', 'alertstate="pending"', ) candidate = tmp_path / "alerts.yml" candidate.write_text(yaml.safe_dump(payload, allow_unicode=True, sort_keys=False), encoding="utf-8") result = _run(candidate) assert result.returncode != 0 assert 'alertstate="firing"' in result.stderr