Skip to content

Addon-Vitest: Make Playwright --with-deps platform-aware to avoid sudo prompt on Linux#34121

Merged
valentinpalkovic merged 6 commits intonextfrom
copilot/fix-storybook-init-sudo-requirement
Mar 13, 2026
Merged

Addon-Vitest: Make Playwright --with-deps platform-aware to avoid sudo prompt on Linux#34121
valentinpalkovic merged 6 commits intonextfrom
copilot/fix-storybook-init-sudo-requirement

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 13, 2026

Manual testing

Create a sandbox on Linux. There should be no sudo prompt.


During storybook init, the addon-vitest postinstall was running npx playwright install chromium --with-deps, which triggers system-level package installation (apt/pacman/etc.) requiring sudo on Linux — prompting users for a root password mid-init with no clear context.

Changes

  • AddonVitestService.ts: Use --with-deps only when running in CI (process.env.CI) or on macOS/Windows (os.platform() === 'darwin' | 'win32') — officially supported platforms where it works reliably. Omit it on other platforms (Linux) to avoid the sudo prompt. After a successful install without --with-deps, a formatted warning is printed informing users they may need to install additional OS libraries for Playwright to work correctly, directing them to run Storybook Test in the Storybook UI to identify missing dependencies, and showing the manual --with-deps command. Updated JSDoc to reflect the conditional behavior.
  • postinstall.ts: Update the skipped-install warning to be platform-aware: shows npx playwright install chromium --with-deps on macOS/Windows, and npx playwright install chromium with an appended note pointing Debian/Ubuntu users to add --with-deps on other Linux platforms.
  • AddonVitestService.test.ts: Update assertions to cover all code paths: CI (with --with-deps), Linux non-CI (without --with-deps), macOS/Windows (with --with-deps), and the post-install warning on Linux.
- const playwrightCommand = ['playwright', 'install', 'chromium', '--with-deps'];
+ const platform = os.platform();
+ const useWithDeps = !!process.env.CI || platform === 'darwin' || platform === 'win32';
+ const playwrightCommand = useWithDeps
+   ? ['playwright', 'install', 'chromium', '--with-deps']
+   : ['playwright', 'install', 'chromium'];

Without --with-deps on Linux local installs, Playwright downloads the Chromium binary only, skipping OS-level dependency installation. Browser dependencies are typically already present on Linux systems via the distro package manager. On macOS, Windows, and in CI environments, --with-deps is retained to ensure all required system dependencies are installed. On Linux, users are shown a post-install warning with guidance on how to check for and install any missing dependencies.

Original prompt

This section details on the original issue you should resolve

<issue_title>[Bug]: Storybook init can require sudo because of Playwright install</issue_title>
<issue_description>### Describe the bug

When initting Storybook and getting addon-vitest, the addon's postinstall installs Playwright with dependencies:

await packageManager.executeCommand({
command: 'npx',
args: ['playwright', 'install', 'chromium', '--with-deps'],
});

This can lead to the terminal require sudo, because that can be necessary to install the browser dependencies. This requirement can scare some users off, because they are not just giving sudo to the playwright install, but to the whole init process, which is opaque to the user and less secure.

Additional context

Originally reported by @dominikg. I have not myself been able to reproduce this, it seems like Playwright refuses to install browsers on my machine, relying on some cached installs that I can't remove.

This the log shown:

› Configuring Playwright with Chromium (this might take some time):
  npx playwright install chromium --with-deps
[sudo] password for USER: 

If we don't add --with-deps it just downloads the binaries without using sudo. The deps are usually present from the system installed chromium and managed by the packaging system of the linux distro. It can lead to issues if the system installed chromium has deps that are incompatible from the one playwright wants to use, but that might not be an issue in practice.</issue_description>

Comments on the Issue (you are @copilot in this section)

@Sidnioulz I want to add to this that some commands, like `yarn start` in the monorepo, run install commands in quiet mode, so users don't even know it's Playwright asking for a password.

