From 7bee5ca4eff9e98b2ffdbdae858d10c5bd114775 Mon Sep 17 00:00:00 2001 From: OneByJorah Date: Sun, 18 Oct 2026 04:20:37 +0000 Subject: [PATCH] fix(ci): sync hardened reusable screenshots workflow; wait for real dashboard render MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - reusable-screenshots.yml: sync hardened copy from repo-template — force-push bot branch (regenerated wholesale), PR-existence check guarded to OPEN state, concurrent PR-create races result in success instead of failure - screenshots.mjs: dashboard waitFor targets the rendered #page-title (visible) instead of the permanently hidden #app-ready marker; per-page state support - verified locally: app serves on 127.0.0.1:5000, script captures dashboard and public screenshots with scrub checks passing --- .github/workflows/reusable-screenshots.yml | 7 ++++--- scripts/screenshots.mjs | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/reusable-screenshots.yml b/.github/workflows/reusable-screenshots.yml index b8525cf..939b755 100644 --- a/.github/workflows/reusable-screenshots.yml +++ b/.github/workflows/reusable-screenshots.yml @@ -107,11 +107,12 @@ jobs: git add "$OUT_DIR" if git diff --cached --quiet; then echo "No screenshot changes"; exit 0; fi git commit -m "docs: update screenshots" - git push --force-with-lease origin "$BRANCH" - if gh pr view "$BRANCH" >/dev/null 2>&1; then + git push --force origin "$BRANCH" # bot branch is regenerated wholesale each run + if gh pr view "$BRANCH" --state OPEN >/dev/null 2>&1; then echo "PR already open for $BRANCH" else gh pr create --base "$DEFAULT_BRANCH" --head "$BRANCH" \ --title "docs: update screenshots" \ - --body "Automated screenshots captured from the demo stack. Review each image for real data before merging." + --body "Automated screenshots captured from the demo stack. Review each image for real data before merging." \ + || echo "PR create skipped (already exists from a concurrent run) - success outcome" fi diff --git a/scripts/screenshots.mjs b/scripts/screenshots.mjs index 5367562..bfa618d 100644 --- a/scripts/screenshots.mjs +++ b/scripts/screenshots.mjs @@ -17,7 +17,8 @@ const RECORD = process.env.RECORD === "1"; // Edit this list per project: one entry per meaningful screen. const PAGES = [ - { name: "dashboard", path: "/", waitFor: "#app-ready" }, + // "#app-ready" is a hidden marker span; wait for the real rendered title instead. + { name: "dashboard", path: "/", waitFor: "#page-title", state: "visible" }, { name: "public", path: "/public" }, ]; @@ -54,7 +55,7 @@ let failed = false; for (const p of PAGES) { const page = await context.newPage(); await page.goto(new URL(p.path, BASE).toString(), { waitUntil: "networkidle" }); - if (p.waitFor) await page.waitForSelector(p.waitFor, { state: "attached", timeout: 15000 }); + if (p.waitFor) await page.waitForSelector(p.waitFor, { state: p.state || "attached", timeout: 15000 }); const text = (await page.evaluate(() => document.body.innerText)) + "\n" + (await page.title()); const hits = FORBIDDEN.filter((f) => f.re.test(text)).map((f) => f.label);