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

225 lines
7.1 KiB
Python

"""Inject benchmark summary into README.md between HTML comment markers.
Follows the same marker-replacement pattern used elsewhere in ``README.md``:
content between a start and end marker is replaced idempotently via ``re.sub``
with ``re.DOTALL``.
"""
from __future__ import annotations
import logging
import re
from collections.abc import Sequence
from dataclasses import dataclass
from pathlib import Path
from typing import Any
logger = logging.getLogger(__name__)
DEFAULT_START_MARKER = "<!-- BENCHMARK-START -->"
DEFAULT_END_MARKER = "<!-- BENCHMARK-END -->"
@dataclass(frozen=True)
class _CaseMetrics:
"""Lightweight case data parsed from a benchmark report."""
scenario_id: str
run_status: str
duration_seconds: float
total_tokens: int
estimated_cost_usd: float
@dataclass(frozen=True)
class _SummaryMetrics:
"""Lightweight summary data parsed from a benchmark report."""
case_count: int
success_count: int
total_duration_seconds: float
total_estimated_cost_usd: float
def render_readme_summary(cases: Sequence[Any], summary: Any) -> str:
"""Render a compact markdown snippet suitable for injection into README.md.
Accepts any objects with the expected attributes (``scenario_id``,
``run_status``, ``duration_seconds``, ``total_tokens``,
``estimated_cost_usd`` on cases; ``success_count``, ``case_count``,
``total_estimated_cost_usd``, ``total_duration_seconds`` on summary).
"""
lines: list[str] = []
lines.append("| Scenario | Status | Duration (s) | Tokens | Est. Cost (USD) |")
lines.append("|---|---|---:|---:|---:|")
for c in cases:
lines.append(
f"| {c.scenario_id} | {c.run_status} | {c.duration_seconds:.2f} "
f"| {c.total_tokens} | {c.estimated_cost_usd:.6f} |"
)
lines.append("")
lines.append(
f"**{summary.success_count}/{summary.case_count} passed** "
f"| Total cost: ${summary.total_estimated_cost_usd:.4f} "
f"| Total duration: {summary.total_duration_seconds:.1f}s"
)
lines.append("")
lines.append("Full report: [docs/benchmarks/results.md](docs/benchmarks/results.md)")
return "\n".join(lines)
def update_readme_benchmarks(
readme_path: Path,
snippet: str,
*,
start_marker: str = DEFAULT_START_MARKER,
end_marker: str = DEFAULT_END_MARKER,
) -> None:
"""Replace the section between *start_marker* and *end_marker* in *readme_path*.
Raises ``ValueError`` if either marker is missing from the file.
"""
content = readme_path.read_text(encoding="utf-8")
if start_marker not in content:
raise ValueError(f"Start marker {start_marker!r} not found in {readme_path}")
if end_marker not in content:
raise ValueError(f"End marker {end_marker!r} not found in {readme_path}")
pattern = re.escape(start_marker) + r".*?" + re.escape(end_marker)
replacement = f"{start_marker}\n{snippet}\n{end_marker}"
updated = re.sub(pattern, replacement, content, flags=re.DOTALL)
readme_path.write_text(updated, encoding="utf-8")
logger.info("Updated benchmark section in %s", readme_path)
def _find_repo_root() -> Path:
"""Walk up from this file to find the repository root (contains README.md)."""
current = Path(__file__).resolve().parent
for parent in (current, *current.parents):
if (parent / "README.md").exists():
return parent
raise FileNotFoundError("Could not locate repository root with README.md")
def _parse_report_to_metrics(
report: str,
) -> tuple[list[_CaseMetrics], _SummaryMetrics] | None:
"""Parse a benchmark report back into structured metrics.
Returns ``None`` if the report cannot be parsed (empty or malformed).
"""
cases: list[_CaseMetrics] = []
summary_kv: dict[str, str] = {}
# Parse per-case table rows
in_table = False
for raw_line in report.splitlines():
line = raw_line.strip()
if line.startswith("| Scenario"):
in_table = True
continue
if in_table and line.startswith("|---"):
continue
if in_table:
if not line.startswith("|"):
in_table = False
continue
cols = [c.strip() for c in line.split("|")[1:-1]]
if len(cols) >= 7:
cases.append(
_CaseMetrics(
scenario_id=cols[0],
run_status=cols[1],
duration_seconds=float(cols[2]),
total_tokens=int(cols[5]),
estimated_cost_usd=float(cols[6]),
)
)
# Parse summary section
in_summary = False
for raw_line in report.splitlines():
line = raw_line.strip()
if line == "## Summary":
in_summary = True
continue
if in_summary:
if line.startswith("##"):
break
if line.startswith("- "):
key, _, val = line[2:].partition(":")
summary_kv[key.strip()] = val.strip()
if not cases:
return None
case_count = int(summary_kv.get("Cases", str(len(cases))))
success_count = int(
summary_kv.get(
"Successful runs",
str(sum(1 for c in cases if c.run_status == "ok")),
)
)
total_duration = float(
summary_kv.get(
"Total duration (s)",
str(sum(c.duration_seconds for c in cases)),
)
)
total_cost = float(
summary_kv.get(
"Total estimated cost (USD)",
str(sum(c.estimated_cost_usd for c in cases)),
)
)
summary = _SummaryMetrics(
case_count=case_count,
success_count=success_count,
total_duration_seconds=total_duration,
total_estimated_cost_usd=total_cost,
)
return cases, summary
def extract_summary_from_report(report: str) -> str:
"""Extract a compact summary snippet from a full benchmark report.
Parses the report back into structured metrics and renders using
``render_readme_summary``, ensuring both update paths produce
identical README content.
"""
parsed = _parse_report_to_metrics(report)
if parsed is None:
return "\nFull report: [docs/benchmarks/results.md](docs/benchmarks/results.md)"
cases, summary = parsed
return render_readme_summary(cases, summary)
def main() -> int:
"""Update README benchmark section from the cached results report.
Parses ``docs/benchmarks/results.md`` to extract the per-case table and
summary, then injects a compact snippet into README.md.
"""
logging.basicConfig(level=logging.INFO, format="%(message)s")
repo_root = _find_repo_root()
results_path = repo_root / "docs" / "benchmarks" / "results.md"
readme_path = repo_root / "README.md"
if not results_path.exists():
logger.error("No benchmark results found at %s. Run 'make benchmark' first.", results_path)
return 1
snippet = extract_summary_from_report(results_path.read_text(encoding="utf-8"))
update_readme_benchmarks(readme_path, snippet)
return 0
if __name__ == "__main__":
raise SystemExit(main())