From 25b26f459389659600b6bafadb59462b6c513df9 Mon Sep 17 00:00:00 2001 From: Codex Date: Sun, 28 Jun 2026 09:00:59 +0000 Subject: [PATCH] fix: verify sentinel dashboard with route prefix --- scripts/src/hwlab-node-web-sentinel-cicd.ts | 32 ++++++++++++++------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/scripts/src/hwlab-node-web-sentinel-cicd.ts b/scripts/src/hwlab-node-web-sentinel-cicd.ts index f85b4ba7..bfe63017 100644 --- a/scripts/src/hwlab-node-web-sentinel-cicd.ts +++ b/scripts/src/hwlab-node-web-sentinel-cicd.ts @@ -2273,8 +2273,13 @@ const dom = await page.evaluate(async ({ expectedRoutePrefix, expectedSentinelId chartCounts.ok = typeof chartCounts.error === "number" && typeof chartCounts.warning === "number" && typeof chartCounts.total === "number" ? chartCounts.total === chartCounts.error + chartCounts.warning : false; - const runsPayload = await fetch("/api/runs?limit=30&sort=updated", { cache: "no-store" }).then((item) => item.json()).catch(() => null); - const overviewPayload = await fetch("/api/overview", { cache: "no-store" }).then((item) => item.json()).catch(() => null); + const apiUrl = (path) => { + const basePath = root?.getAttribute("data-base-path") || expectedRoutePrefix || ""; + const prefix = basePath.replace(/\/+$/u, ""); + return (prefix + (path.startsWith("/") ? path : "/" + path)) || path; + }; + const runsPayload = await fetch(apiUrl("/api/runs?limit=30&sort=updated"), { cache: "no-store" }).then((item) => item.json()).catch(() => null); + const overviewPayload = await fetch(apiUrl("/api/overview"), { cache: "no-store" }).then((item) => item.json()).catch(() => null); const runs = Array.isArray(runsPayload?.runs) ? runsPayload.runs : Array.isArray(runsPayload?.items) ? runsPayload.items : []; const latestRun = runs[0] || null; const latestCounts = latestRun && latestRun.severityCounts && typeof latestRun.severityCounts === "object" && !Array.isArray(latestRun.severityCounts) @@ -2289,7 +2294,7 @@ const dom = await page.evaluate(async ({ expectedRoutePrefix, expectedSentinelId allSamples: allSampleCount(latestCounts), }; const latestDetailPayload = latestRunCounts.runId - ? await fetch("/api/runs/" + encodeURIComponent(latestRunCounts.runId), { cache: "no-store" }).then((item) => item.json()).catch(() => null) + ? await fetch(apiUrl("/api/runs/" + encodeURIComponent(latestRunCounts.runId)), { cache: "no-store" }).then((item) => item.json()).catch(() => null) : null; const latestDetailRows = Array.isArray(latestDetailPayload?.findings) ? latestDetailPayload.findings : []; const rowSeverity = (row) => { @@ -2502,9 +2507,14 @@ const dom = await page.evaluate(async ({ expectedRoutePrefix, expectedSentinelId } }, { expectedRoutePrefix, expectedSentinelId }); -const runFilterProbe = await page.evaluate(async () => { - const requestedRunId = "sentinel-run-mqxi16vo-39b603ae"; +const runFilterProbe = await page.evaluate(async ({ expectedRoutePrefix }) => { const numberValue = (value) => Number.isFinite(Number(value)) ? Number(value) : 0; + const root = document.querySelector("#monitor-web-root"); + const apiUrl = (path) => { + const basePath = root?.getAttribute("data-base-path") || expectedRoutePrefix || ""; + const prefix = basePath.replace(/\/+$/u, ""); + return (prefix + (path.startsWith("/") ? path : "/" + path)) || path; + }; const rowSeverity = (row) => { const raw = String(row?.maxSeverity || row?.checkLevel || row?.severity || row?.level || "").toLowerCase(); if (["red", "critical", "error", "blocked", "failed"].includes(raw)) return "red"; @@ -2549,16 +2559,18 @@ const runFilterProbe = await page.evaluate(async () => { }; const select = document.querySelector("select[aria-label='选择运行记录']"); if (!(select instanceof HTMLSelectElement)) { - return { ok: false, requestedRunId, reason: "run-select-missing" }; + return { ok: false, requestedRunId: null, reason: "run-select-missing" }; } - const requestedOption = Array.from(select.options).find((option) => option.value === requestedRunId); - const fallbackOption = requestedOption || select.options[Math.min(2, Math.max(0, select.options.length - 1))] || select.options[0] || null; + const options = Array.from(select.options).filter((option) => option.value); + const requestedOption = options[Math.min(2, Math.max(0, options.length - 1))] || options[0] || null; + const requestedRunId = requestedOption?.value || null; + const fallbackOption = requestedOption || null; const targetRunId = fallbackOption?.value || requestedRunId; if (!targetRunId) return { ok: false, requestedRunId, reason: "run-option-missing" }; select.value = targetRunId; select.dispatchEvent(new Event("change", { bubbles: true })); const panelReady = await waitForRun(targetRunId); - const detailPayload = await fetch("/api/runs/" + encodeURIComponent(targetRunId), { cache: "no-store" }).then((item) => item.json()).catch(() => null); + const detailPayload = await fetch(apiUrl("/api/runs/" + encodeURIComponent(targetRunId)), { cache: "no-store" }).then((item) => item.json()).catch(() => null); const detailRows = Array.isArray(detailPayload?.findings) ? detailPayload.findings : []; const expected = summarizeRows(detailRows); const observed = panelCounts(); @@ -2580,7 +2592,7 @@ const runFilterProbe = await page.evaluate(async () => { expected, matchesRunDetail, }; -}); +}, { expectedRoutePrefix }); dom.runFilterProbe = runFilterProbe; const consoleErrors = consoleMessages.filter((item) => item.type === "error");