* HH-446: restore auditable quality gates * test(HH-446): restore help center smoke contract --------- Co-authored-by: Rogee <rogee@ipao.vip>
48 lines
1.6 KiB
Python
Executable File
48 lines
1.6 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Validate the stable JSON contract returned by GET /health."""
|
|
|
|
import argparse
|
|
import json
|
|
import sys
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
|
|
|
|
def validate(value):
|
|
if not isinstance(value, dict):
|
|
return "health response must be a JSON object"
|
|
missing = sorted({"status", "timestamp", "uptime", "checks"} - value.keys())
|
|
if missing:
|
|
return f"health response missing fields: {', '.join(missing)}"
|
|
if value["status"] != "healthy":
|
|
return f"unexpected health status: {value['status']}"
|
|
try:
|
|
datetime.fromisoformat(value["timestamp"].replace("Z", "+00:00"))
|
|
except (AttributeError, ValueError):
|
|
return "timestamp must be RFC3339"
|
|
if not isinstance(value["uptime"], str) or not value["uptime"]:
|
|
return "uptime must be a non-empty string"
|
|
if not isinstance(value["checks"], dict) or value["checks"].get("database") != "healthy":
|
|
return "database health check must be healthy"
|
|
return None
|
|
|
|
|
|
def main(argv=None):
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("path", nargs="?", help="JSON file; stdin when omitted")
|
|
args = parser.parse_args(argv)
|
|
try:
|
|
raw = Path(args.path).read_text(encoding="utf-8") if args.path else sys.stdin.read()
|
|
error = validate(json.loads(raw))
|
|
except (OSError, json.JSONDecodeError) as exc:
|
|
error = f"invalid health JSON: {exc}"
|
|
if error:
|
|
print(error, file=sys.stderr)
|
|
return 1
|
|
print("health JSON contract: ok")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|