Files
wehub-resource-sync 4b6817381b
CI (OpenClaw E2E) / openclaw test (push) Has been cancelled
CI / coverage-report (push) Has been cancelled
CI / test-kubernetes (push) Has been cancelled
CI / should-run-thorough (push) Has been cancelled
CI / test-thorough (cloudwatch-demo) (push) Has been cancelled
CI / test-thorough (flink-ecs) (push) Has been cancelled
CI / test-thorough (upstream-lambda) (push) Has been cancelled
CI / test-thorough (prefect-ecs-fargate) (push) Has been cancelled
Release / build-binaries (zip, opensre.exe, onefile, windows-latest, windows-x64) (push) Has been cancelled
Benchmark image — build + push to ECR (any adapter) / build + push (push) Has been cancelled
CI / quality (ubuntu-latest) (push) Has been cancelled
CI / test (tools-runtime) (push) Has been cancelled
CI / test (e2e-general) (push) Has been cancelled
CI / test (cli-runtime) (push) Has been cancelled
CI / test (e2e-provider-and-openclaw) (push) Has been cancelled
CI / test (integrations-and-misc) (push) Has been cancelled
Release / verify (push) Has been cancelled
Release / build-python-dist (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-15-intel, darwin-x64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-latest, darwin-arm64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04, linux-x64) (push) Has been cancelled
Release / publish-release (push) Has been cancelled
Release / publish-main-release (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-checks (no-LLM) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-live shard ${{ matrix.shard_index }} (push) Has been cancelled
Release / prepare (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04-arm, linux-arm64) (push) Has been cancelled
Synthetic Deterministic Tests / Synthetic offline (deterministic) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:10:45 +08:00

173 lines
5.1 KiB
Python

"""Rendering helpers for the ``opensre health`` command."""
from __future__ import annotations
import json
from pathlib import Path
from typing import Any
import click
from rich import box
from rich.console import Console
from rich.panel import Panel
from rich.table import Table
from rich.text import Text
from platform.terminal.theme import (
BOLD_BRAND,
BRAND,
ERROR,
HIGHLIGHT,
SECONDARY,
WARNING,
)
def status_badge(status: str) -> Text:
normalized = status.strip().lower()
if normalized in {"passed", "pass", "ok", "healthy"}:
return Text("PASSED", style=f"bold {HIGHLIGHT}")
if normalized in {"warn", "warning", "degraded", "outdated"}:
return Text("WARN", style=f"bold {WARNING}")
if normalized == "missing":
return Text("MISSING", style=f"bold {WARNING}")
if normalized in {"failed", "fail", "error", "unhealthy"}:
return Text("FAILED", style=f"bold {ERROR}")
return Text(normalized.upper() or "UNKNOWN", style="bold")
_STATUS_BUCKETS: dict[str, str] = {
"passed": "passed",
"pass": "passed",
"ok": "passed",
"healthy": "passed",
"missing": "missing",
"failed": "failed",
"fail": "failed",
"error": "failed",
"unhealthy": "failed",
}
def _summary_counts(results: list[dict[str, str]]) -> dict[str, int]:
counts = {"passed": 0, "missing": 0, "failed": 0, "other": 0}
for result in results:
status = str(result.get("status", "")).strip().lower()
bucket = _STATUS_BUCKETS.get(status, "other")
counts[bucket] += 1
return counts
def render_health_report(
*,
console: Console,
environment: str,
integration_store_path: str | Path,
results: list[dict[str, Any]],
) -> None:
"""Render a polished health report with summary and actionable hints."""
store_path_text = str(integration_store_path)
normalized_results: list[dict[str, str]] = [
{
"service": str(item.get("service", "")),
"source": str(item.get("source", "")),
"status": str(item.get("status", "")),
"detail": str(item.get("detail", "")),
}
for item in results
]
counts = _summary_counts(normalized_results)
console.print()
console.print(Panel.fit(f"[{BOLD_BRAND}]OpenSRE Health[/]", border_style=BRAND))
from platform.guardrails.rules import get_default_rules_path, load_rules
rules_path = get_default_rules_path()
if rules_path.exists():
rules = load_rules(rules_path)
enabled = [r for r in rules if r.enabled]
guardrails_status = f"{len(enabled)} rules active ({rules_path})"
else:
guardrails_status = "not configured"
meta = Table.grid(padding=(0, 1))
meta.add_row("[bold]Environment[/bold]", environment)
meta.add_row("[bold]Integration store[/bold]", store_path_text)
meta.add_row("[bold]Guardrails[/bold]", guardrails_status)
console.print(meta)
summary = Text.assemble(
("Summary: ", "bold"),
(f"{counts['passed']} passed", HIGHLIGHT),
(" | ", SECONDARY),
(f"{counts['missing']} missing", WARNING),
(" | ", SECONDARY),
(f"{counts['failed']} failed", ERROR),
)
if counts["other"]:
summary.append(" | ", style=SECONDARY)
summary.append(f"{counts['other']} unknown")
console.print(summary)
console.print()
table = Table(title="Integration Checks", box=box.SIMPLE_HEAVY, show_lines=False)
table.add_column("Service", style=BOLD_BRAND)
table.add_column("Source", style=SECONDARY)
table.add_column("Status")
table.add_column("Detail")
for result in normalized_results:
table.add_row(
result["service"] or "-",
result["source"] or "-",
status_badge(result["status"]),
result["detail"] or "-",
)
console.print(table)
console.print()
if counts["failed"] > 0:
console.print(
f"[bold {ERROR}]Action:[/] Fix failed integrations, then rerun [bold]opensre health[/bold]."
)
elif counts["missing"] > 0:
console.print(
f"[bold {WARNING}]Action:[/] Configure missing integrations with "
"[bold]opensre integrations setup <service>[/bold]."
)
else:
console.print(f"[bold {HIGHLIGHT}]All configured integrations look healthy.[/]")
def render_health_json(
*,
environment: str,
integration_store_path: str | Path,
results: list[dict[str, Any]],
) -> None:
"""Render the health report as machine-readable JSON."""
normalized = [
{
"service": str(item.get("service", "")),
"source": str(item.get("source", "")),
"status": str(item.get("status", "")),
"detail": str(item.get("detail", "")),
}
for item in results
]
counts = _summary_counts(normalized)
click.echo(
json.dumps(
{
"environment": environment,
"integration_store": str(integration_store_path),
"summary": counts,
"results": normalized,
},
indent=2,
)
)