From 0c26216b85cce9ccb4f8233d1d03eb3951005b40 Mon Sep 17 00:00:00 2001 From: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> Date: Sat, 29 Aug 2026 13:47:03 -0300 Subject: [PATCH] fix(release): the packaged-app smoke verifies the database opened, not a driver line the primary path never prints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The packaged app does open SQLite during the smoke (migrations run, [DB] Added … column, cache_size lines) but its primary open path prints no "[DB] Driver: …" line — only the recovery path and the sql.js fallback do — so the #7592 assertion demanded a line that never exists and every Linux release leg failed on it. The guard now: rejects the sql.js fallback line (which the fallback always prints), accepts a native driver line, and otherwise accepts demonstrable database activity; after readiness the smoke requests /api/monitoring/health and waits for that activity, outside the readiness retry loop so a missing database is a verdict, not a retry. The previous commit on this branch had the wait inside the loop and made ci.yml's Electron Package Smoke fail; electron-smoke-script suite 10/10. --- scripts/dev/smoke-electron-packaged.mjs | 36 +++++++++++++++--------- tests/unit/electron-smoke-script.test.ts | 35 +++++++++++++++++------ 2 files changed, 49 insertions(+), 22 deletions(-) diff --git a/scripts/dev/smoke-electron-packaged.mjs b/scripts/dev/smoke-electron-packaged.mjs index e134f5a5f0..688524bf7b 100644 --- a/scripts/dev/smoke-electron-packaged.mjs +++ b/scripts/dev/smoke-electron-packaged.mjs @@ -125,25 +125,27 @@ function discoverPackagedExecutable() { /** * The packaged app opens SQLite lazily: `/login` (the readiness URL) never touches the - * database, so a smoke that only waits for readiness sees no "[DB] Driver: ..." line at - * all and `assertNativeDriverSelected` cannot tell a native driver from nothing (v3.8.50 - * re-attach, run 33251755872: every leg green up to the smoke, then this). After readiness - * the smoke now requests a DB-backed endpoint and waits for the driver line to appear. + * database, so a smoke that only waits for readiness sees no `[DB]` line at all. After + * readiness the smoke requests a DB-backed endpoint and waits for evidence that the + * database opened. The primary open path does NOT print "[DB] Driver: ..." (only the + * recovery path and the sql.js fallback do), so the evidence is any `[DB]`/`[Migration]` + * startup line — and the #7592 guard below rejects the fallback's own line explicitly. */ export const DB_TOUCH_PATH = "/api/monitoring/health"; -const DB_DRIVER_LINE_PATTERN = /\[DB\] Driver: /; +export const DB_OPEN_EVIDENCE_PATTERN = + /\[DB\] (Driver: |SQLite database ready|Added [^\n]* column|Changing cache_size|cache_size changed)|\[Migration\] (Applied|Pre-migration backup)/; -export async function waitForDriverLine(getLogs, { timeoutMs = 15_000, pollMs = 250 } = {}) { +export async function waitForDatabaseOpen(getLogs, { timeoutMs = 15_000, pollMs = 250 } = {}) { const startedAt = Date.now(); while (Date.now() - startedAt < timeoutMs) { const logs = getLogs(); assertNoFatalLogs(logs); - if (DB_DRIVER_LINE_PATTERN.test(logs)) return logs; + if (DB_OPEN_EVIDENCE_PATTERN.test(logs)) return logs; await sleep(pollMs); } throw new Error( - `Packaged Electron app logged no "[DB] Driver: ..." line within ${timeoutMs}ms of touching ` + - `${DB_TOUCH_PATH} — the database never opened, so the SQLite driver cannot be verified.` + `Packaged Electron app logged no [DB]/[Migration] startup line within ${timeoutMs}ms of ` + + `touching ${DB_TOUCH_PATH} — the database never opened, so the SQLite driver cannot be verified.` ); } @@ -156,11 +158,11 @@ async function openDatabaseForSmoke({ logs, smokeUrl }) { ); } catch (error) { console.log( - `[electron-smoke] touching ${touchUrl} failed (${error instanceof Error ? error.message : String(error)}) — waiting for the driver line anyway` + `[electron-smoke] touching ${touchUrl} failed (${error instanceof Error ? error.message : String(error)}) — waiting for the database anyway` ); } - await waitForDriverLine(() => logs.value); - console.log("[electron-smoke] database opened — driver line captured"); + await waitForDatabaseOpen(() => logs.value); + console.log("[electron-smoke] database opened"); } async function fetchWithTimeout(url, timeoutMs) { @@ -490,8 +492,13 @@ export function assertNativeDriverSelected(logs) { ); } + // The primary open path prints no "[DB] Driver: ..." line at all (only the recovery path and + // the sql.js fallback do), so a database that demonstrably opened WITHOUT the fallback's own + // line is the native driver — that is exactly what #7592 guards. + if (DB_OPEN_EVIDENCE_PATTERN.test(logs)) return; + throw new Error( - "Packaged Electron app logs contain no '[DB] Driver: ...' line — cannot confirm which SQLite " + + "Packaged Electron app logs show no database activity at all — cannot confirm which SQLite " + "driver loaded." ); } @@ -517,7 +524,6 @@ async function waitForReady({ logs, smokeUrl, timeoutMs, settleMs, exitState }) if (response.status === 200) { assertNoFatalLogs(logs.value); console.log(`[electron-smoke] ready: ${smokeUrl} returned HTTP 200`); - await openDatabaseForSmoke({ logs, smokeUrl }); await settleAfterReady({ getExitState: () => ({ exitCode: exitState.exitCode, signalCode: exitState.signalCode }), logs, @@ -586,6 +592,8 @@ async function launchAndCollectLogs({ try { await waitForReady({ logs, smokeUrl, timeoutMs, settleMs, exitState }); + // Outside waitForReady on purpose: a missing database is a verdict, not a readiness retry. + await openDatabaseForSmoke({ logs, smokeUrl }); return logs.value; } catch (error) { if (!streamLogs) { diff --git a/tests/unit/electron-smoke-script.test.ts b/tests/unit/electron-smoke-script.test.ts index 57abbd9305..c302c19aae 100644 --- a/tests/unit/electron-smoke-script.test.ts +++ b/tests/unit/electron-smoke-script.test.ts @@ -7,7 +7,7 @@ import { FATAL_LOG_PATTERNS, LINUX_EXECUTABLE_NAMES, stopApp, - waitForDriverLine, + waitForDatabaseOpen, DB_TOUCH_PATH, } from "../../scripts/dev/smoke-electron-packaged.mjs"; @@ -96,27 +96,46 @@ test("electron smoke flags a cold-restart fallback to the sql.js WASM driver", ( test("electron smoke flags startup logs missing any driver selection line", () => { assert.throws( () => assertNativeDriverSelected("[electron] [server] listening on 20128"), - /no '\[DB\] Driver: \.\.\.' line/ + /no database activity/ ); }); -test("electron smoke waits for the [DB] Driver line after touching a DB-backed endpoint", async () => { +test("electron smoke waits for database-open evidence after touching a DB-backed endpoint", async () => { assert.equal(DB_TOUCH_PATH, "/api/monitoring/health"); let logs = "[electron] [Server] [STARTUP] ready\n"; setTimeout(() => { - logs += "[electron] [Server] [DB] Driver: better-sqlite3 | file: /tmp/x/storage.sqlite\n"; + logs += "[electron] [Server] [DB] Added usage_history.combo_strategy column\n"; }, 60); - const seen = await waitForDriverLine(() => logs, { timeoutMs: 2_000, pollMs: 20 }); - assert.match(seen, /\[DB\] Driver: better-sqlite3/); + const seen = await waitForDatabaseOpen(() => logs, { timeoutMs: 2_000, pollMs: 20 }); + assert.match(seen, /\[DB\] Added/); }); test("electron smoke fails clearly when the database never opens", async () => { await assert.rejects( () => - waitForDriverLine(() => "[electron] [Server] [STARTUP] ready\n", { + waitForDatabaseOpen(() => "[electron] [Server] [STARTUP] ready\n", { timeoutMs: 120, pollMs: 20, }), - /logged no "\[DB\] Driver: \.\.\." line within 120ms/ + /logged no \[DB\]\/\[Migration\] startup line within 120ms/ + ); +}); + +test("electron smoke driver guard: native line, DB evidence and sql.js fallback", () => { + assert.doesNotThrow(() => + assertNativeDriverSelected("[DB] Driver: better-sqlite3 | file: /tmp/x/storage.sqlite\n") + ); + assert.doesNotThrow(() => + assertNativeDriverSelected( + "[electron] [Server] [DB] Added call_logs.session_tag column\n[electron] [Server] [Migration] Applied: 046_database_settings\n" + ) + ); + assert.throws( + () => assertNativeDriverSelected("[DB] Driver: sql.js | file: /tmp/x/storage.sqlite\n"), + /sql\.js \(WASM\) driver/ + ); + assert.throws( + () => assertNativeDriverSelected("[STARTUP] nothing here\n"), + /no database activity/ ); });