From a318e16956d330267ccd3c2d93e1206b1abaad53 Mon Sep 17 00:00:00 2001 From: Mick Date: Thu, 13 Aug 2026 11:50:10 +0800 Subject: [PATCH] [diffusion] feat: publish an index of nightly comparison runs (#34652) Co-authored-by: Claude Opus 5 --- .../diffusion/publish_comparison_results.py | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/scripts/ci/utils/diffusion/publish_comparison_results.py b/scripts/ci/utils/diffusion/publish_comparison_results.py index 7a5bae557..c1bc1f8b8 100644 --- a/scripts/ci/utils/diffusion/publish_comparison_results.py +++ b/scripts/ci/utils/diffusion/publish_comparison_results.py @@ -14,6 +14,7 @@ Usage: """ import argparse +import json import os import sys import time @@ -31,6 +32,7 @@ if __package__: get_tree_sha, is_permission_error, is_rate_limit_error, + make_github_request, update_branch_ref, verify_token_permissions, ) @@ -44,6 +46,7 @@ else: get_tree_sha, is_permission_error, is_rate_limit_error, + make_github_request, update_branch_ref, verify_token_permissions, ) @@ -76,6 +79,47 @@ def _collect_chart_files(charts_dir: str) -> list[tuple[str, bytes]]: return files +def _build_run_index(run_target: str, token: str, keep: int = 90) -> bytes: + """List the published run files and return an index.json body. + + The site cannot discover these files itself: listing the directory needs + the contents API, whose anonymous 60/hour budget is shared per egress IP, + so viewers behind a shared proxy get permanent 403s. Publishing a stable + index alongside the runs lets the page read everything from + raw.githubusercontent.com instead, which is CORS-enabled and unmetered. + """ + names = {os.path.basename(run_target)} + try: + branch_sha = get_branch_sha(REPO_OWNER, REPO_NAME, BRANCH, token) + tree_sha = get_tree_sha(REPO_OWNER, REPO_NAME, branch_sha, token) + url = ( + f"https://api.github.com/repos/{REPO_OWNER}/{REPO_NAME}" + f"/git/trees/{tree_sha}?recursive=1" + ) + tree = json.loads(make_github_request(url, token)) + for item in tree.get("tree", []): + path = item.get("path", "") + base = os.path.basename(path) + if ( + path.startswith(f"{STORAGE_PREFIX}/") + and "/" not in path[len(STORAGE_PREFIX) + 1 :] + and base.endswith(".json") + and base != "index.json" + ): + names.add(base) + except Exception as exc: # an index is a convenience, never a publish blocker + print(f"Warning: could not list existing runs for the index ({exc})") + + # filenames start with the UTC date, so lexical order is chronological + recent = sorted(names, reverse=True)[:keep] + body = { + "generated_at": datetime.now(timezone.utc).isoformat(), + "prefix": STORAGE_PREFIX, + "runs": recent, + } + return json.dumps(body, indent=2).encode() + b"\n" + + def publish_comparison( results_path: str, dashboard_path: str | None = None, @@ -110,6 +154,11 @@ def publish_comparison( with open(results_path, "rb") as f: files_to_upload.append((results_target, f.read())) + # Stable index so the site can enumerate runs without the contents API + files_to_upload.append( + (f"{STORAGE_PREFIX}/index.json", _build_run_index(results_target, token)) + ) + # Dashboard markdown: always overwrite latest if dashboard_path and os.path.exists(dashboard_path): dashboard_target = f"{STORAGE_PREFIX}/dashboard.md"