@galda/cli 0.10.68 → 0.10.70

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/engine/shot.mjs CHANGED
@@ -21,6 +21,7 @@ import { existsSync, mkdirSync, statSync } from 'node:fs';
21
21
  import { dirname, resolve } from 'node:path';
22
22
  import { createRequire } from 'node:module';
23
23
  import { parseShotArgs, shotTargetUrl, pickChromePath } from './lib.mjs';
24
+ import { chromeUpdatePending } from './chrome-safety.mjs';
24
25
 
25
26
  const require = createRequire(import.meta.url);
26
27
 
@@ -42,6 +43,9 @@ const url = shotTargetUrl(opt.target, (p) => resolve(process.cwd(), p));
42
43
  const out = resolve(process.cwd(), opt.out);
43
44
  const chrome = pickChromePath(process.env, existsSync);
44
45
  if (!chrome) die('Chrome not found — install Google Chrome or set CHROME_PATH to the binary');
46
+ if (process.env.GALDA_TEST_ALLOW_PENDING_CHROME !== '1' && chromeUpdatePending(chrome)) {
47
+ die('Chrome just updated while it was open. Restart Chrome, then retry the screenshot.');
48
+ }
45
49
 
46
50
  let puppeteer;
47
51
  try {
package/engine/verify.mjs CHANGED
@@ -6,10 +6,14 @@
6
6
 
7
7
  import { spawnSync } from 'node:child_process';
8
8
  import { createRequire } from 'node:module';
9
+ import { mkdtempSync, rmSync } from 'node:fs';
10
+ import { tmpdir } from 'node:os';
11
+ import { join } from 'node:path';
9
12
 
10
13
  const require = createRequire(import.meta.url);
11
14
  const puppeteer = require('puppeteer-core');
12
15
  import { existsSync } from 'node:fs';
16
+ import { chromeUpdatePending } from './chrome-safety.mjs';
13
17
 
14
18
  const CHROME_CANDIDATES = [
15
19
  process.env.CHROME_PATH,
@@ -109,12 +113,28 @@ export async function exerciseUi(page, ui) {
109
113
  // still screenshot is produced) — used for a cheap baseline ("before") shot
110
114
  // where a comparison image is enough and a second full video isn't worth
111
115
  // the extra time/flakiness.
112
- export async function runVerification({ entryUrl, verify, outBase, record = true, viewport = null }) {
113
- const browser = await puppeteer.launch({
114
- executablePath: CHROME, headless: 'new',
115
- args: ['--no-first-run', '--hide-scrollbars'],
116
- });
116
+ export async function runVerification({
117
+ entryUrl, verify, outBase, record = true, viewport = null,
118
+ browserUpdatePending = () => chromeUpdatePending(CHROME),
119
+ }) {
120
+ if (browserUpdatePending()) {
121
+ return {
122
+ pass: false,
123
+ inconclusive: true,
124
+ detail: 'Chrome was updated while it was open. Automatic browser verification was safely deferred; restart Chrome to enable it.',
125
+ shotPath: null,
126
+ videoPath: null,
127
+ gifPath: null,
128
+ };
129
+ }
130
+ const userDataDir = mkdtempSync(join(tmpdir(), 'galda-verify-chrome-'));
131
+ let browser;
117
132
  try {
133
+ browser = await puppeteer.launch({
134
+ executablePath: CHROME, headless: 'new',
135
+ userDataDir,
136
+ args: ['--no-first-run', '--hide-scrollbars', '--disable-crash-reporter'],
137
+ });
118
138
  const page = await browser.newPage();
119
139
  await page.setViewport(viewport ?? { width: 900, height: 640, deviceScaleFactor: 2 });
120
140
  const consoleErrors = [];
@@ -160,6 +180,7 @@ export async function runVerification({ entryUrl, verify, outBase, record = true
160
180
  if (consoleErrors.length) result.detail += ` | page errors: ${consoleErrors.join(' / ').slice(0, 300)}`;
161
181
  return { ...result, shotPath, videoPath: finalVideo, gifPath };
162
182
  } finally {
163
- await browser.close();
183
+ await browser?.close().catch(() => {});
184
+ rmSync(userDataDir, { recursive: true, force: true });
164
185
  }
165
186
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@galda/cli",
3
- "version": "0.10.68",
3
+ "version": "0.10.70",
4
4
  "type": "module",
5
5
  "description": "Galda - hand off work to Claude Code or Codex, get proof back. Runs on your existing subscription, no extra API cost.",
6
6
  "scripts": {