Skip to content

feat: add a playwright feature - #11

Merged
ashwin153 merged 7 commits into
mainfrom
claude/devcontainer-feature-migration-u53qfp
Aug 5, 2026
Merged

feat: add a playwright feature#11
ashwin153 merged 7 commits into
mainfrom
claude/devcontainer-feature-migration-u53qfp

Conversation

@ashwin153

@ashwin153 ashwin153 commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Softlight Overview

UX Score: 5/5

Softlight reviewed this change and found no issues.

To run Softlight again, click here or comment @softlight.

Adds a playwright feature that installs the Playwright CLI globally and downloads a Chromium build at image-build time, so containers do not pay for an npm install and a browser download on every start.

This is the feature from orianna-ai/devcontainer#82, moved here so it is published and shared rather than living locally under that repo's .devcontainer/features.

Changes

  • src/playwright/devcontainer-feature.json — sets PLAYWRIGHT_BROWSERS_PATH via containerEnv, declares installsAfter on common-utils and node, and exposes a version option for the @playwright/cli npm package.
  • src/playwright/install.sh — sources nvm when npm is not already on PATH, installs @playwright/cli, then runs install-deps chromium and install chromium through the playwright-core CLI (@playwright/cli never links that binary). Restores the pre-existing ownership of the global module tree afterwards, so the node feature's remote user can keep installing global packages at run time.
  • src/playwright/README.md — generated with devcontainer features generate-docs.
  • test/playwright/ — a scenario on base:ubuntu-22.04 plus the node feature, checking that playwright-cli is on PATH, that PLAYWRIGHT_BROWSERS_PATH is exported, that a Chromium build landed there, and that the path is still readable and traversable as the remote user.

Notes

Browsers land in /usr/local/share/ms-playwright rather than Playwright's default $HOME/.cache, because a sandbox may point HOME at a per-pod volume — anything baked into the image's home directory is invisible there. PLAYWRIGHT_BROWSERS_PATH is declared in devcontainer-feature.json so it is baked into the image environment, which points both the install and every later run at the same directory.

The version option defaults to latest here, matching cloud-sql-proxy; the pin to 0.1.17 from the original PR moves to the call site in the devcontainer repo.

Testing

pre-commit run --all-files passes, and the manifest validates against the devcontainer feature schema. The scenario test needs Docker, so it runs in CI rather than locally.


Generated by Claude Code


Note

Low Risk
New optional devcontainer feature and install script only; no changes to existing runtime services or auth/data paths.

Overview
Adds a new playwright devcontainer feature that bakes @playwright/cli and a Chromium build into the image at build time, avoiding npm install and browser download on every container start.

The feature sets PLAYWRIGHT_BROWSERS_PATH to /usr/local/share/ms-playwright (HOME-independent for sandboxes with per-pod HOME), depends on node and common-utils, and exposes a version option for the CLI package. install.sh installs the global CLI, runs Chromium install-deps / install via playwright-core, restores global npm tree ownership for the remote user, and makes the browsers directory world-readable.

Documentation and an Ubuntu 22.04 scenario test assert playwright-cli on PATH, the env var, Chromium under the shared path, and remote-user read/execute access.

Reviewed by Cursor Bugbot for commit 02a87d8. Configure here.

Greptile Summary

Adds a Playwright devcontainer feature that installs the global CLI, Chromium, and its Debian/Ubuntu system dependencies during image construction.

  • Publishes a configurable @playwright/cli version and shared browser path.
  • Preserves npm-tree ownership for the remote user.
  • Adds generated documentation and an Ubuntu scenario test.

Confidence Score: 4/5

The PR is not yet safe to merge because its primary standalone example still causes image builds without Node to fail.

The reply says the missing Node dependency was addressed through documentation, but the README’s primary Example Usage still omits Node, while the installer exits whenever npm is unavailable; users copying that example therefore encounter the same previously reported failure.

Files Needing Attention: src/playwright/README.md

Important Files Changed

Filename Overview
src/playwright/install.sh Installs the selected Playwright CLI and Chromium, rejects unsupported package-manager environments early, and restores shared-directory ownership.
src/playwright/devcontainer-feature.json Defines the feature metadata, browser environment path, install ordering, and configurable CLI version.
src/playwright/README.md Documents feature usage, prerequisites, supported distributions, and the shared browser path.
test/playwright/ubuntu.sh Verifies CLI availability, browser installation, environment propagation, and remote-user access.

Reviews (2): Last reviewed commit: "style: trim the playwright feature to th..." | Re-trigger Greptile

Installs the Playwright CLI globally and downloads a Chromium build, so containers do not pay for
an npm install and a browser download on every start.