Besides, Playwright fails install on many Linux distros, and it tries for those distros to serve a 5 year old APT package for Ubuntu, which of course fails (all the package's dependencies have had multiple updates since then).

microsoft/playwright#26482 (comment) provides a command which apparently installs browsers without triggering this whole package download and sudo request. We might want to look into adding that --shell-only command if it has no relevant side effects for us.</comment_new>
<comment_new>@Sidnioulz

it's --only-shell https://playwright.dev/docs/test-cli#install-browsers

i think you can only run headless tests then. might work for repo internal ci scripts but not user facing scripts as users might want to execute with browser ui showing

Thanks @dominikg! I suspect this might be enough for Addon Vitest, as it runs in CLI and outputs results in the UI and/or CLI. Let's see if the team believe --headed must be available by default.</comment_new>
<comment_new>@Sidnioulz
Just tested rewriting addon-vitest's postinstall and sudo will keep being triggered until --with-deps is removed. Now, on my Arch system I can install with --only-shell and without --with-deps, and the addon runs fine because I already have playwright locally installed.

Obviously this means users without playwright will run into trouble.

One thing we could possibly do is use execa to run playwright --version and check if it's already installed; in which case --with-deps is redundant on Linux.

We could also try and detect distros. Playwright only supports Debian/Ubuntu so that shouldn't be too much of a stretch. Plenty of options to detect distros.

ANd if we figure out that users do need to install Playwright themselves, provide a big fat visible warning for them so they know they have to do it.</comment_new>
<comment_new>@Sidnioulz

even though theg claim it only works w debian/ubuntu i haven't run into native issues with it on arch (manjaro) for years

Agreed, it's the NPM install DX that's broken. They don't know how to install it so they prompt you into typing a password and start downloading an Ubuntu 20 package, then they cry wolf because the package is using different dependency versions from the ones locally installed.

Meanwhile, not installing Playwright via NPM results in a functional experience for me on Arch.</comment_new>
<comment_new>@Sidnioulz
Unfortunately it's not exactly the last step. It still does one or two things with Vitest config files afterwards.

@JReinhold, do you reckon it's doable to put the playwright install step at the very end of the process?

I just installed Storybook and I really didn't like that it asked for a root password, because I don't know how it will affect my system. Does it install something using pacman? Does it install something in /usr/bin? I just pressed Ctrl+C and ...


💬 Send tasks to Copilot coding agent from Slack and Teams to turn conversations into code. Copilot posts an update in your thread when it's finished.

Summary by CodeRabbit

  • Bug Fixes
    • Playwright install guidance now avoids forcing extra system-dependency flags on unsupported platforms in local runs, reducing unnecessary install steps.
  • New Features
    • Installer messages are platform-aware and show the recommended command for your OS; when dependencies are omitted, a clear note explains how to install them if needed.
  • Tests
    • Expanded cross-platform and CI/non‑CI test coverage for install behavior.

…rement

Co-authored-by: valentinpalkovic <5889929+valentinpalkovic@users.noreply.github.com>
Copilot AI changed the title [WIP] [Bug] Fix Storybook init sudo requirement during Playwright install fix(addon-vitest): remove --with-deps from Playwright install to avoid sudo prompt Mar 13, 2026
Copilot AI requested a review from valentinpalkovic March 13, 2026 07:50
@valentinpalkovic valentinpalkovic changed the title fix(addon-vitest): remove --with-deps from Playwright install to avoid sudo prompt Addon-Vitest: Remove --with-deps from Playwright install to avoid sudo prompt Mar 13, 2026
@valentinpalkovic
Copy link
Copy Markdown
Contributor

@copilot Add back '--with-deps' in CI environments (process.env.CI)

@nx-cloud
Copy link
Copy Markdown

nx-cloud bot commented Mar 13, 2026

View your CI Pipeline Execution ↗ for commit bfb242e

Command Status Duration Result
nx run-many -t compile -c production --parallel=1 ✅ Succeeded 5m 23s View ↗

☁️ Nx Cloud last updated this comment at 2026-03-13 12:52:57 UTC

Co-authored-by: valentinpalkovic <5889929+valentinpalkovic@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 13, 2026

@copilot Add back '--with-deps' in CI environments (process.env.CI)

Done in 590dffb. The playwright command now uses --with-deps only when process.env.CI is set, and falls back to plain playwright install chromium otherwise. Added tests for both code paths.

Copilot AI changed the title Addon-Vitest: Remove --with-deps from Playwright install to avoid sudo prompt Addon-Vitest: Remove --with-deps from Playwright install to avoid sudo prompt on local installs Mar 13, 2026
@valentinpalkovic valentinpalkovic moved this to In Progress in Core Team Projects Mar 13, 2026
@valentinpalkovic valentinpalkovic marked this pull request as ready for review March 13, 2026 08:49
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 13, 2026

📝 Walkthrough

Walkthrough

Make Playwright's Chromium install command conditional on platform and CI: include --with-deps on CI or on officially supported platforms (macOS/Windows), omit it otherwise; update post-install messaging and tests to reflect platform-aware commands and Linux-specific notes.

Changes

Cohort / File(s) Summary
Service implementation
code/core/src/cli/AddonVitestService.ts
Add node:os platform detection; compute useWithDeps true for CI or darwin/win32; build Playwright command to include --with-deps only when appropriate; emit Linux-specific follow-up warning when dependencies were not installed.
Postinstall script
code/addons/vitest/src/postinstall.ts
Use platform-aware guidance when installation is skipped: choose between npx playwright install chromium --with-deps and npx playwright install chromium and include an optional Linux note.
Tests
code/core/src/cli/AddonVitestService.test.ts
Add node:os mocking; split and expand tests to cover non-CI, CI, and platform-specific (darwin,win32,linux) behaviors and the Linux dependency warning; update assertions to match new command variants.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant AddonVitestService
  participant OS as node:os
  participant Child as ChildProcess

  User->>AddonVitestService: trigger installPlaywright
  AddonVitestService->>OS: os.platform()
  OS-->>AddonVitestService: platform
  AddonVitestService->>AddonVitestService: compute useWithDeps (CI || darwin || win32)
  AddonVitestService->>Child: spawn("npx playwright install chromium" [+ "--with-deps" if useWithDeps])
  Child-->>AddonVitestService: exit/ok or error
  AddonVitestService-->>User: print success or platform-specific warning (Linux deps note when omitted)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
📝 Coding Plan
  • Generate coding plan for human review comments

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

CodeRabbit can generate a title for your PR based on the changes.

Add @coderabbitai placeholder anywhere in the title of your PR and CodeRabbit will replace it with a title based on the changes in the PR. You can change the placeholder by changing the reviews.auto_title_placeholder setting.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@code/core/src/cli/AddonVitestService.test.ts`:
- Around line 425-431: Move the inline vi.mocked(prompt.executeTaskWithSpinner)
implementations into the test suite's beforeEach: create a beforeEach that sets
vi.mocked(prompt.executeTaskWithSpinner).mockImplementation(async (factory:
ChildProcessFactory | ChildProcessFactory[]) => { commandFactory =
Array.isArray(factory) ? factory[0] : factory; commandFactory(); }); also reset
commandFactory to undefined (or a known initial state) at the start of
beforeEach so each test gets a clean setup, and remove the duplicate inline
mocks found in the two test cases (including the other occurrence around the
second test). Ensure both tests rely on the shared behavior provided by the
beforeEach mock rather than defining their own mock implementations.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3b4a9129-cc60-4912-83cc-73ce9aacecc3

📥 Commits

Reviewing files that changed from the base of the PR and between 1210a3a and 590dffb.

📒 Files selected for processing (3)
  • code/addons/vitest/src/postinstall.ts
  • code/core/src/cli/AddonVitestService.test.ts
  • code/core/src/cli/AddonVitestService.ts

Comment on lines +425 to +431
vi.mocked(prompt.executeTaskWithSpinner).mockImplementation(
async (factory: ChildProcessFactory | ChildProcessFactory[]) => {
commandFactory = Array.isArray(factory) ? factory[0] : factory;
// Simulate the child process completion
commandFactory();
}
);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Move spinner mock implementations out of test cases and into beforeEach.

prompt.executeTaskWithSpinner is mocked inline in both tests; that breaks the repo’s Vitest mocking rules for centralized setup.

♻️ Suggested refactor
 describe('installPlaywright', () => {
+  type ChildProcessFactory = (signal?: AbortSignal) => ResultPromise;
+
   beforeEach(() => {
     // Mock the logger methods used in installPlaywright
     vi.mocked(logger.log).mockImplementation(() => {});
     vi.mocked(logger.warn).mockImplementation(() => {});
     // Mock getPackageCommand to return a string
     vi.mocked(mockPackageManager.getPackageCommand).mockReturnValue(
       'npx playwright install chromium'
     );
+    vi.mocked(prompt.executeTaskWithSpinner).mockImplementation(
+      async (factory: ChildProcessFactory | ChildProcessFactory[]) => {
+        const commandFactory = Array.isArray(factory) ? factory[0] : factory;
+        commandFactory();
+        return undefined;
+      }
+    );
   });

   it('should execute playwright install command', async () => {
     const originalCI = process.env.CI;
     delete process.env.CI;
     try {
-      type ChildProcessFactory = (signal?: AbortSignal) => ResultPromise;
-      let commandFactory: ChildProcessFactory | ChildProcessFactory[];
       vi.mocked(prompt.confirm).mockResolvedValue(true);
-      vi.mocked(prompt.executeTaskWithSpinner).mockImplementation(
-        async (factory: ChildProcessFactory | ChildProcessFactory[]) => {
-          commandFactory = Array.isArray(factory) ? factory[0] : factory;
-          // Simulate the child process completion
-          commandFactory();
-        }
-      );

       await service.installPlaywright();

       expect(mockPackageManager.runPackageCommand).toHaveBeenCalledWith({
         args: ['playwright', 'install', 'chromium'],
@@
   it('should execute playwright install command with --with-deps in CI', async () => {
     const originalCI = process.env.CI;
     process.env.CI = 'true';
     try {
-      type ChildProcessFactory = (signal?: AbortSignal) => ResultPromise;
-      let commandFactory: ChildProcessFactory | ChildProcessFactory[];
       vi.mocked(prompt.confirm).mockResolvedValue(true);
-      vi.mocked(prompt.executeTaskWithSpinner).mockImplementation(
-        async (factory: ChildProcessFactory | ChildProcessFactory[]) => {
-          commandFactory = Array.isArray(factory) ? factory[0] : factory;
-          commandFactory();
-        }
-      );

       await service.installPlaywright();

       expect(mockPackageManager.runPackageCommand).toHaveBeenCalledWith({

As per coding guidelines “Avoid inline mock implementations within test cases in Vitest tests” and “Implement mock behaviors in beforeEach blocks in Vitest tests”.

Also applies to: 454-459

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@code/core/src/cli/AddonVitestService.test.ts` around lines 425 - 431, Move
the inline vi.mocked(prompt.executeTaskWithSpinner) implementations into the
test suite's beforeEach: create a beforeEach that sets
vi.mocked(prompt.executeTaskWithSpinner).mockImplementation(async (factory:
ChildProcessFactory | ChildProcessFactory[]) => { commandFactory =
Array.isArray(factory) ? factory[0] : factory; commandFactory(); }); also reset
commandFactory to undefined (or a known initial state) at the start of
beforeEach so each test gets a clean setup, and remove the duplicate inline
mocks found in the two test cases (including the other occurrence around the
second test). Ensure both tests rely on the shared behavior provided by the
beforeEach mock rather than defining their own mock implementations.

Copy link
Copy Markdown
Member

@Sidnioulz Sidnioulz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is SO MUCH NICER. No more buggy sudo prompt.

I would suggest using os.platform, on top of CI, to still install deps on win and darwin as we know it works for those users.

I would also suggest writing a big warning stating we skipped deps install for playwright and users may have extra work to do depending on their distro. I would print the "--with-deps" command as part of that warning for Debian/Ubuntu users.

Comment thread code/core/src/cli/AddonVitestService.ts Outdated
const errors: string[] = [];

const playwrightCommand = ['playwright', 'install', 'chromium', '--with-deps'];
const playwrightCommand = process.env.CI
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Here I would suggest also enabling --with-deps for os.platform darwin and win32 as they are officially supported.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 8de539a. --with-deps is now enabled for darwin and win32 (in addition to CI).

Comment thread code/addons/vitest/src/postinstall.ts Outdated
logger.warn(dedent`
Playwright browser binaries installation skipped. Please run the following command manually later:
${CLI_COLORS.cta('npx playwright install chromium --with-deps')}
${CLI_COLORS.cta('npx playwright install chromium')}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot here I would use os.platform to print the --with-deps command for darwin and win32 users, and for other users:

 ${CLI_COLORS.cta('npx playwright install chromium')} (add --with-deps if using Debian or Ubuntu)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 8de539a. On macOS/Windows the warning shows npx playwright install chromium --with-deps; on other platforms it shows npx playwright install chromium with an appended note: Note: add --with-deps to the command above if you are on Debian or Ubuntu.

…tros

Co-authored-by: Sidnioulz <5108577+Sidnioulz@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 13, 2026

This is SO MUCH NICER. No more buggy sudo prompt.

I would suggest using os.platform, on top of CI, to still install deps on win and darwin as we know it works for those users.
...

Done in 8de539a. os.platform() is now used alongside process.env.CI to gate --with-deps — it's enabled on darwin, win32, and in CI. On other Linux platforms the command omits --with-deps and the skip warning includes the Debian/Ubuntu note.

Copilot AI changed the title Addon-Vitest: Remove --with-deps from Playwright install to avoid sudo prompt on local installs Addon-Vitest: Make Playwright --with-deps platform-aware to avoid sudo prompt on Linux Mar 13, 2026
Copilot AI requested a review from Sidnioulz March 13, 2026 10:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

[Bug]: Storybook init can require sudo because of Playwright install

4 participants