From c2e1939a276e494eff9f4e9c64698cbe48501290 Mon Sep 17 00:00:00 2001 From: pulk17 Date: Sun, 25 Oct 2026 00:12:38 +0530 Subject: [PATCH] base test health on finished master runs the list picked master runs out of the newest 40, so it went blank whenever pr runs filled them, and it read whichever platform ran last, so a linux-only failure could show as passing. pr runs are now labelled in the detail panel. --- web/src/lib/api.ts | 91 +++++++++++++++++++++++++------------ web/src/pages/Workspace.tsx | 6 ++- 2 files changed, 68 insertions(+), 29 deletions(-) diff --git a/web/src/lib/api.ts b/web/src/lib/api.ts index 0db2fb8de..7e126111f 100644 --- a/web/src/lib/api.ts +++ b/web/src/lib/api.ts @@ -98,8 +98,17 @@ async function fetchAll(path: string, cap = 500): Promise { /* ---------------- live queries ---------------- */ -/** How many past runs the sparklines and the average runtime look back over. */ -const HISTORY_RUNS = 6; +/** How many master commits the sparklines and the average runtime look back over. */ +const HISTORY_COMMITS = 6; + +/** + * Pushes to master on the main repository. PR runs are stored on the branch + * "pull_request" and fork pushes under their own repository, so this is what + * "the health of a test" means. Not exposed by the API, hence spelled out + * here as RunNew does. + */ +const MASTER_RUNS = + "/runs?branch=master&repository=CCExtractor/ccextractor&limit=40&sort=-created_at"; interface TestHistory { recent_results: SparkResult[]; @@ -116,19 +125,38 @@ function sparkResultOf(status: string): SparkResult { return "skip"; } -/** Collect one test's results and runtimes across the runs that covered it. */ -function foldRunRows(perRun: RunSampleRow[][]) { +/** One commit's result per test: a failure on either platform wins, then a pass. */ +function commitResults(rows: RunSampleRow[]): Map { + const results = new Map(); + for (const row of rows) { + const now = sparkResultOf(row.status); + const seen = results.get(row.regression_test_id); + if (seen !== "fail" && (now === "fail" || seen !== "pass")) { + results.set(row.regression_test_id, now); + } + } + return results; +} + +/** + * Collect each test's results and runtimes, one point per commit, oldest + * first. A test fails a commit if it failed on either platform: otherwise a + * Linux-only failure reads as passing whenever the Windows run happens to + * have the higher id. + */ +export function foldCommitRows(perCommit: RunSampleRow[][]) { const history = new Map(); const runtimes = new Map(); - for (const row of perRun.flat()) { - const entry = history.get(row.regression_test_id) ?? { - recent_results: [], - avg_runtime_ms: null, - }; - entry.recent_results.push(sparkResultOf(row.status)); - history.set(row.regression_test_id, entry); + for (const rows of perCommit) { + for (const [id, result] of commitResults(rows)) { + const entry = history.get(id) ?? { recent_results: [], avg_runtime_ms: null }; + entry.recent_results.push(result); + history.set(id, entry); + } + } + for (const row of perCommit.flat()) { if (row.runtime_ms != null) { runtimes.set(row.regression_test_id, [ ...(runtimes.get(row.regression_test_id) ?? []), @@ -147,36 +175,43 @@ function foldRunRows(perRun: RunSampleRow[][]) { } /** - * Per-test result history, assembled from recent runs. + * Per-test result history over the last few finished master commits. * * There is no per-test history endpoint, but /runs/{id}/samples already * returns every test's status and runtime for one run, so reading a handful * of runs and transposing them costs a few requests rather than one per - * test. Only commit runs count: a PR run failing says something about the - * pull request, not about the health of the test. + * test. Master runs are fetched on their own: picking them out of the + * shared "latest runs" list found none whenever PR runs filled it. Only + * finished runs count, since a queued or stuck one has no results yet. */ export function useTestHistory() { - const { data: runs = [] } = useRuns(); - const runIds = runs - .filter((r) => r.test_type === "commit") - .slice(0, HISTORY_RUNS) - .flatMap((r) => r.platforms.map((p) => p.run_id)) - .toSorted((a, b) => a - b); - return useQuery({ - queryKey: ["test-history", runIds], - enabled: runIds.length > 0, + queryKey: ["test-history"], staleTime: 60_000, - queryFn: async () => - foldRunRows( + queryFn: async () => { + const res = await apiGet>(MASTER_RUNS); + const finished = res.data.filter((r) => r.status === "pass" || r.status === "fail"); + const commits = [...new Set(finished.map((r) => r.commit_sha))] + .slice(0, HISTORY_COMMITS) + .reverse(); + return foldCommitRows( await Promise.all( - runIds.map((id) => fetchAll(`/runs/${id}/samples`, 400)), + commits.map(async (sha) => + ( + await Promise.all( + finished + .filter((r) => r.commit_sha === sha) + .map((r) => fetchAll(`/runs/${r.run_id}/samples`, 400)), + ) + ).flat(), + ), ), - ), + ); + }, }); } -interface RunSampleRow { +export interface RunSampleRow { regression_test_id: number; status: string; runtime_ms: number | null; diff --git a/web/src/pages/Workspace.tsx b/web/src/pages/Workspace.tsx index 102e6151a..21536cefb 100644 --- a/web/src/pages/Workspace.tsx +++ b/web/src/pages/Workspace.tsx @@ -391,7 +391,8 @@ function Detail({ test }: Readonly<{ test: RegressionTest }>) {
- {passN} pass · {liveResults.length - passN} fail · runs that included this test + {passN} pass · {liveResults.length - passN} fail · every run of this test, + PR runs included
) : ( @@ -432,6 +433,9 @@ function Detail({ test }: Readonly<{ test: RegressionTest }>) { )} /> run {h.run_id} + {h.branch !== "master" && ( + pr + )}