diff --git a/scripts/ensure-playwright-chromium.mjs b/scripts/ensure-playwright-chromium.mjs index 5e158d3394bf..98dd7e9a8a40 100644 --- a/scripts/ensure-playwright-chromium.mjs +++ b/scripts/ensure-playwright-chromium.mjs @@ -151,48 +151,55 @@ export function ensurePlaywrightChromium(options = {}) { } log(`[ui-e2e] Playwright Chromium is not runnable at ${executablePath}; installing chromium.`); - const runner = resolvePlaywrightInstallRunner({ - comSpec: options.comSpec, + const canInstallSystemDependencies = shouldInstallPlaywrightSystemDependencies({ env, + getuid: options.getuid, platform: options.platform, }); - const result = spawnSync(runner.command, runner.args, { - cwd: options.cwd ?? repoRoot, - env, - shell: runner.shell, - stdio: options.stdio ?? "inherit", - windowsVerbatimArguments: runner.windowsVerbatimArguments, - }); - const status = result.status ?? 1; + const runPlaywrightInstall = (withDeps = false) => { + const runner = resolvePlaywrightInstallRunner({ + comSpec: options.comSpec, + env, + platform: options.platform, + withDeps, + }); + const result = spawnSync(runner.command, runner.args, { + cwd: options.cwd ?? repoRoot, + env, + shell: runner.shell, + stdio: options.stdio ?? "inherit", + windowsVerbatimArguments: runner.windowsVerbatimArguments, + }); + return result.status ?? 1; + }; + + const status = runPlaywrightInstall(); if (status !== 0) { + if (canInstallSystemDependencies) { + log( + `[ui-e2e] Chromium install failed in a Linux CI/root lane; installing Linux system dependencies.`, + ); + const depsStatus = runPlaywrightInstall(true); + if (depsStatus !== 0) { + return depsStatus; + } + if (existsSync(executablePath) && canRunChromiumExecutable(executablePath, spawnSync)) { + return 0; + } + log( + `[ui-e2e] Playwright install completed but Chromium is still not runnable at ${executablePath}.`, + ); + return 1; + } return status; } if (!existsSync(executablePath) || !canRunChromiumExecutable(executablePath, spawnSync)) { - if ( - shouldInstallPlaywrightSystemDependencies({ - env, - getuid: options.getuid, - platform: options.platform, - }) - ) { + if (canInstallSystemDependencies) { log( `[ui-e2e] Chromium is installed but still cannot start; installing Linux system dependencies.`, ); - const depsRunner = resolvePlaywrightInstallRunner({ - comSpec: options.comSpec, - env, - platform: options.platform, - withDeps: true, - }); - const depsResult = spawnSync(depsRunner.command, depsRunner.args, { - cwd: options.cwd ?? repoRoot, - env, - shell: depsRunner.shell, - stdio: options.stdio ?? "inherit", - windowsVerbatimArguments: depsRunner.windowsVerbatimArguments, - }); - const depsStatus = depsResult.status ?? 1; + const depsStatus = runPlaywrightInstall(true); if (depsStatus !== 0) { return depsStatus; } diff --git a/test/scripts/ensure-playwright-chromium.test.ts b/test/scripts/ensure-playwright-chromium.test.ts index fc47576e4cdd..52b83b5e395d 100644 --- a/test/scripts/ensure-playwright-chromium.test.ts +++ b/test/scripts/ensure-playwright-chromium.test.ts @@ -193,6 +193,56 @@ describe("ensurePlaywrightChromium", () => { ); }); + it("retries with Linux system dependencies when the Chromium install reports missing host deps", () => { + const logs: string[] = []; + const spawnSync = vi + .fn() + .mockReturnValueOnce({ status: 23 }) + .mockReturnValueOnce({ status: 0 }) + .mockReturnValueOnce({ status: 0 }); + let existsCalls = 0; + + expect( + ensurePlaywrightChromium({ + cwd: "/repo", + env: { CI: "1", PATH: "/bin" }, + executablePath: "/cache/chromium/chrome", + existsSync: () => ++existsCalls > 1, + getuid: () => 501, + log: (line: string) => logs.push(line), + platform: "linux", + spawnSync, + stdio: "pipe", + systemExecutablePath: "", + }), + ).toBe(0); + expect(spawnSync).toHaveBeenNthCalledWith( + 1, + "pnpm", + ["--dir", "ui", "exec", "playwright", "install", "chromium"], + { + cwd: "/repo", + env: { CI: "1", PATH: "/bin" }, + shell: false, + stdio: "pipe", + windowsVerbatimArguments: undefined, + }, + ); + expect(spawnSync).toHaveBeenNthCalledWith( + 2, + "pnpm", + ["--dir", "ui", "exec", "playwright", "install", "--with-deps", "chromium"], + { + cwd: "/repo", + env: { CI: "1", PATH: "/bin" }, + shell: false, + stdio: "pipe", + windowsVerbatimArguments: undefined, + }, + ); + expect(logs.join("\n")).toContain("installing Linux system dependencies"); + }); + it("does not install Linux system dependencies for an unprivileged local lane", () => { const spawnSync = vi .fn()