Browsers land in /usr/local/share/ms-playwright rather than Playwright's default "$HOME/.cache",
because sandboxes may replace HOME with a per-pod volume: anything baked into the image's home
directory is invisible there. PLAYWRIGHT_BROWSERS_PATH is set through containerEnv so the install
and every later run agree on that location.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MB7zNmdzPYMpwkUWxAjSFt
Comment thread src/playwright/devcontainer-feature.json
Comment thread src/playwright/install.sh
"id": "playwright",
"installsAfter": [
"ghcr.io/devcontainers/features/common-utils",
"ghcr.io/devcontainers/features/node"

This comment was marked as outdated.

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.

Declining dependsOn — it would break the consumer this feature exists for, so I documented the requirement instead.

The spec deduplicates Features only when the id and the options match exactly ("two Features are identical if their manifest digests are equal, and the options executed against the Feature are equal"). orianna-ai/devcontainer already selects ghcr.io/devcontainers/features/node:2 with {"version": "24.18.0"}. A dependsOn entry has to name some tag and some options, and whatever I pick will not match that, so both copies install and whichever runs last wins the nvm default alias — silently unpinning a node version renovate manages. Hardcoding node:2 + 24.18.0 into a shared feature to dodge that is worse.

The other suggestion, having the installer provision node itself, reimplements the node feature inside this one and hits the same collision.

So: NOTES.md now gives the README a Requirements section showing node selected alongside playwright, and the installer keeps failing fast with npm was not found; this feature has to install after the node feature. The documented setup is the two-feature one; the single-feature example above it is generated from the manifest and I cannot edit it.


Generated by Claude Code

Comment thread src/playwright/install.sh

# install-deps installs Chromium's shared libraries with apt, and an earlier feature may already
# have dropped the package lists.
apt-get update -y

This comment was marked as outdated.

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.

Took the second option — an explicit supported-distribution check. Playwright only knows how to install Chromium's shared libraries with apt, so there is no Fedora/RHEL branch to implement; the feature is inherently Debian and Ubuntu only.

install.sh now checks for apt-get before the npm install, so a non-Debian build stops in a second with apt-get was not found; this feature only supports debian and ubuntu base images instead of after a package download. NOTES.md documents the constraint and it shows up in the generated README.

Not adding the non-Ubuntu scenario: devcontainer features test scenarios assert that a build succeeds and the checks pass, so there is no way to express "this build should fail" — the scenario would just be a red job.


Generated by Claude Code

claude added 2 commits August 5, 2026 05:14
The installer only ever installed Chromium's shared libraries with apt, so it died mid-install on a
non-Debian base with "apt-get: command not found". Check for apt-get up front instead, before the
npm install, and say what the feature supports.

Node stays in installsAfter rather than dependsOn: the spec only deduplicates Features whose id and
options match exactly, so a dependsOn entry would install a second, separately versioned copy of the
node feature for anyone who already pins one. NOTES.md documents the requirement instead, so the
generated README shows node alongside playwright.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MB7zNmdzPYMpwkUWxAjSFt
Drops the comments that restate the code, the blank lines before exit, and the name and description
that ran long next to buildbuddy and cloud-sql-proxy. Drops the version proposals too, so the option
looks like cloud-sql-proxy's. The test loses its local path variable for the same reason.

What stays is the three things a reader cannot get from the code: why browsers go to a system-wide
path, why the global module tree is chowned back, and why playwright-core is located rather than
invoked by name.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MB7zNmdzPYMpwkUWxAjSFt

Copy link
Copy Markdown
Contributor Author

@greptileai


Generated by Claude Code

Copy link
Copy Markdown
Contributor Author

@softlight


Generated by Claude Code

claude added 3 commits August 5, 2026 13:18
Says what the feature actually installs, which was missing: chromium only, no firefox or webkit.
Notes the ownership the install leaves behind, now that install.sh no longer explains it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MB7zNmdzPYMpwkUWxAjSFt
Drops the ownership paragraph and the installsAfter-versus-dependsOn rationale, which explained our
implementation rather than telling anyone what to do. The reader keeps the four things they cannot
get from the manifest: node is required, debian and ubuntu only, chromium only, and where the
browsers live.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MB7zNmdzPYMpwkUWxAjSFt
@ashwin153
ashwin153 enabled auto-merge (squash) August 5, 2026 13:24
The generated Example Usage block shows this feature on its own and cannot be edited, so a reader
copying it hit the npm error with nothing warning them first. The description renders above that
block, so put it there.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MB7zNmdzPYMpwkUWxAjSFt
@ashwin153
ashwin153 merged commit c87ae88 into main Aug 5, 2026
2 checks passed
@ashwin153
ashwin153 deleted the claude/devcontainer-feature-migration-u53qfp branch August 5, 2026 13:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants