feat(ack): shard task records for merge-safe workspaces

This commit is contained in:
2026-09-20 19:15:43 +08:00
parent fd13dad2b0
commit 130dcc36c5
29 changed files with 985 additions and 218 deletions
+24 -7
View File
@@ -5,6 +5,7 @@ from __future__ import annotations
import argparse
import csv
import re
import sys
from collections import Counter
from pathlib import Path
@@ -19,6 +20,7 @@ except ImportError: # pragma: no cover
from generate_cases_csv import load_cases, one_line, resolve_root, tester_dir
RESULTS = ("pass", "fail", "environment-fail", "skipped", "not-run")
RUN_ID_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$")
EXECUTED_YES = frozenset({"pass", "fail", "environment-fail"})
EXECUTED_NO = frozenset({"skipped", "not-run"})
FIELDS = (
@@ -56,6 +58,22 @@ def latest_run_yaml(root: Path) -> Path | None:
return files[-1] if files else None
def new_run_id(scope: str, suffix: str | None = None) -> str:
"""Return a collision-resistant filename/id for a new run snapshot."""
from datetime import datetime, timezone
from secrets import token_hex
clean_scope = re.sub(r"[^A-Za-z0-9._-]+", "-", scope).strip("-") or "run"
stamp = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ")
clean_suffix = re.sub(r"[^A-Za-z0-9._-]+", "-", suffix or "").strip("-")
random_part = token_hex(3)
parts = [stamp, clean_scope]
if clean_suffix:
parts.append(clean_suffix)
parts.append(random_part)
return "-".join(parts)
def load_run(path: Path) -> dict[str, Any]:
data = yaml.safe_load(path.read_text(encoding="utf-8")) or {}
if not isinstance(data, dict):
@@ -63,6 +81,11 @@ def load_run(path: Path) -> dict[str, Any]:
results = data.get("results")
if not isinstance(results, list):
raise SystemExit(f"{path} 缺少 results 列表")
run_id = data.get("runId")
if run_id is not None and (
not isinstance(run_id, str) or RUN_ID_RE.fullmatch(run_id) is None
):
raise SystemExit(f"{path} 的 runId 格式无效")
return data
@@ -88,7 +111,6 @@ def export_run_csv(
root: Path,
run_path: Path | None = None,
out: Path | None = None,
refresh_cases: bool = True,
) -> Path:
path = run_path or latest_run_yaml(root)
if path is None:
@@ -122,10 +144,6 @@ def export_run_csv(
"maps_to": case.get("maps_to") or "",
}
)
if refresh_cases:
from generate_cases_csv import export_cases_csv
export_cases_csv(root)
return dest
@@ -137,7 +155,7 @@ def main(argv: list[str] | None = None) -> int:
parser.add_argument(
"--no-refresh-cases",
action="store_true",
help="不要顺便刷新 cases.csv 的 last_* 列",
help="兼容旧命令;cases.csv 已不会被运行结果刷新",
)
args = parser.parse_args(argv)
root = resolve_root(args.root)
@@ -147,7 +165,6 @@ def main(argv: list[str] | None = None) -> int:
root,
run_path=run_path,
out=out,
refresh_cases=not args.no_refresh_cases,
)
counts: Counter[str] = Counter()
with path.open(encoding="utf-8-sig", newline="") as handle: