From dfebda73af2a7c10e600cc7e988ef80d54e9b6e3 Mon Sep 17 00:00:00 2001 From: dan bachelder <325706+dbachelder@users.noreply.github.com> Date: Wed, 11 Mar 2026 17:19:33 -0700 Subject: [PATCH] fix: avoid sudo prompts in postinstall (#73) Co-authored-by: Ada --- scripts/postinstall.js | 47 ++++++++++++++++++++++++++++++------- src/tests/app-smoke.test.ts | 22 +++++++++++++++++ 2 files changed, 60 insertions(+), 9 deletions(-) diff --git a/scripts/postinstall.js b/scripts/postinstall.js index a06519ef8..47d8af090 100644 --- a/scripts/postinstall.js +++ b/scripts/postinstall.js @@ -33,23 +33,52 @@ const banner = ` ${green}✓${reset} Installed successfully\n` + ` ${dim}Run ${reset}${cyan}gsd${reset}${dim} to get started.${reset}\n` +function run(command, options = {}) { + return execSync(command, { + cwd: resolve(__dirname, '..'), + encoding: 'utf8', + stdio: ['ignore', 'pipe', 'pipe'], + ...options, + }) +} + +function printCaptured(output) { + if (output) process.stderr.write(output) +} + process.stderr.write(banner) // Apply patches to upstream dependencies (non-fatal) try { - execSync('npx patch-package', { stdio: 'inherit', cwd: resolve(__dirname, '..') }) + const output = run('npx patch-package') + printCaptured(output) process.stderr.write(`\n ${green}✓${reset} Patches applied\n`) -} catch { +} catch (error) { + printCaptured(error.stdout) + printCaptured(error.stderr) process.stderr.write(`\n ${yellow}⚠${reset} Failed to apply patches — run ${cyan}npx patch-package${reset} manually\n`) } -// Install Playwright chromium for browser tools (non-fatal) +// Install Playwright chromium for browser tools (non-fatal). +// We intentionally avoid --with-deps here because install scripts should not +// block on interactive sudo prompts. Playwright validates host requirements +// after download; if Linux libs are missing, suggest the explicit follow-up. try { - execSync('npx playwright install chromium', { stdio: 'inherit' }) + const output = run('npx playwright install chromium') + printCaptured(output) process.stderr.write(`\n ${green}✓${reset} Browser tools ready\n\n`) -} catch { - const hint = os.platform() === 'linux' - ? `${cyan}npx playwright install --with-deps chromium${reset}` - : `${cyan}npx playwright install chromium${reset}` - process.stderr.write(`\n ${yellow}⚠${reset} Browser tools unavailable — run ${hint} to enable\n\n`) +} catch (error) { + const output = `${error.stdout ?? ''}${error.stderr ?? ''}` + printCaptured(output) + + if (os.platform() === 'linux' && output.includes('Host system is missing dependencies to run browsers.')) { + process.stderr.write( + `\n ${yellow}⚠${reset} Browser downloaded, but Linux system dependencies are missing.\n` + + ` ${dim}Run ${reset}${cyan}sudo npx playwright install-deps chromium${reset}${dim} to finish setup.${reset}\n\n` + ) + } else { + process.stderr.write( + `\n ${yellow}⚠${reset} Browser tools unavailable — run ${cyan}npx playwright install chromium${reset} to enable\n\n` + ) + } } diff --git a/src/tests/app-smoke.test.ts b/src/tests/app-smoke.test.ts index 7e8e24181..788bb5882 100644 --- a/src/tests/app-smoke.test.ts +++ b/src/tests/app-smoke.test.ts @@ -308,6 +308,28 @@ test("tarball installs and gsd binary resolves", async () => { } }); +test("postinstall avoids sudo during browser setup and suggests install-deps only when needed", () => { + const postinstall = readFileSync(join(projectRoot, "scripts", "postinstall.js"), "utf-8"); + + assert.doesNotMatch( + postinstall, + /playwright install chromium[^\n]*--with-deps/, + "postinstall does not request sudo-backed Playwright deps during npm install", + ); + assert.ok( + postinstall.includes("npx playwright install chromium"), + "postinstall downloads Chromium during install", + ); + assert.ok( + postinstall.includes("Host system is missing dependencies to run browsers."), + "postinstall detects Playwright's missing Linux dependency warning", + ); + assert.ok( + postinstall.includes("sudo npx playwright install-deps chromium"), + "postinstall suggests the explicit follow-up command only when Linux deps are missing", + ); +}); + // ═══════════════════════════════════════════════════════════════════════════ // 8. Launch → extensions load → no errors on stderr // ═══════════════════════════════════════════════════════════════════════════