From 2a5567ff09fa044cf391b1d79ecf1fe7846e8828 Mon Sep 17 00:00:00 2001 From: Michael Bianco Date: Mon, 19 Jan 2026 15:39:52 -0700 Subject: [PATCH 1/2] Revert "feat: automatically install packages required for playwright, and playwright browser (#348)" This reverts commit c6fc142593a2e16a282a417ad7bb31ecd4bb9893. --- ...lanForExamples_node-playwright_1.snap.json | 189 ------------------ ...nForExamples_python-playwright_1.snap.json | 187 ----------------- core/providers/node/node.go | 39 +--- core/providers/node/package_manager.go | 11 - core/providers/node/spa.go | 4 - core/providers/python/python.go | 32 +-- examples/node-playwright/index.js | 20 -- examples/node-playwright/mise.toml | 3 - examples/node-playwright/package.json | 15 -- examples/node-playwright/pnpm-lock.yaml | 43 ---- examples/node-playwright/test.json | 5 - examples/python-playwright/main.py | 14 -- examples/python-playwright/mise.toml | 3 - examples/python-playwright/pyproject.toml | 8 - examples/python-playwright/test.json | 5 - examples/python-playwright/uv.lock | 104 ---------- mise.toml | 4 - 17 files changed, 14 insertions(+), 672 deletions(-) delete mode 100755 core/__snapshots__/TestGenerateBuildPlanForExamples_node-playwright_1.snap.json delete mode 100755 core/__snapshots__/TestGenerateBuildPlanForExamples_python-playwright_1.snap.json delete mode 100644 examples/node-playwright/index.js delete mode 100644 examples/node-playwright/mise.toml delete mode 100644 examples/node-playwright/package.json delete mode 100644 examples/node-playwright/pnpm-lock.yaml delete mode 100644 examples/node-playwright/test.json delete mode 100644 examples/python-playwright/main.py delete mode 100644 examples/python-playwright/mise.toml delete mode 100644 examples/python-playwright/pyproject.toml delete mode 100644 examples/python-playwright/test.json delete mode 100644 examples/python-playwright/uv.lock diff --git a/core/__snapshots__/TestGenerateBuildPlanForExamples_node-playwright_1.snap.json b/core/__snapshots__/TestGenerateBuildPlanForExamples_node-playwright_1.snap.json deleted file mode 100755 index 9c0c9e20..00000000 --- a/core/__snapshots__/TestGenerateBuildPlanForExamples_node-playwright_1.snap.json +++ /dev/null @@ -1,189 +0,0 @@ -{ - "caches": { - "apt": { - "directory": "/var/cache/apt", - "type": "locked" - }, - "apt-lists": { - "directory": "/var/lib/apt/lists", - "type": "locked" - }, - "node-modules": { - "directory": "/app/node_modules/.cache", - "type": "shared" - }, - "pnpm-install": { - "directory": "/root/.local/share/pnpm/store/v3", - "type": "shared" - } - }, - "deploy": { - "base": { - "step": "packages:apt:runtime" - }, - "inputs": [ - { - "include": [ - "/mise/shims", - "/mise/installs", - "/usr/local/bin/mise", - "/etc/mise/config.toml", - "/root/.local/state/mise" - ], - "step": "packages:mise" - }, - { - "include": [ - "/app/node_modules" - ], - "step": "build" - }, - { - "exclude": [ - "node_modules", - ".yarn" - ], - "include": [ - "/root/.cache", - "." - ], - "step": "build" - } - ], - "startCommand": "node index.js", - "variables": { - "CI": "true", - "NODE_ENV": "production", - "NPM_CONFIG_FUND": "false", - "NPM_CONFIG_PRODUCTION": "false", - "NPM_CONFIG_UPDATE_NOTIFIER": "false" - } - }, - "steps": [ - { - "assets": { - "mise.toml": "[mise.toml]" - }, - "commands": [ - { - "path": "/mise/shims" - }, - { - "dest": "mise.toml", - "src": "mise.toml" - }, - { - "customName": "create mise config", - "name": "mise.toml", - "path": "/etc/mise/config.toml" - }, - { - "cmd": "mise install", - "customName": "install mise packages: node, pnpm" - } - ], - "inputs": [ - { - "image": "ghcr.io/railwayapp/railpack-builder:latest" - } - ], - "name": "packages:mise", - "variables": { - "MISE_CACHE_DIR": "/mise/cache", - "MISE_CONFIG_DIR": "/mise", - "MISE_DATA_DIR": "/mise", - "MISE_IDIOMATIC_VERSION_FILE_ENABLE_TOOLS": "python,node,ruby,elixir,go,java,yarn", - "MISE_INSTALLS_DIR": "/mise/installs", - "MISE_NODE_VERIFY": "false", - "MISE_PARANOID": "1", - "MISE_SHIMS_DIR": "/mise/shims", - "MISE_TRUSTED_CONFIG_PATHS": "/app" - } - }, - { - "caches": [ - "pnpm-install" - ], - "commands": [ - { - "path": "/app/node_modules/.bin" - }, - { - "cmd": "mkdir -p /app/node_modules/.cache" - }, - { - "dest": "package.json", - "src": "package.json" - }, - { - "dest": "pnpm-lock.yaml", - "src": "pnpm-lock.yaml" - }, - { - "path": "/pnpm" - }, - { - "cmd": "pnpm add -g node-gyp" - }, - { - "cmd": "pnpm install --frozen-lockfile --prefer-offline" - }, - { - "cmd": "pnpm exec playwright install --only-shell" - } - ], - "inputs": [ - { - "step": "packages:mise" - } - ], - "name": "install", - "variables": { - "CI": "true", - "NODE_ENV": "production", - "NPM_CONFIG_FUND": "false", - "NPM_CONFIG_PRODUCTION": "false", - "NPM_CONFIG_UPDATE_NOTIFIER": "false", - "PNPM_HOME": "/pnpm" - } - }, - { - "caches": [ - "node-modules" - ], - "inputs": [ - { - "step": "install" - }, - { - "include": [ - "." - ], - "local": true - } - ], - "name": "build", - "secrets": [ - "*" - ] - }, - { - "caches": [ - "apt", - "apt-lists" - ], - "commands": [ - { - "cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y libasound2 libatk-bridge2.0-0 libatk1.0-0 libatomic1 libatspi2.0-0 libcairo2 libcups2 libgbm1 libglib2.0-0 libnspr4 libnss3 libpango-1.0-0 libxcomposite1 libxdamage1 libxfixes3 libxkbcommon0 libxrandr2'", - "customName": "install apt packages: libasound2 libatk-bridge2.0-0 libatk1.0-0 libatomic1 libatspi2.0-0 libcairo2 libcups2 libgbm1 libglib2.0-0 libnspr4 libnss3 libpango-1.0-0 libxcomposite1 libxdamage1 libxfixes3 libxkbcommon0 libxrandr2" - } - ], - "inputs": [ - { - "image": "ghcr.io/railwayapp/railpack-runtime:latest" - } - ], - "name": "packages:apt:runtime" - } - ] -} \ No newline at end of file diff --git a/core/__snapshots__/TestGenerateBuildPlanForExamples_python-playwright_1.snap.json b/core/__snapshots__/TestGenerateBuildPlanForExamples_python-playwright_1.snap.json deleted file mode 100755 index 66649ab2..00000000 --- a/core/__snapshots__/TestGenerateBuildPlanForExamples_python-playwright_1.snap.json +++ /dev/null @@ -1,187 +0,0 @@ -{ - "caches": { - "apt": { - "directory": "/var/cache/apt", - "type": "locked" - }, - "apt-lists": { - "directory": "/var/lib/apt/lists", - "type": "locked" - }, - "uv": { - "directory": "/opt/uv-cache", - "type": "shared" - } - }, - "deploy": { - "base": { - "step": "packages:apt:runtime" - }, - "inputs": [ - { - "include": [ - "/mise/shims", - "/mise/installs", - "/usr/local/bin/mise", - "/etc/mise/config.toml", - "/root/.local/state/mise" - ], - "step": "packages:mise" - }, - { - "include": [ - "/app/.venv", - "/root/.cache/ms-playwright" - ], - "step": "build" - }, - { - "exclude": [ - ".venv" - ], - "include": [ - "." - ], - "step": "build" - } - ], - "startCommand": "python main.py", - "variables": { - "PIP_DEFAULT_TIMEOUT": "100", - "PIP_DISABLE_PIP_VERSION_CHECK": "1", - "PYTHONDONTWRITEBYTECODE": "1", - "PYTHONFAULTHANDLER": "1", - "PYTHONHASHSEED": "random", - "PYTHONUNBUFFERED": "1" - } - }, - "steps": [ - { - "assets": { - "mise.toml": "[mise.toml]" - }, - "commands": [ - { - "path": "/mise/shims" - }, - { - "dest": "mise.toml", - "src": "mise.toml" - }, - { - "customName": "create mise config", - "name": "mise.toml", - "path": "/etc/mise/config.toml" - }, - { - "cmd": "mise install", - "customName": "install mise packages: python, uv" - } - ], - "inputs": [ - { - "image": "ghcr.io/railwayapp/railpack-builder:latest" - } - ], - "name": "packages:mise", - "variables": { - "MISE_CACHE_DIR": "/mise/cache", - "MISE_CONFIG_DIR": "/mise", - "MISE_DATA_DIR": "/mise", - "MISE_IDIOMATIC_VERSION_FILE_ENABLE_TOOLS": "python,node,ruby,elixir,go,java,yarn", - "MISE_INSTALLS_DIR": "/mise/installs", - "MISE_NODE_VERIFY": "false", - "MISE_PARANOID": "1", - "MISE_PYTHON_COMPILE": "false", - "MISE_SHIMS_DIR": "/mise/shims", - "MISE_TRUSTED_CONFIG_PATHS": "/app" - } - }, - { - "caches": [ - "uv" - ], - "commands": [ - { - "dest": "pyproject.toml", - "src": "pyproject.toml" - }, - { - "dest": "uv.lock", - "src": "uv.lock" - }, - { - "path": "/root/.local/bin" - }, - { - "path": "/app/.venv/bin" - }, - { - "cmd": "uv sync --locked --no-dev --no-install-project" - }, - { - "cmd": "playwright install --only-shell" - } - ], - "inputs": [ - { - "step": "packages:mise" - } - ], - "name": "install", - "variables": { - "PIP_DEFAULT_TIMEOUT": "100", - "PIP_DISABLE_PIP_VERSION_CHECK": "1", - "PYTHONDONTWRITEBYTECODE": "1", - "PYTHONFAULTHANDLER": "1", - "PYTHONHASHSEED": "random", - "PYTHONUNBUFFERED": "1", - "UV_CACHE_DIR": "/opt/uv-cache", - "UV_COMPILE_BYTECODE": "1", - "UV_LINK_MODE": "copy", - "UV_PYTHON_DOWNLOADS": "never", - "VIRTUAL_ENV": "/app/.venv" - } - }, - { - "commands": [ - { - "cmd": "uv sync --locked --no-dev --no-editable" - } - ], - "inputs": [ - { - "step": "install" - }, - { - "include": [ - "." - ], - "local": true - } - ], - "name": "build", - "secrets": [ - "*" - ] - }, - { - "caches": [ - "apt", - "apt-lists" - ], - "commands": [ - { - "cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y libasound2 libatk-bridge2.0-0 libatk1.0-0 libatspi2.0-0 libcairo2 libcups2 libgbm1 libglib2.0-0 libnspr4 libnss3 libpango-1.0-0 libxcomposite1 libxdamage1 libxfixes3 libxkbcommon0 libxrandr2'", - "customName": "install apt packages: libasound2 libatk-bridge2.0-0 libatk1.0-0 libatspi2.0-0 libcairo2 libcups2 libgbm1 libglib2.0-0 libnspr4 libnss3 libpango-1.0-0 libxcomposite1 libxdamage1 libxfixes3 libxkbcommon0 libxrandr2" - } - ], - "inputs": [ - { - "image": "ghcr.io/railwayapp/railpack-runtime:latest" - } - ], - "name": "packages:apt:runtime" - } - ] -} \ No newline at end of file diff --git a/core/providers/node/node.go b/core/providers/node/node.go index 0e861edc..4925b670 100644 --- a/core/providers/node/node.go +++ b/core/providers/node/node.go @@ -20,20 +20,12 @@ const ( DEFAULT_NODE_VERSION = "22" DEFAULT_BUN_VERSION = "latest" + COREPACK_HOME = "/opt/corepack" + // not used by npm, but many other tools: next, jest, webpack, etc - NODE_MODULES_CACHE = "/app/node_modules/.cache" - COREPACK_HOME = "/opt/corepack" - PLAYWRIGHT_CACHE_DIR = "/root/.cache/ms-playwright" + NODE_MODULES_CACHE = "/app/node_modules/.cache" ) -var nodeRuntimeDepRequirements = map[string][]string{ - // To find the latest list: run `npx puppeteer@latest install --help` and inspect docs - "puppeteer": {"xvfb", "gconf-service", "libasound2", "libatk1.0-0", "libc6", "libcairo2", "libcups2", "libdbus-1-3", "libexpat1", "libfontconfig1", "libgbm1", "libgcc1", "libgconf-2-4", "libgdk-pixbuf2.0-0", "libglib2.0-0", "libgtk-3-0", "libnspr4", "libpango-1.0-0", "libpangocairo-1.0-0", "libstdc++6", "libx11-6", "libx11-xcb1", "libxcb1", "libxcomposite1", "libxcursor1", "libxdamage1", "libxext6", "libxfixes3", "libxi6", "libxrandr2", "libxrender1", "libxss1", "libxtst6", "ca-certificates", "fonts-liberation", "libappindicator1", "libnss3", "lsb-release", "xdg-utils", "wget"}, - // To find the latest list: run `playwright install-deps chromium` and inspect the apt-get install output - // Or check: https://github.com/microsoft/playwright/blob/main/packages/playwright-core/browsers.json - "playwright": {"libglib2.0-0", "libatk1.0-0", "libatk-bridge2.0-0", "libcups2", "libxkbcommon0", "libatspi2.0-0", "libxcomposite1", "libxdamage1", "libxfixes3", "libxrandr2", "libgbm1", "libcairo2", "libpango-1.0-0", "libasound2", "libnspr4", "libnss3"}, -} - var ( // bunCommandRegex matches "bun" or "bunx" as a command (not part of another word) bunCommandRegex = regexp.MustCompile(`(^|\s|;|&|&&|\||\|\|)bunx?\s`) @@ -84,6 +76,8 @@ func (p *NodeProvider) Plan(ctx *generate.GenerateContext) error { ctx.Logger.LogInfo("Found workspace with %d packages", len(p.workspace.Packages)) } + isSPA := p.isSPA(ctx) + miseStep := ctx.GetMiseStepBuilder() p.InstallMisePackages(ctx, miseStep) @@ -91,8 +85,6 @@ func (p *NodeProvider) Plan(ctx *generate.GenerateContext) error { install.AddInput(plan.NewStepLayer(miseStep.Name())) p.InstallNodeDeps(ctx, install) - isSPA := p.isSPA(ctx) - prune := ctx.NewCommandStep("prune") prune.AddInput(plan.NewStepLayer(install.Name())) prune.Secrets = []string{} @@ -121,21 +113,10 @@ func (p *NodeProvider) Plan(ctx *generate.GenerateContext) error { buildIncludeDirs = append(buildIncludeDirs, COREPACK_HOME) } - // determine additional Apt packages needed - - // Required for Node.js 25+ - runtimeAptPackages := []string{"libatomic1"} - + runtimeAptPackages := []string{} if p.usesPuppeteer() { - ctx.Logger.LogInfo("Installing puppeteer packages") - runtimeAptPackages = append(runtimeAptPackages, nodeRuntimeDepRequirements["puppeteer"]...) - } - - if p.usesPlaywright() { - ctx.Logger.LogInfo("Installing playwright packages and headless browser") - runtimeAptPackages = append(runtimeAptPackages, nodeRuntimeDepRequirements["playwright"]...) - // --only-shell is smaller and more appropriate for server environments than full chromium - install.AddCommand(plan.NewExecCommand(p.packageManager.ExecCommand("playwright install --only-shell"))) + ctx.Logger.LogInfo("Installing puppeteer dependencies") + runtimeAptPackages = append(runtimeAptPackages, "xvfb", "gconf-service", "libasound2", "libatk1.0-0", "libc6", "libcairo2", "libcups2", "libdbus-1-3", "libexpat1", "libfontconfig1", "libgbm1", "libgcc1", "libgconf-2-4", "libgdk-pixbuf2.0-0", "libglib2.0-0", "libgtk-3-0", "libnspr4", "libpango-1.0-0", "libpangocairo-1.0-0", "libstdc++6", "libx11-6", "libx11-xcb1", "libxcb1", "libxcomposite1", "libxcursor1", "libxdamage1", "libxext6", "libxfixes3", "libxi6", "libxrandr2", "libxrender1", "libxss1", "libxtst6", "ca-certificates", "fonts-liberation", "libappindicator1", "libnss3", "lsb-release", "xdg-utils", "wget") } nodeModulesLayer := plan.NewStepLayer(build.Name(), plan.Filter{ @@ -405,10 +386,6 @@ func (p *NodeProvider) usesPuppeteer() bool { return p.workspace.HasDependency("puppeteer") } -func (p *NodeProvider) usesPlaywright() bool { - return p.workspace.HasDependency("playwright") -} - // determine the major version of yarn from a version string. These major versions are installed and managed quite // differently which is why we need to distinguish them here. func parseYarnPackageManager(pmVersion string) PackageManager { diff --git a/core/providers/node/package_manager.go b/core/providers/node/package_manager.go index d5c192fd..1f7a17a3 100644 --- a/core/providers/node/package_manager.go +++ b/core/providers/node/package_manager.go @@ -47,17 +47,6 @@ func (p PackageManager) RunScriptCommand(cmd string) string { return "node " + cmd } -func (p PackageManager) ExecCommand(cmd string) string { - switch p { - case PackageManagerPnpm: - return fmt.Sprintf("pnpm exec %s", cmd) - case PackageManagerBun: - return fmt.Sprintf("bunx %s", cmd) - default: - return fmt.Sprintf("npx %s", cmd) - } -} - func (p PackageManager) installDependencies(ctx *generate.GenerateContext, workspace *Workspace, install *generate.CommandStepBuilder, usingCorepack bool) { packageJsons := workspace.AllPackageJson() diff --git a/core/providers/node/spa.go b/core/providers/node/spa.go index 86b8f04f..e77adf08 100644 --- a/core/providers/node/spa.go +++ b/core/providers/node/spa.go @@ -5,7 +5,6 @@ import ( "fmt" "path" - "github.com/charmbracelet/log" "github.com/railwayapp/railpack/core/generate" "github.com/railwayapp/railpack/core/plan" ) @@ -57,9 +56,6 @@ func (p *NodeProvider) getSPAFramework(ctx *generate.GenerateContext) string { return "CRA" } else if p.isAngular(ctx) { return "Angular" - } else { - // this should never happen! - log.Error("SPA framework expected, but could not determine type") } return "" diff --git a/core/providers/python/python.go b/core/providers/python/python.go index ee9171ac..b8b6766f 100644 --- a/core/providers/python/python.go +++ b/core/providers/python/python.go @@ -18,7 +18,6 @@ const ( PIP_CACHE_DIR = "/opt/pip-cache" VENV_PATH = "/app/.venv" LOCAL_BIN_PATH = "/root/.local/bin" - PLAYWRIGHT_CACHE_DIR = "/root/.cache/ms-playwright" ) type PythonProvider struct{} @@ -68,15 +67,6 @@ func (p *PythonProvider) Plan(ctx *generate.GenerateContext) error { installOutputs = p.InstallPipenv(ctx, install) } - if p.usesDep(ctx, "playwright") { - ctx.Logger.LogInfo("Installing Playwright chromium browser") - // --only-shell installs only the headless shell version (chromium_headless_shell) - // This is smaller and more appropriate for server environments than full chromium - install.AddCommand(plan.NewExecCommand("playwright install --only-shell")) - // Include Playwright browser cache so browsers are available in deploy stage - installOutputs = append(installOutputs, PLAYWRIGHT_CACHE_DIR) - } - p.addMetadata(ctx) build.AddInput(plan.NewStepLayer(install.Name())) @@ -167,16 +157,14 @@ func (p *PythonProvider) InstallUv(ctx *generate.GenerateContext, install *gener install.AddEnvVars(p.GetPythonEnvVars(ctx)) p.copyInstallFiles(ctx, install) - installCommands := []plan.Command{ + install.AddCommands([]plan.Command{ plan.NewPathCommand(LOCAL_BIN_PATH), plan.NewPathCommand(VENV_PATH + "/bin"), // if we exclude workspace packages, uv.lock will fail the frozen test and the user will get an error // to avoid this, we (a) detect if workspace packages are required (b) if they aren't, we don't include project // source in order to optimize layer caching (c) install project in the build phase. plan.NewExecCommand("uv sync --locked --no-dev --no-install-project"), - } - - install.AddCommands(installCommands) + }) return []string{VENV_PATH} } @@ -221,13 +209,11 @@ func (p *PythonProvider) InstallPDM(ctx *generate.GenerateContext, install *gene }) p.copyInstallFiles(ctx, install) - installCommands := []plan.Command{ + install.AddCommands([]plan.Command{ plan.NewPathCommand(LOCAL_BIN_PATH), plan.NewPathCommand(VENV_PATH + "/bin"), plan.NewExecCommand("pdm install --check --prod --no-editable"), - } - - install.AddCommands(installCommands) + }) return []string{VENV_PATH} } @@ -243,13 +229,11 @@ func (p *PythonProvider) InstallPoetry(ctx *generate.GenerateContext, install *g }) p.copyInstallFiles(ctx, install) - installCommands := []plan.Command{ + install.AddCommands([]plan.Command{ plan.NewPathCommand(LOCAL_BIN_PATH), plan.NewPathCommand(VENV_PATH + "/bin"), plan.NewExecCommand("poetry install --no-interaction --no-ansi --only main --no-root"), - } - - install.AddCommands(installCommands) + }) return []string{VENV_PATH} } @@ -573,8 +557,4 @@ var pythonRuntimeDepRequirements = map[string][]string{ "pdf2image": {"poppler-utils"}, "pydub": {"ffmpeg"}, "pymovie": {"ffmpeg", "qt5-qmake", "qtbase5-dev", "qtbase5-dev-tools", "qttools5-dev-tools", "libqt5core5a", "python3-pyqt5"}, - // Playwright runtime dependencies for Chromium browser - // To find the latest list: run `playwright install-deps chromium` and inspect the apt-get install output - // Or check: https://github.com/microsoft/playwright/blob/main/packages/playwright-core/browsers.json - "playwright": {"libglib2.0-0", "libatk1.0-0", "libatk-bridge2.0-0", "libcups2", "libxkbcommon0", "libatspi2.0-0", "libxcomposite1", "libxdamage1", "libxfixes3", "libxrandr2", "libgbm1", "libcairo2", "libpango-1.0-0", "libasound2", "libnspr4", "libnss3"}, } diff --git a/examples/node-playwright/index.js b/examples/node-playwright/index.js deleted file mode 100644 index 43faf8ba..00000000 --- a/examples/node-playwright/index.js +++ /dev/null @@ -1,20 +0,0 @@ -const { chromium } = require("playwright"); - -(async () => { - console.log("Starting Playwright"); - const browser = await chromium.launch({ - headless: true, - args: ["--no-sandbox"], - }); - const version = browser.version(); - console.log(`Chromium version: ${version}`); - console.log("Creating Page"); - const page = await browser.newPage(); - console.log("Navigating to hackernews"); - await page.goto("https://news.ycombinator.com", { - waitUntil: "networkidle", - }); - - await browser.close(); - console.log("Hello from playwright"); -})(); diff --git a/examples/node-playwright/mise.toml b/examples/node-playwright/mise.toml deleted file mode 100644 index c284c6f4..00000000 --- a/examples/node-playwright/mise.toml +++ /dev/null @@ -1,3 +0,0 @@ -[tools] -node = "latest" -pnpm = "latest" diff --git a/examples/node-playwright/package.json b/examples/node-playwright/package.json deleted file mode 100644 index 14cdbea0..00000000 --- a/examples/node-playwright/package.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "playwright-example", - "version": "1.0.0", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [], - "author": "", - "license": "ISC", - "description": "", - "dependencies": { - "playwright": "^1.49" - } -} diff --git a/examples/node-playwright/pnpm-lock.yaml b/examples/node-playwright/pnpm-lock.yaml deleted file mode 100644 index dfd264cc..00000000 --- a/examples/node-playwright/pnpm-lock.yaml +++ /dev/null @@ -1,43 +0,0 @@ -lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - dependencies: - playwright: - specifier: ^1.49 - version: 1.56.1 - -packages: - - fsevents@2.3.2: - resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - - playwright-core@1.56.1: - resolution: {integrity: sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ==} - engines: {node: '>=18'} - hasBin: true - - playwright@1.56.1: - resolution: {integrity: sha512-aFi5B0WovBHTEvpM3DzXTUaeN6eN0qWnTkKx4NQaH4Wvcmc153PdaY2UBdSYKaGYw+UyWXSVyxDUg5DoPEttjw==} - engines: {node: '>=18'} - hasBin: true - -snapshots: - - fsevents@2.3.2: - optional: true - - playwright-core@1.56.1: {} - - playwright@1.56.1: - dependencies: - playwright-core: 1.56.1 - optionalDependencies: - fsevents: 2.3.2 diff --git a/examples/node-playwright/test.json b/examples/node-playwright/test.json deleted file mode 100644 index 5fd48231..00000000 --- a/examples/node-playwright/test.json +++ /dev/null @@ -1,5 +0,0 @@ -[ - { - "expectedOutput": "Hello from playwright" - } -] diff --git a/examples/python-playwright/main.py b/examples/python-playwright/main.py deleted file mode 100644 index 1eabb4f2..00000000 --- a/examples/python-playwright/main.py +++ /dev/null @@ -1,14 +0,0 @@ -from playwright.sync_api import sync_playwright - -print("Starting Playwright") -with sync_playwright() as p: - browser = p.chromium.launch(headless=True, args=["--no-sandbox"]) - version = browser.version - print(f"Chromium version: {version}") - print("Creating Page") - page = browser.new_page() - print("Navigating to hackernews") - page.goto("https://news.ycombinator.com", wait_until="networkidle") - browser.close() - -print("Hello from playwright") diff --git a/examples/python-playwright/mise.toml b/examples/python-playwright/mise.toml deleted file mode 100644 index 96e04be8..00000000 --- a/examples/python-playwright/mise.toml +++ /dev/null @@ -1,3 +0,0 @@ -[tools] -python = "latest" -uv = "latest" diff --git a/examples/python-playwright/pyproject.toml b/examples/python-playwright/pyproject.toml deleted file mode 100644 index 217759ec..00000000 --- a/examples/python-playwright/pyproject.toml +++ /dev/null @@ -1,8 +0,0 @@ -[project] -name = "python-playwright" -version = "0.1.0" -description = "Python Playwright example" -requires-python = ">=3.11" -dependencies = [ - "playwright>=1.49", -] diff --git a/examples/python-playwright/test.json b/examples/python-playwright/test.json deleted file mode 100644 index 5fd48231..00000000 --- a/examples/python-playwright/test.json +++ /dev/null @@ -1,5 +0,0 @@ -[ - { - "expectedOutput": "Hello from playwright" - } -] diff --git a/examples/python-playwright/uv.lock b/examples/python-playwright/uv.lock deleted file mode 100644 index 41e431ad..00000000 --- a/examples/python-playwright/uv.lock +++ /dev/null @@ -1,104 +0,0 @@ -version = 1 -revision = 3 -requires-python = ">=3.11" - -[[package]] -name = "greenlet" -version = "3.2.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/03/b8/704d753a5a45507a7aab61f18db9509302ed3d0a27ac7e0359ec2905b1a6/greenlet-3.2.4.tar.gz", hash = "sha256:0dca0d95ff849f9a364385f36ab49f50065d76964944638be9691e1832e9f86d", size = 188260, upload-time = "2025-08-07T13:24:33.51Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a4/de/f28ced0a67749cac23fecb02b694f6473f47686dff6afaa211d186e2ef9c/greenlet-3.2.4-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:96378df1de302bc38e99c3a9aa311967b7dc80ced1dcc6f171e99842987882a2", size = 272305, upload-time = "2025-08-07T13:15:41.288Z" }, - { url = "https://files.pythonhosted.org/packages/09/16/2c3792cba130000bf2a31c5272999113f4764fd9d874fb257ff588ac779a/greenlet-3.2.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1ee8fae0519a337f2329cb78bd7a8e128ec0f881073d43f023c7b8d4831d5246", size = 632472, upload-time = "2025-08-07T13:42:55.044Z" }, - { url = "https://files.pythonhosted.org/packages/ae/8f/95d48d7e3d433e6dae5b1682e4292242a53f22df82e6d3dda81b1701a960/greenlet-3.2.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:94abf90142c2a18151632371140b3dba4dee031633fe614cb592dbb6c9e17bc3", size = 644646, upload-time = "2025-08-07T13:45:26.523Z" }, - { url = "https://files.pythonhosted.org/packages/d5/5e/405965351aef8c76b8ef7ad370e5da58d57ef6068df197548b015464001a/greenlet-3.2.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:4d1378601b85e2e5171b99be8d2dc85f594c79967599328f95c1dc1a40f1c633", size = 640519, upload-time = "2025-08-07T13:53:13.928Z" }, - { url = "https://files.pythonhosted.org/packages/25/5d/382753b52006ce0218297ec1b628e048c4e64b155379331f25a7316eb749/greenlet-3.2.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0db5594dce18db94f7d1650d7489909b57afde4c580806b8d9203b6e79cdc079", size = 639707, upload-time = "2025-08-07T13:18:27.146Z" }, - { url = "https://files.pythonhosted.org/packages/1f/8e/abdd3f14d735b2929290a018ecf133c901be4874b858dd1c604b9319f064/greenlet-3.2.4-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2523e5246274f54fdadbce8494458a2ebdcdbc7b802318466ac5606d3cded1f8", size = 587684, upload-time = "2025-08-07T13:18:25.164Z" }, - { url = "https://files.pythonhosted.org/packages/5d/65/deb2a69c3e5996439b0176f6651e0052542bb6c8f8ec2e3fba97c9768805/greenlet-3.2.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1987de92fec508535687fb807a5cea1560f6196285a4cde35c100b8cd632cc52", size = 1116647, upload-time = "2025-08-07T13:42:38.655Z" }, - { url = "https://files.pythonhosted.org/packages/3f/cc/b07000438a29ac5cfb2194bfc128151d52f333cee74dd7dfe3fb733fc16c/greenlet-3.2.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:55e9c5affaa6775e2c6b67659f3a71684de4c549b3dd9afca3bc773533d284fa", size = 1142073, upload-time = "2025-08-07T13:18:21.737Z" }, - { url = "https://files.pythonhosted.org/packages/67/24/28a5b2fa42d12b3d7e5614145f0bd89714c34c08be6aabe39c14dd52db34/greenlet-3.2.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c9c6de1940a7d828635fbd254d69db79e54619f165ee7ce32fda763a9cb6a58c", size = 1548385, upload-time = "2025-11-04T12:42:11.067Z" }, - { url = "https://files.pythonhosted.org/packages/6a/05/03f2f0bdd0b0ff9a4f7b99333d57b53a7709c27723ec8123056b084e69cd/greenlet-3.2.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:03c5136e7be905045160b1b9fdca93dd6727b180feeafda6818e6496434ed8c5", size = 1613329, upload-time = "2025-11-04T12:42:12.928Z" }, - { url = "https://files.pythonhosted.org/packages/d8/0f/30aef242fcab550b0b3520b8e3561156857c94288f0332a79928c31a52cf/greenlet-3.2.4-cp311-cp311-win_amd64.whl", hash = "sha256:9c40adce87eaa9ddb593ccb0fa6a07caf34015a29bf8d344811665b573138db9", size = 299100, upload-time = "2025-08-07T13:44:12.287Z" }, - { url = "https://files.pythonhosted.org/packages/44/69/9b804adb5fd0671f367781560eb5eb586c4d495277c93bde4307b9e28068/greenlet-3.2.4-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:3b67ca49f54cede0186854a008109d6ee71f66bd57bb36abd6d0a0267b540cdd", size = 274079, upload-time = "2025-08-07T13:15:45.033Z" }, - { url = "https://files.pythonhosted.org/packages/46/e9/d2a80c99f19a153eff70bc451ab78615583b8dac0754cfb942223d2c1a0d/greenlet-3.2.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ddf9164e7a5b08e9d22511526865780a576f19ddd00d62f8a665949327fde8bb", size = 640997, upload-time = "2025-08-07T13:42:56.234Z" }, - { url = "https://files.pythonhosted.org/packages/3b/16/035dcfcc48715ccd345f3a93183267167cdd162ad123cd93067d86f27ce4/greenlet-3.2.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f28588772bb5fb869a8eb331374ec06f24a83a9c25bfa1f38b6993afe9c1e968", size = 655185, upload-time = "2025-08-07T13:45:27.624Z" }, - { url = "https://files.pythonhosted.org/packages/31/da/0386695eef69ffae1ad726881571dfe28b41970173947e7c558d9998de0f/greenlet-3.2.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:5c9320971821a7cb77cfab8d956fa8e39cd07ca44b6070db358ceb7f8797c8c9", size = 649926, upload-time = "2025-08-07T13:53:15.251Z" }, - { url = "https://files.pythonhosted.org/packages/68/88/69bf19fd4dc19981928ceacbc5fd4bb6bc2215d53199e367832e98d1d8fe/greenlet-3.2.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c60a6d84229b271d44b70fb6e5fa23781abb5d742af7b808ae3f6efd7c9c60f6", size = 651839, upload-time = "2025-08-07T13:18:30.281Z" }, - { url = "https://files.pythonhosted.org/packages/19/0d/6660d55f7373b2ff8152401a83e02084956da23ae58cddbfb0b330978fe9/greenlet-3.2.4-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b3812d8d0c9579967815af437d96623f45c0f2ae5f04e366de62a12d83a8fb0", size = 607586, upload-time = "2025-08-07T13:18:28.544Z" }, - { url = "https://files.pythonhosted.org/packages/8e/1a/c953fdedd22d81ee4629afbb38d2f9d71e37d23caace44775a3a969147d4/greenlet-3.2.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:abbf57b5a870d30c4675928c37278493044d7c14378350b3aa5d484fa65575f0", size = 1123281, upload-time = "2025-08-07T13:42:39.858Z" }, - { url = "https://files.pythonhosted.org/packages/3f/c7/12381b18e21aef2c6bd3a636da1088b888b97b7a0362fac2e4de92405f97/greenlet-3.2.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:20fb936b4652b6e307b8f347665e2c615540d4b42b3b4c8a321d8286da7e520f", size = 1151142, upload-time = "2025-08-07T13:18:22.981Z" }, - { url = "https://files.pythonhosted.org/packages/27/45/80935968b53cfd3f33cf99ea5f08227f2646e044568c9b1555b58ffd61c2/greenlet-3.2.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ee7a6ec486883397d70eec05059353b8e83eca9168b9f3f9a361971e77e0bcd0", size = 1564846, upload-time = "2025-11-04T12:42:15.191Z" }, - { url = "https://files.pythonhosted.org/packages/69/02/b7c30e5e04752cb4db6202a3858b149c0710e5453b71a3b2aec5d78a1aab/greenlet-3.2.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:326d234cbf337c9c3def0676412eb7040a35a768efc92504b947b3e9cfc7543d", size = 1633814, upload-time = "2025-11-04T12:42:17.175Z" }, - { url = "https://files.pythonhosted.org/packages/e9/08/b0814846b79399e585f974bbeebf5580fbe59e258ea7be64d9dfb253c84f/greenlet-3.2.4-cp312-cp312-win_amd64.whl", hash = "sha256:a7d4e128405eea3814a12cc2605e0e6aedb4035bf32697f72deca74de4105e02", size = 299899, upload-time = "2025-08-07T13:38:53.448Z" }, - { url = "https://files.pythonhosted.org/packages/49/e8/58c7f85958bda41dafea50497cbd59738c5c43dbbea5ee83d651234398f4/greenlet-3.2.4-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:1a921e542453fe531144e91e1feedf12e07351b1cf6c9e8a3325ea600a715a31", size = 272814, upload-time = "2025-08-07T13:15:50.011Z" }, - { url = "https://files.pythonhosted.org/packages/62/dd/b9f59862e9e257a16e4e610480cfffd29e3fae018a68c2332090b53aac3d/greenlet-3.2.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cd3c8e693bff0fff6ba55f140bf390fa92c994083f838fece0f63be121334945", size = 641073, upload-time = "2025-08-07T13:42:57.23Z" }, - { url = "https://files.pythonhosted.org/packages/f7/0b/bc13f787394920b23073ca3b6c4a7a21396301ed75a655bcb47196b50e6e/greenlet-3.2.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:710638eb93b1fa52823aa91bf75326f9ecdfd5e0466f00789246a5280f4ba0fc", size = 655191, upload-time = "2025-08-07T13:45:29.752Z" }, - { url = "https://files.pythonhosted.org/packages/f2/d6/6adde57d1345a8d0f14d31e4ab9c23cfe8e2cd39c3baf7674b4b0338d266/greenlet-3.2.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:c5111ccdc9c88f423426df3fd1811bfc40ed66264d35aa373420a34377efc98a", size = 649516, upload-time = "2025-08-07T13:53:16.314Z" }, - { url = "https://files.pythonhosted.org/packages/7f/3b/3a3328a788d4a473889a2d403199932be55b1b0060f4ddd96ee7cdfcad10/greenlet-3.2.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d76383238584e9711e20ebe14db6c88ddcedc1829a9ad31a584389463b5aa504", size = 652169, upload-time = "2025-08-07T13:18:32.861Z" }, - { url = "https://files.pythonhosted.org/packages/ee/43/3cecdc0349359e1a527cbf2e3e28e5f8f06d3343aaf82ca13437a9aa290f/greenlet-3.2.4-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23768528f2911bcd7e475210822ffb5254ed10d71f4028387e5a99b4c6699671", size = 610497, upload-time = "2025-08-07T13:18:31.636Z" }, - { url = "https://files.pythonhosted.org/packages/b8/19/06b6cf5d604e2c382a6f31cafafd6f33d5dea706f4db7bdab184bad2b21d/greenlet-3.2.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:00fadb3fedccc447f517ee0d3fd8fe49eae949e1cd0f6a611818f4f6fb7dc83b", size = 1121662, upload-time = "2025-08-07T13:42:41.117Z" }, - { url = "https://files.pythonhosted.org/packages/a2/15/0d5e4e1a66fab130d98168fe984c509249c833c1a3c16806b90f253ce7b9/greenlet-3.2.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:d25c5091190f2dc0eaa3f950252122edbbadbb682aa7b1ef2f8af0f8c0afefae", size = 1149210, upload-time = "2025-08-07T13:18:24.072Z" }, - { url = "https://files.pythonhosted.org/packages/1c/53/f9c440463b3057485b8594d7a638bed53ba531165ef0ca0e6c364b5cc807/greenlet-3.2.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6e343822feb58ac4d0a1211bd9399de2b3a04963ddeec21530fc426cc121f19b", size = 1564759, upload-time = "2025-11-04T12:42:19.395Z" }, - { url = "https://files.pythonhosted.org/packages/47/e4/3bb4240abdd0a8d23f4f88adec746a3099f0d86bfedb623f063b2e3b4df0/greenlet-3.2.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ca7f6f1f2649b89ce02f6f229d7c19f680a6238af656f61e0115b24857917929", size = 1634288, upload-time = "2025-11-04T12:42:21.174Z" }, - { url = "https://files.pythonhosted.org/packages/0b/55/2321e43595e6801e105fcfdee02b34c0f996eb71e6ddffca6b10b7e1d771/greenlet-3.2.4-cp313-cp313-win_amd64.whl", hash = "sha256:554b03b6e73aaabec3745364d6239e9e012d64c68ccd0b8430c64ccc14939a8b", size = 299685, upload-time = "2025-08-07T13:24:38.824Z" }, - { url = "https://files.pythonhosted.org/packages/22/5c/85273fd7cc388285632b0498dbbab97596e04b154933dfe0f3e68156c68c/greenlet-3.2.4-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:49a30d5fda2507ae77be16479bdb62a660fa51b1eb4928b524975b3bde77b3c0", size = 273586, upload-time = "2025-08-07T13:16:08.004Z" }, - { url = "https://files.pythonhosted.org/packages/d1/75/10aeeaa3da9332c2e761e4c50d4c3556c21113ee3f0afa2cf5769946f7a3/greenlet-3.2.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:299fd615cd8fc86267b47597123e3f43ad79c9d8a22bebdce535e53550763e2f", size = 686346, upload-time = "2025-08-07T13:42:59.944Z" }, - { url = "https://files.pythonhosted.org/packages/c0/aa/687d6b12ffb505a4447567d1f3abea23bd20e73a5bed63871178e0831b7a/greenlet-3.2.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:c17b6b34111ea72fc5a4e4beec9711d2226285f0386ea83477cbb97c30a3f3a5", size = 699218, upload-time = "2025-08-07T13:45:30.969Z" }, - { url = "https://files.pythonhosted.org/packages/dc/8b/29aae55436521f1d6f8ff4e12fb676f3400de7fcf27fccd1d4d17fd8fecd/greenlet-3.2.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b4a1870c51720687af7fa3e7cda6d08d801dae660f75a76f3845b642b4da6ee1", size = 694659, upload-time = "2025-08-07T13:53:17.759Z" }, - { url = "https://files.pythonhosted.org/packages/92/2e/ea25914b1ebfde93b6fc4ff46d6864564fba59024e928bdc7de475affc25/greenlet-3.2.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:061dc4cf2c34852b052a8620d40f36324554bc192be474b9e9770e8c042fd735", size = 695355, upload-time = "2025-08-07T13:18:34.517Z" }, - { url = "https://files.pythonhosted.org/packages/72/60/fc56c62046ec17f6b0d3060564562c64c862948c9d4bc8aa807cf5bd74f4/greenlet-3.2.4-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:44358b9bf66c8576a9f57a590d5f5d6e72fa4228b763d0e43fee6d3b06d3a337", size = 657512, upload-time = "2025-08-07T13:18:33.969Z" }, - { url = "https://files.pythonhosted.org/packages/23/6e/74407aed965a4ab6ddd93a7ded3180b730d281c77b765788419484cdfeef/greenlet-3.2.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:2917bdf657f5859fbf3386b12d68ede4cf1f04c90c3a6bc1f013dd68a22e2269", size = 1612508, upload-time = "2025-11-04T12:42:23.427Z" }, - { url = "https://files.pythonhosted.org/packages/0d/da/343cd760ab2f92bac1845ca07ee3faea9fe52bee65f7bcb19f16ad7de08b/greenlet-3.2.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:015d48959d4add5d6c9f6c5210ee3803a830dce46356e3bc326d6776bde54681", size = 1680760, upload-time = "2025-11-04T12:42:25.341Z" }, - { url = "https://files.pythonhosted.org/packages/e3/a5/6ddab2b4c112be95601c13428db1d8b6608a8b6039816f2ba09c346c08fc/greenlet-3.2.4-cp314-cp314-win_amd64.whl", hash = "sha256:e37ab26028f12dbb0ff65f29a8d3d44a765c61e729647bf2ddfbbed621726f01", size = 303425, upload-time = "2025-08-07T13:32:27.59Z" }, -] - -[[package]] -name = "playwright" -version = "1.56.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "greenlet" }, - { name = "pyee" }, -] -wheels = [ - { url = "https://files.pythonhosted.org/packages/6b/31/a5362cee43f844509f1f10d8a27c9cc0e2f7bdce5353d304d93b2151c1b1/playwright-1.56.0-py3-none-macosx_10_13_x86_64.whl", hash = "sha256:b33eb89c516cbc6723f2e3523bada4a4eb0984a9c411325c02d7016a5d625e9c", size = 40611424, upload-time = "2025-11-11T18:39:10.175Z" }, - { url = "https://files.pythonhosted.org/packages/ef/95/347eef596d8778fb53590dc326c344d427fa19ba3d42b646fce2a4572eb3/playwright-1.56.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:b228b3395212b9472a4ee5f1afe40d376eef9568eb039fcb3e563de8f4f4657b", size = 39400228, upload-time = "2025-11-11T18:39:13.915Z" }, - { url = "https://files.pythonhosted.org/packages/b9/54/6ad97b08b2ca1dfcb4fbde4536c4f45c0d9d8b1857a2d20e7bbfdf43bf15/playwright-1.56.0-py3-none-macosx_11_0_universal2.whl", hash = "sha256:0ef7e6fd653267798a8a968ff7aa2dcac14398b7dd7440ef57524e01e0fbbd65", size = 40611424, upload-time = "2025-11-11T18:39:17.093Z" }, - { url = "https://files.pythonhosted.org/packages/e4/76/6d409e37e82cdd5dda3df1ab958130ae32b46e42458bd4fc93d7eb8749cb/playwright-1.56.0-py3-none-manylinux1_x86_64.whl", hash = "sha256:404be089b49d94bc4c1fe0dfb07664bda5ffe87789034a03bffb884489bdfb5c", size = 46263122, upload-time = "2025-11-11T18:39:20.619Z" }, - { url = "https://files.pythonhosted.org/packages/4f/84/fb292cc5d45f3252e255ea39066cd1d2385c61c6c1596548dfbf59c88605/playwright-1.56.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64cda7cf4e51c0d35dab55190841bfcdfb5871685ec22cb722cd0ad2df183e34", size = 46110645, upload-time = "2025-11-11T18:39:24.005Z" }, - { url = "https://files.pythonhosted.org/packages/61/bd/8c02c3388ae14edc374ac9f22cbe4e14826c6a51b2d8eaf86e89fabee264/playwright-1.56.0-py3-none-win32.whl", hash = "sha256:d87b79bcb082092d916a332c27ec9732e0418c319755d235d93cc6be13bdd721", size = 35639837, upload-time = "2025-11-11T18:39:27.174Z" }, - { url = "https://files.pythonhosted.org/packages/64/27/f13b538fbc6b7a00152f4379054a49f6abc0bf55ac86f677ae54bc49fb82/playwright-1.56.0-py3-none-win_amd64.whl", hash = "sha256:3c7fc49bb9e673489bf2622855f9486d41c5101bbed964638552b864c4591f94", size = 35639843, upload-time = "2025-11-11T18:39:30.851Z" }, - { url = "https://files.pythonhosted.org/packages/f2/c7/3ee8b556107995846576b4fe42a08ed49b8677619421f2afacf6ee421138/playwright-1.56.0-py3-none-win_arm64.whl", hash = "sha256:2745490ae8dd58d27e5ea4d9aa28402e8e2991eb84fb4b2fd5fbde2106716f6f", size = 31248959, upload-time = "2025-11-11T18:39:33.998Z" }, -] - -[[package]] -name = "pyee" -version = "13.0.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/95/03/1fd98d5841cd7964a27d729ccf2199602fe05eb7a405c1462eb7277945ed/pyee-13.0.0.tar.gz", hash = "sha256:b391e3c5a434d1f5118a25615001dbc8f669cf410ab67d04c4d4e07c55481c37", size = 31250, upload-time = "2025-03-17T18:53:15.955Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9b/4d/b9add7c84060d4c1906abe9a7e5359f2a60f7a9a4f67268b2766673427d8/pyee-13.0.0-py3-none-any.whl", hash = "sha256:48195a3cddb3b1515ce0695ed76036b5ccc2ef3a9f963ff9f77aec0139845498", size = 15730, upload-time = "2025-03-17T18:53:14.532Z" }, -] - -[[package]] -name = "python-playwright" -version = "0.1.0" -source = { virtual = "." } -dependencies = [ - { name = "playwright" }, -] - -[package.metadata] -requires-dist = [{ name = "playwright", specifier = ">=1.49" }] - -[[package]] -name = "typing-extensions" -version = "4.15.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, -] diff --git a/mise.toml b/mise.toml index 6db910e7..a1f32c92 100644 --- a/mise.toml +++ b/mise.toml @@ -32,10 +32,6 @@ run = [ "go clean -testcache", "mise cache clear", "rm -rf /tmp/railpack", - # delete all top-level node_modules in examples/, this can cause state issues which cause snapshots to generate incorrectly - "find examples -maxdepth 2 -type d -name node_modules -exec rm -rf {} +", - # same goes for python .venv folders - "find examples -maxdepth 2 -type d -name .venv -exec rm -rf {} +", ] # if a example folder does not have a test.json file, it will be skipped From 2253fc789e02a8caef87f0be4baa45a1aaa797b3 Mon Sep 17 00:00:00 2001 From: Michael Bianco Date: Wed, 21 Jan 2026 07:50:11 -0700 Subject: [PATCH 2/2] feat: automatically install packages required for playwright, and playwright browser This reverts commit 2a5567ff09fa044cf391b1d79ecf1fe7846e8828. --- ...lanForExamples_node-playwright_1.snap.json | 189 ++++++++++++++++++ ...nForExamples_python-playwright_1.snap.json | 187 +++++++++++++++++ core/providers/node/node.go | 39 +++- core/providers/node/package_manager.go | 11 + core/providers/node/spa.go | 4 + core/providers/python/python.go | 32 ++- examples/node-playwright/index.js | 20 ++ examples/node-playwright/mise.toml | 3 + examples/node-playwright/package.json | 15 ++ examples/node-playwright/pnpm-lock.yaml | 43 ++++ examples/node-playwright/test.json | 5 + examples/python-playwright/main.py | 14 ++ examples/python-playwright/mise.toml | 3 + examples/python-playwright/pyproject.toml | 8 + examples/python-playwright/test.json | 5 + examples/python-playwright/uv.lock | 104 ++++++++++ mise.toml | 4 + 17 files changed, 672 insertions(+), 14 deletions(-) create mode 100755 core/__snapshots__/TestGenerateBuildPlanForExamples_node-playwright_1.snap.json create mode 100755 core/__snapshots__/TestGenerateBuildPlanForExamples_python-playwright_1.snap.json create mode 100644 examples/node-playwright/index.js create mode 100644 examples/node-playwright/mise.toml create mode 100644 examples/node-playwright/package.json create mode 100644 examples/node-playwright/pnpm-lock.yaml create mode 100644 examples/node-playwright/test.json create mode 100644 examples/python-playwright/main.py create mode 100644 examples/python-playwright/mise.toml create mode 100644 examples/python-playwright/pyproject.toml create mode 100644 examples/python-playwright/test.json create mode 100644 examples/python-playwright/uv.lock diff --git a/core/__snapshots__/TestGenerateBuildPlanForExamples_node-playwright_1.snap.json b/core/__snapshots__/TestGenerateBuildPlanForExamples_node-playwright_1.snap.json new file mode 100755 index 00000000..9c0c9e20 --- /dev/null +++ b/core/__snapshots__/TestGenerateBuildPlanForExamples_node-playwright_1.snap.json @@ -0,0 +1,189 @@ +{ + "caches": { + "apt": { + "directory": "/var/cache/apt", + "type": "locked" + }, + "apt-lists": { + "directory": "/var/lib/apt/lists", + "type": "locked" + }, + "node-modules": { + "directory": "/app/node_modules/.cache", + "type": "shared" + }, + "pnpm-install": { + "directory": "/root/.local/share/pnpm/store/v3", + "type": "shared" + } + }, + "deploy": { + "base": { + "step": "packages:apt:runtime" + }, + "inputs": [ + { + "include": [ + "/mise/shims", + "/mise/installs", + "/usr/local/bin/mise", + "/etc/mise/config.toml", + "/root/.local/state/mise" + ], + "step": "packages:mise" + }, + { + "include": [ + "/app/node_modules" + ], + "step": "build" + }, + { + "exclude": [ + "node_modules", + ".yarn" + ], + "include": [ + "/root/.cache", + "." + ], + "step": "build" + } + ], + "startCommand": "node index.js", + "variables": { + "CI": "true", + "NODE_ENV": "production", + "NPM_CONFIG_FUND": "false", + "NPM_CONFIG_PRODUCTION": "false", + "NPM_CONFIG_UPDATE_NOTIFIER": "false" + } + }, + "steps": [ + { + "assets": { + "mise.toml": "[mise.toml]" + }, + "commands": [ + { + "path": "/mise/shims" + }, + { + "dest": "mise.toml", + "src": "mise.toml" + }, + { + "customName": "create mise config", + "name": "mise.toml", + "path": "/etc/mise/config.toml" + }, + { + "cmd": "mise install", + "customName": "install mise packages: node, pnpm" + } + ], + "inputs": [ + { + "image": "ghcr.io/railwayapp/railpack-builder:latest" + } + ], + "name": "packages:mise", + "variables": { + "MISE_CACHE_DIR": "/mise/cache", + "MISE_CONFIG_DIR": "/mise", + "MISE_DATA_DIR": "/mise", + "MISE_IDIOMATIC_VERSION_FILE_ENABLE_TOOLS": "python,node,ruby,elixir,go,java,yarn", + "MISE_INSTALLS_DIR": "/mise/installs", + "MISE_NODE_VERIFY": "false", + "MISE_PARANOID": "1", + "MISE_SHIMS_DIR": "/mise/shims", + "MISE_TRUSTED_CONFIG_PATHS": "/app" + } + }, + { + "caches": [ + "pnpm-install" + ], + "commands": [ + { + "path": "/app/node_modules/.bin" + }, + { + "cmd": "mkdir -p /app/node_modules/.cache" + }, + { + "dest": "package.json", + "src": "package.json" + }, + { + "dest": "pnpm-lock.yaml", + "src": "pnpm-lock.yaml" + }, + { + "path": "/pnpm" + }, + { + "cmd": "pnpm add -g node-gyp" + }, + { + "cmd": "pnpm install --frozen-lockfile --prefer-offline" + }, + { + "cmd": "pnpm exec playwright install --only-shell" + } + ], + "inputs": [ + { + "step": "packages:mise" + } + ], + "name": "install", + "variables": { + "CI": "true", + "NODE_ENV": "production", + "NPM_CONFIG_FUND": "false", + "NPM_CONFIG_PRODUCTION": "false", + "NPM_CONFIG_UPDATE_NOTIFIER": "false", + "PNPM_HOME": "/pnpm" + } + }, + { + "caches": [ + "node-modules" + ], + "inputs": [ + { + "step": "install" + }, + { + "include": [ + "." + ], + "local": true + } + ], + "name": "build", + "secrets": [ + "*" + ] + }, + { + "caches": [ + "apt", + "apt-lists" + ], + "commands": [ + { + "cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y libasound2 libatk-bridge2.0-0 libatk1.0-0 libatomic1 libatspi2.0-0 libcairo2 libcups2 libgbm1 libglib2.0-0 libnspr4 libnss3 libpango-1.0-0 libxcomposite1 libxdamage1 libxfixes3 libxkbcommon0 libxrandr2'", + "customName": "install apt packages: libasound2 libatk-bridge2.0-0 libatk1.0-0 libatomic1 libatspi2.0-0 libcairo2 libcups2 libgbm1 libglib2.0-0 libnspr4 libnss3 libpango-1.0-0 libxcomposite1 libxdamage1 libxfixes3 libxkbcommon0 libxrandr2" + } + ], + "inputs": [ + { + "image": "ghcr.io/railwayapp/railpack-runtime:latest" + } + ], + "name": "packages:apt:runtime" + } + ] +} \ No newline at end of file diff --git a/core/__snapshots__/TestGenerateBuildPlanForExamples_python-playwright_1.snap.json b/core/__snapshots__/TestGenerateBuildPlanForExamples_python-playwright_1.snap.json new file mode 100755 index 00000000..66649ab2 --- /dev/null +++ b/core/__snapshots__/TestGenerateBuildPlanForExamples_python-playwright_1.snap.json @@ -0,0 +1,187 @@ +{ + "caches": { + "apt": { + "directory": "/var/cache/apt", + "type": "locked" + }, + "apt-lists": { + "directory": "/var/lib/apt/lists", + "type": "locked" + }, + "uv": { + "directory": "/opt/uv-cache", + "type": "shared" + } + }, + "deploy": { + "base": { + "step": "packages:apt:runtime" + }, + "inputs": [ + { + "include": [ + "/mise/shims", + "/mise/installs", + "/usr/local/bin/mise", + "/etc/mise/config.toml", + "/root/.local/state/mise" + ], + "step": "packages:mise" + }, + { + "include": [ + "/app/.venv", + "/root/.cache/ms-playwright" + ], + "step": "build" + }, + { + "exclude": [ + ".venv" + ], + "include": [ + "." + ], + "step": "build" + } + ], + "startCommand": "python main.py", + "variables": { + "PIP_DEFAULT_TIMEOUT": "100", + "PIP_DISABLE_PIP_VERSION_CHECK": "1", + "PYTHONDONTWRITEBYTECODE": "1", + "PYTHONFAULTHANDLER": "1", + "PYTHONHASHSEED": "random", + "PYTHONUNBUFFERED": "1" + } + }, + "steps": [ + { + "assets": { + "mise.toml": "[mise.toml]" + }, + "commands": [ + { + "path": "/mise/shims" + }, + { + "dest": "mise.toml", + "src": "mise.toml" + }, + { + "customName": "create mise config", + "name": "mise.toml", + "path": "/etc/mise/config.toml" + }, + { + "cmd": "mise install", + "customName": "install mise packages: python, uv" + } + ], + "inputs": [ + { + "image": "ghcr.io/railwayapp/railpack-builder:latest" + } + ], + "name": "packages:mise", + "variables": { + "MISE_CACHE_DIR": "/mise/cache", + "MISE_CONFIG_DIR": "/mise", + "MISE_DATA_DIR": "/mise", + "MISE_IDIOMATIC_VERSION_FILE_ENABLE_TOOLS": "python,node,ruby,elixir,go,java,yarn", + "MISE_INSTALLS_DIR": "/mise/installs", + "MISE_NODE_VERIFY": "false", + "MISE_PARANOID": "1", + "MISE_PYTHON_COMPILE": "false", + "MISE_SHIMS_DIR": "/mise/shims", + "MISE_TRUSTED_CONFIG_PATHS": "/app" + } + }, + { + "caches": [ + "uv" + ], + "commands": [ + { + "dest": "pyproject.toml", + "src": "pyproject.toml" + }, + { + "dest": "uv.lock", + "src": "uv.lock" + }, + { + "path": "/root/.local/bin" + }, + { + "path": "/app/.venv/bin" + }, + { + "cmd": "uv sync --locked --no-dev --no-install-project" + }, + { + "cmd": "playwright install --only-shell" + } + ], + "inputs": [ + { + "step": "packages:mise" + } + ], + "name": "install", + "variables": { + "PIP_DEFAULT_TIMEOUT": "100", + "PIP_DISABLE_PIP_VERSION_CHECK": "1", + "PYTHONDONTWRITEBYTECODE": "1", + "PYTHONFAULTHANDLER": "1", + "PYTHONHASHSEED": "random", + "PYTHONUNBUFFERED": "1", + "UV_CACHE_DIR": "/opt/uv-cache", + "UV_COMPILE_BYTECODE": "1", + "UV_LINK_MODE": "copy", + "UV_PYTHON_DOWNLOADS": "never", + "VIRTUAL_ENV": "/app/.venv" + } + }, + { + "commands": [ + { + "cmd": "uv sync --locked --no-dev --no-editable" + } + ], + "inputs": [ + { + "step": "install" + }, + { + "include": [ + "." + ], + "local": true + } + ], + "name": "build", + "secrets": [ + "*" + ] + }, + { + "caches": [ + "apt", + "apt-lists" + ], + "commands": [ + { + "cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y libasound2 libatk-bridge2.0-0 libatk1.0-0 libatspi2.0-0 libcairo2 libcups2 libgbm1 libglib2.0-0 libnspr4 libnss3 libpango-1.0-0 libxcomposite1 libxdamage1 libxfixes3 libxkbcommon0 libxrandr2'", + "customName": "install apt packages: libasound2 libatk-bridge2.0-0 libatk1.0-0 libatspi2.0-0 libcairo2 libcups2 libgbm1 libglib2.0-0 libnspr4 libnss3 libpango-1.0-0 libxcomposite1 libxdamage1 libxfixes3 libxkbcommon0 libxrandr2" + } + ], + "inputs": [ + { + "image": "ghcr.io/railwayapp/railpack-runtime:latest" + } + ], + "name": "packages:apt:runtime" + } + ] +} \ No newline at end of file diff --git a/core/providers/node/node.go b/core/providers/node/node.go index 4925b670..0e861edc 100644 --- a/core/providers/node/node.go +++ b/core/providers/node/node.go @@ -20,12 +20,20 @@ const ( DEFAULT_NODE_VERSION = "22" DEFAULT_BUN_VERSION = "latest" - COREPACK_HOME = "/opt/corepack" - // not used by npm, but many other tools: next, jest, webpack, etc - NODE_MODULES_CACHE = "/app/node_modules/.cache" + NODE_MODULES_CACHE = "/app/node_modules/.cache" + COREPACK_HOME = "/opt/corepack" + PLAYWRIGHT_CACHE_DIR = "/root/.cache/ms-playwright" ) +var nodeRuntimeDepRequirements = map[string][]string{ + // To find the latest list: run `npx puppeteer@latest install --help` and inspect docs + "puppeteer": {"xvfb", "gconf-service", "libasound2", "libatk1.0-0", "libc6", "libcairo2", "libcups2", "libdbus-1-3", "libexpat1", "libfontconfig1", "libgbm1", "libgcc1", "libgconf-2-4", "libgdk-pixbuf2.0-0", "libglib2.0-0", "libgtk-3-0", "libnspr4", "libpango-1.0-0", "libpangocairo-1.0-0", "libstdc++6", "libx11-6", "libx11-xcb1", "libxcb1", "libxcomposite1", "libxcursor1", "libxdamage1", "libxext6", "libxfixes3", "libxi6", "libxrandr2", "libxrender1", "libxss1", "libxtst6", "ca-certificates", "fonts-liberation", "libappindicator1", "libnss3", "lsb-release", "xdg-utils", "wget"}, + // To find the latest list: run `playwright install-deps chromium` and inspect the apt-get install output + // Or check: https://github.com/microsoft/playwright/blob/main/packages/playwright-core/browsers.json + "playwright": {"libglib2.0-0", "libatk1.0-0", "libatk-bridge2.0-0", "libcups2", "libxkbcommon0", "libatspi2.0-0", "libxcomposite1", "libxdamage1", "libxfixes3", "libxrandr2", "libgbm1", "libcairo2", "libpango-1.0-0", "libasound2", "libnspr4", "libnss3"}, +} + var ( // bunCommandRegex matches "bun" or "bunx" as a command (not part of another word) bunCommandRegex = regexp.MustCompile(`(^|\s|;|&|&&|\||\|\|)bunx?\s`) @@ -76,8 +84,6 @@ func (p *NodeProvider) Plan(ctx *generate.GenerateContext) error { ctx.Logger.LogInfo("Found workspace with %d packages", len(p.workspace.Packages)) } - isSPA := p.isSPA(ctx) - miseStep := ctx.GetMiseStepBuilder() p.InstallMisePackages(ctx, miseStep) @@ -85,6 +91,8 @@ func (p *NodeProvider) Plan(ctx *generate.GenerateContext) error { install.AddInput(plan.NewStepLayer(miseStep.Name())) p.InstallNodeDeps(ctx, install) + isSPA := p.isSPA(ctx) + prune := ctx.NewCommandStep("prune") prune.AddInput(plan.NewStepLayer(install.Name())) prune.Secrets = []string{} @@ -113,10 +121,21 @@ func (p *NodeProvider) Plan(ctx *generate.GenerateContext) error { buildIncludeDirs = append(buildIncludeDirs, COREPACK_HOME) } - runtimeAptPackages := []string{} + // determine additional Apt packages needed + + // Required for Node.js 25+ + runtimeAptPackages := []string{"libatomic1"} + if p.usesPuppeteer() { - ctx.Logger.LogInfo("Installing puppeteer dependencies") - runtimeAptPackages = append(runtimeAptPackages, "xvfb", "gconf-service", "libasound2", "libatk1.0-0", "libc6", "libcairo2", "libcups2", "libdbus-1-3", "libexpat1", "libfontconfig1", "libgbm1", "libgcc1", "libgconf-2-4", "libgdk-pixbuf2.0-0", "libglib2.0-0", "libgtk-3-0", "libnspr4", "libpango-1.0-0", "libpangocairo-1.0-0", "libstdc++6", "libx11-6", "libx11-xcb1", "libxcb1", "libxcomposite1", "libxcursor1", "libxdamage1", "libxext6", "libxfixes3", "libxi6", "libxrandr2", "libxrender1", "libxss1", "libxtst6", "ca-certificates", "fonts-liberation", "libappindicator1", "libnss3", "lsb-release", "xdg-utils", "wget") + ctx.Logger.LogInfo("Installing puppeteer packages") + runtimeAptPackages = append(runtimeAptPackages, nodeRuntimeDepRequirements["puppeteer"]...) + } + + if p.usesPlaywright() { + ctx.Logger.LogInfo("Installing playwright packages and headless browser") + runtimeAptPackages = append(runtimeAptPackages, nodeRuntimeDepRequirements["playwright"]...) + // --only-shell is smaller and more appropriate for server environments than full chromium + install.AddCommand(plan.NewExecCommand(p.packageManager.ExecCommand("playwright install --only-shell"))) } nodeModulesLayer := plan.NewStepLayer(build.Name(), plan.Filter{ @@ -386,6 +405,10 @@ func (p *NodeProvider) usesPuppeteer() bool { return p.workspace.HasDependency("puppeteer") } +func (p *NodeProvider) usesPlaywright() bool { + return p.workspace.HasDependency("playwright") +} + // determine the major version of yarn from a version string. These major versions are installed and managed quite // differently which is why we need to distinguish them here. func parseYarnPackageManager(pmVersion string) PackageManager { diff --git a/core/providers/node/package_manager.go b/core/providers/node/package_manager.go index 1f7a17a3..d5c192fd 100644 --- a/core/providers/node/package_manager.go +++ b/core/providers/node/package_manager.go @@ -47,6 +47,17 @@ func (p PackageManager) RunScriptCommand(cmd string) string { return "node " + cmd } +func (p PackageManager) ExecCommand(cmd string) string { + switch p { + case PackageManagerPnpm: + return fmt.Sprintf("pnpm exec %s", cmd) + case PackageManagerBun: + return fmt.Sprintf("bunx %s", cmd) + default: + return fmt.Sprintf("npx %s", cmd) + } +} + func (p PackageManager) installDependencies(ctx *generate.GenerateContext, workspace *Workspace, install *generate.CommandStepBuilder, usingCorepack bool) { packageJsons := workspace.AllPackageJson() diff --git a/core/providers/node/spa.go b/core/providers/node/spa.go index e77adf08..86b8f04f 100644 --- a/core/providers/node/spa.go +++ b/core/providers/node/spa.go @@ -5,6 +5,7 @@ import ( "fmt" "path" + "github.com/charmbracelet/log" "github.com/railwayapp/railpack/core/generate" "github.com/railwayapp/railpack/core/plan" ) @@ -56,6 +57,9 @@ func (p *NodeProvider) getSPAFramework(ctx *generate.GenerateContext) string { return "CRA" } else if p.isAngular(ctx) { return "Angular" + } else { + // this should never happen! + log.Error("SPA framework expected, but could not determine type") } return "" diff --git a/core/providers/python/python.go b/core/providers/python/python.go index b8b6766f..ee9171ac 100644 --- a/core/providers/python/python.go +++ b/core/providers/python/python.go @@ -18,6 +18,7 @@ const ( PIP_CACHE_DIR = "/opt/pip-cache" VENV_PATH = "/app/.venv" LOCAL_BIN_PATH = "/root/.local/bin" + PLAYWRIGHT_CACHE_DIR = "/root/.cache/ms-playwright" ) type PythonProvider struct{} @@ -67,6 +68,15 @@ func (p *PythonProvider) Plan(ctx *generate.GenerateContext) error { installOutputs = p.InstallPipenv(ctx, install) } + if p.usesDep(ctx, "playwright") { + ctx.Logger.LogInfo("Installing Playwright chromium browser") + // --only-shell installs only the headless shell version (chromium_headless_shell) + // This is smaller and more appropriate for server environments than full chromium + install.AddCommand(plan.NewExecCommand("playwright install --only-shell")) + // Include Playwright browser cache so browsers are available in deploy stage + installOutputs = append(installOutputs, PLAYWRIGHT_CACHE_DIR) + } + p.addMetadata(ctx) build.AddInput(plan.NewStepLayer(install.Name())) @@ -157,14 +167,16 @@ func (p *PythonProvider) InstallUv(ctx *generate.GenerateContext, install *gener install.AddEnvVars(p.GetPythonEnvVars(ctx)) p.copyInstallFiles(ctx, install) - install.AddCommands([]plan.Command{ + installCommands := []plan.Command{ plan.NewPathCommand(LOCAL_BIN_PATH), plan.NewPathCommand(VENV_PATH + "/bin"), // if we exclude workspace packages, uv.lock will fail the frozen test and the user will get an error // to avoid this, we (a) detect if workspace packages are required (b) if they aren't, we don't include project // source in order to optimize layer caching (c) install project in the build phase. plan.NewExecCommand("uv sync --locked --no-dev --no-install-project"), - }) + } + + install.AddCommands(installCommands) return []string{VENV_PATH} } @@ -209,11 +221,13 @@ func (p *PythonProvider) InstallPDM(ctx *generate.GenerateContext, install *gene }) p.copyInstallFiles(ctx, install) - install.AddCommands([]plan.Command{ + installCommands := []plan.Command{ plan.NewPathCommand(LOCAL_BIN_PATH), plan.NewPathCommand(VENV_PATH + "/bin"), plan.NewExecCommand("pdm install --check --prod --no-editable"), - }) + } + + install.AddCommands(installCommands) return []string{VENV_PATH} } @@ -229,11 +243,13 @@ func (p *PythonProvider) InstallPoetry(ctx *generate.GenerateContext, install *g }) p.copyInstallFiles(ctx, install) - install.AddCommands([]plan.Command{ + installCommands := []plan.Command{ plan.NewPathCommand(LOCAL_BIN_PATH), plan.NewPathCommand(VENV_PATH + "/bin"), plan.NewExecCommand("poetry install --no-interaction --no-ansi --only main --no-root"), - }) + } + + install.AddCommands(installCommands) return []string{VENV_PATH} } @@ -557,4 +573,8 @@ var pythonRuntimeDepRequirements = map[string][]string{ "pdf2image": {"poppler-utils"}, "pydub": {"ffmpeg"}, "pymovie": {"ffmpeg", "qt5-qmake", "qtbase5-dev", "qtbase5-dev-tools", "qttools5-dev-tools", "libqt5core5a", "python3-pyqt5"}, + // Playwright runtime dependencies for Chromium browser + // To find the latest list: run `playwright install-deps chromium` and inspect the apt-get install output + // Or check: https://github.com/microsoft/playwright/blob/main/packages/playwright-core/browsers.json + "playwright": {"libglib2.0-0", "libatk1.0-0", "libatk-bridge2.0-0", "libcups2", "libxkbcommon0", "libatspi2.0-0", "libxcomposite1", "libxdamage1", "libxfixes3", "libxrandr2", "libgbm1", "libcairo2", "libpango-1.0-0", "libasound2", "libnspr4", "libnss3"}, } diff --git a/examples/node-playwright/index.js b/examples/node-playwright/index.js new file mode 100644 index 00000000..43faf8ba --- /dev/null +++ b/examples/node-playwright/index.js @@ -0,0 +1,20 @@ +const { chromium } = require("playwright"); + +(async () => { + console.log("Starting Playwright"); + const browser = await chromium.launch({ + headless: true, + args: ["--no-sandbox"], + }); + const version = browser.version(); + console.log(`Chromium version: ${version}`); + console.log("Creating Page"); + const page = await browser.newPage(); + console.log("Navigating to hackernews"); + await page.goto("https://news.ycombinator.com", { + waitUntil: "networkidle", + }); + + await browser.close(); + console.log("Hello from playwright"); +})(); diff --git a/examples/node-playwright/mise.toml b/examples/node-playwright/mise.toml new file mode 100644 index 00000000..c284c6f4 --- /dev/null +++ b/examples/node-playwright/mise.toml @@ -0,0 +1,3 @@ +[tools] +node = "latest" +pnpm = "latest" diff --git a/examples/node-playwright/package.json b/examples/node-playwright/package.json new file mode 100644 index 00000000..14cdbea0 --- /dev/null +++ b/examples/node-playwright/package.json @@ -0,0 +1,15 @@ +{ + "name": "playwright-example", + "version": "1.0.0", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "description": "", + "dependencies": { + "playwright": "^1.49" + } +} diff --git a/examples/node-playwright/pnpm-lock.yaml b/examples/node-playwright/pnpm-lock.yaml new file mode 100644 index 00000000..dfd264cc --- /dev/null +++ b/examples/node-playwright/pnpm-lock.yaml @@ -0,0 +1,43 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + playwright: + specifier: ^1.49 + version: 1.56.1 + +packages: + + fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + playwright-core@1.56.1: + resolution: {integrity: sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ==} + engines: {node: '>=18'} + hasBin: true + + playwright@1.56.1: + resolution: {integrity: sha512-aFi5B0WovBHTEvpM3DzXTUaeN6eN0qWnTkKx4NQaH4Wvcmc153PdaY2UBdSYKaGYw+UyWXSVyxDUg5DoPEttjw==} + engines: {node: '>=18'} + hasBin: true + +snapshots: + + fsevents@2.3.2: + optional: true + + playwright-core@1.56.1: {} + + playwright@1.56.1: + dependencies: + playwright-core: 1.56.1 + optionalDependencies: + fsevents: 2.3.2 diff --git a/examples/node-playwright/test.json b/examples/node-playwright/test.json new file mode 100644 index 00000000..5fd48231 --- /dev/null +++ b/examples/node-playwright/test.json @@ -0,0 +1,5 @@ +[ + { + "expectedOutput": "Hello from playwright" + } +] diff --git a/examples/python-playwright/main.py b/examples/python-playwright/main.py new file mode 100644 index 00000000..1eabb4f2 --- /dev/null +++ b/examples/python-playwright/main.py @@ -0,0 +1,14 @@ +from playwright.sync_api import sync_playwright + +print("Starting Playwright") +with sync_playwright() as p: + browser = p.chromium.launch(headless=True, args=["--no-sandbox"]) + version = browser.version + print(f"Chromium version: {version}") + print("Creating Page") + page = browser.new_page() + print("Navigating to hackernews") + page.goto("https://news.ycombinator.com", wait_until="networkidle") + browser.close() + +print("Hello from playwright") diff --git a/examples/python-playwright/mise.toml b/examples/python-playwright/mise.toml new file mode 100644 index 00000000..96e04be8 --- /dev/null +++ b/examples/python-playwright/mise.toml @@ -0,0 +1,3 @@ +[tools] +python = "latest" +uv = "latest" diff --git a/examples/python-playwright/pyproject.toml b/examples/python-playwright/pyproject.toml new file mode 100644 index 00000000..217759ec --- /dev/null +++ b/examples/python-playwright/pyproject.toml @@ -0,0 +1,8 @@ +[project] +name = "python-playwright" +version = "0.1.0" +description = "Python Playwright example" +requires-python = ">=3.11" +dependencies = [ + "playwright>=1.49", +] diff --git a/examples/python-playwright/test.json b/examples/python-playwright/test.json new file mode 100644 index 00000000..5fd48231 --- /dev/null +++ b/examples/python-playwright/test.json @@ -0,0 +1,5 @@ +[ + { + "expectedOutput": "Hello from playwright" + } +] diff --git a/examples/python-playwright/uv.lock b/examples/python-playwright/uv.lock new file mode 100644 index 00000000..41e431ad --- /dev/null +++ b/examples/python-playwright/uv.lock @@ -0,0 +1,104 @@ +version = 1 +revision = 3 +requires-python = ">=3.11" + +[[package]] +name = "greenlet" +version = "3.2.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/03/b8/704d753a5a45507a7aab61f18db9509302ed3d0a27ac7e0359ec2905b1a6/greenlet-3.2.4.tar.gz", hash = "sha256:0dca0d95ff849f9a364385f36ab49f50065d76964944638be9691e1832e9f86d", size = 188260, upload-time = "2025-08-07T13:24:33.51Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a4/de/f28ced0a67749cac23fecb02b694f6473f47686dff6afaa211d186e2ef9c/greenlet-3.2.4-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:96378df1de302bc38e99c3a9aa311967b7dc80ced1dcc6f171e99842987882a2", size = 272305, upload-time = "2025-08-07T13:15:41.288Z" }, + { url = "https://files.pythonhosted.org/packages/09/16/2c3792cba130000bf2a31c5272999113f4764fd9d874fb257ff588ac779a/greenlet-3.2.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1ee8fae0519a337f2329cb78bd7a8e128ec0f881073d43f023c7b8d4831d5246", size = 632472, upload-time = "2025-08-07T13:42:55.044Z" }, + { url = "https://files.pythonhosted.org/packages/ae/8f/95d48d7e3d433e6dae5b1682e4292242a53f22df82e6d3dda81b1701a960/greenlet-3.2.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:94abf90142c2a18151632371140b3dba4dee031633fe614cb592dbb6c9e17bc3", size = 644646, upload-time = "2025-08-07T13:45:26.523Z" }, + { url = "https://files.pythonhosted.org/packages/d5/5e/405965351aef8c76b8ef7ad370e5da58d57ef6068df197548b015464001a/greenlet-3.2.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:4d1378601b85e2e5171b99be8d2dc85f594c79967599328f95c1dc1a40f1c633", size = 640519, upload-time = "2025-08-07T13:53:13.928Z" }, + { url = "https://files.pythonhosted.org/packages/25/5d/382753b52006ce0218297ec1b628e048c4e64b155379331f25a7316eb749/greenlet-3.2.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0db5594dce18db94f7d1650d7489909b57afde4c580806b8d9203b6e79cdc079", size = 639707, upload-time = "2025-08-07T13:18:27.146Z" }, + { url = "https://files.pythonhosted.org/packages/1f/8e/abdd3f14d735b2929290a018ecf133c901be4874b858dd1c604b9319f064/greenlet-3.2.4-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2523e5246274f54fdadbce8494458a2ebdcdbc7b802318466ac5606d3cded1f8", size = 587684, upload-time = "2025-08-07T13:18:25.164Z" }, + { url = "https://files.pythonhosted.org/packages/5d/65/deb2a69c3e5996439b0176f6651e0052542bb6c8f8ec2e3fba97c9768805/greenlet-3.2.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1987de92fec508535687fb807a5cea1560f6196285a4cde35c100b8cd632cc52", size = 1116647, upload-time = "2025-08-07T13:42:38.655Z" }, + { url = "https://files.pythonhosted.org/packages/3f/cc/b07000438a29ac5cfb2194bfc128151d52f333cee74dd7dfe3fb733fc16c/greenlet-3.2.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:55e9c5affaa6775e2c6b67659f3a71684de4c549b3dd9afca3bc773533d284fa", size = 1142073, upload-time = "2025-08-07T13:18:21.737Z" }, + { url = "https://files.pythonhosted.org/packages/67/24/28a5b2fa42d12b3d7e5614145f0bd89714c34c08be6aabe39c14dd52db34/greenlet-3.2.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c9c6de1940a7d828635fbd254d69db79e54619f165ee7ce32fda763a9cb6a58c", size = 1548385, upload-time = "2025-11-04T12:42:11.067Z" }, + { url = "https://files.pythonhosted.org/packages/6a/05/03f2f0bdd0b0ff9a4f7b99333d57b53a7709c27723ec8123056b084e69cd/greenlet-3.2.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:03c5136e7be905045160b1b9fdca93dd6727b180feeafda6818e6496434ed8c5", size = 1613329, upload-time = "2025-11-04T12:42:12.928Z" }, + { url = "https://files.pythonhosted.org/packages/d8/0f/30aef242fcab550b0b3520b8e3561156857c94288f0332a79928c31a52cf/greenlet-3.2.4-cp311-cp311-win_amd64.whl", hash = "sha256:9c40adce87eaa9ddb593ccb0fa6a07caf34015a29bf8d344811665b573138db9", size = 299100, upload-time = "2025-08-07T13:44:12.287Z" }, + { url = "https://files.pythonhosted.org/packages/44/69/9b804adb5fd0671f367781560eb5eb586c4d495277c93bde4307b9e28068/greenlet-3.2.4-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:3b67ca49f54cede0186854a008109d6ee71f66bd57bb36abd6d0a0267b540cdd", size = 274079, upload-time = "2025-08-07T13:15:45.033Z" }, + { url = "https://files.pythonhosted.org/packages/46/e9/d2a80c99f19a153eff70bc451ab78615583b8dac0754cfb942223d2c1a0d/greenlet-3.2.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ddf9164e7a5b08e9d22511526865780a576f19ddd00d62f8a665949327fde8bb", size = 640997, upload-time = "2025-08-07T13:42:56.234Z" }, + { url = "https://files.pythonhosted.org/packages/3b/16/035dcfcc48715ccd345f3a93183267167cdd162ad123cd93067d86f27ce4/greenlet-3.2.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f28588772bb5fb869a8eb331374ec06f24a83a9c25bfa1f38b6993afe9c1e968", size = 655185, upload-time = "2025-08-07T13:45:27.624Z" }, + { url = "https://files.pythonhosted.org/packages/31/da/0386695eef69ffae1ad726881571dfe28b41970173947e7c558d9998de0f/greenlet-3.2.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:5c9320971821a7cb77cfab8d956fa8e39cd07ca44b6070db358ceb7f8797c8c9", size = 649926, upload-time = "2025-08-07T13:53:15.251Z" }, + { url = "https://files.pythonhosted.org/packages/68/88/69bf19fd4dc19981928ceacbc5fd4bb6bc2215d53199e367832e98d1d8fe/greenlet-3.2.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c60a6d84229b271d44b70fb6e5fa23781abb5d742af7b808ae3f6efd7c9c60f6", size = 651839, upload-time = "2025-08-07T13:18:30.281Z" }, + { url = "https://files.pythonhosted.org/packages/19/0d/6660d55f7373b2ff8152401a83e02084956da23ae58cddbfb0b330978fe9/greenlet-3.2.4-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b3812d8d0c9579967815af437d96623f45c0f2ae5f04e366de62a12d83a8fb0", size = 607586, upload-time = "2025-08-07T13:18:28.544Z" }, + { url = "https://files.pythonhosted.org/packages/8e/1a/c953fdedd22d81ee4629afbb38d2f9d71e37d23caace44775a3a969147d4/greenlet-3.2.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:abbf57b5a870d30c4675928c37278493044d7c14378350b3aa5d484fa65575f0", size = 1123281, upload-time = "2025-08-07T13:42:39.858Z" }, + { url = "https://files.pythonhosted.org/packages/3f/c7/12381b18e21aef2c6bd3a636da1088b888b97b7a0362fac2e4de92405f97/greenlet-3.2.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:20fb936b4652b6e307b8f347665e2c615540d4b42b3b4c8a321d8286da7e520f", size = 1151142, upload-time = "2025-08-07T13:18:22.981Z" }, + { url = "https://files.pythonhosted.org/packages/27/45/80935968b53cfd3f33cf99ea5f08227f2646e044568c9b1555b58ffd61c2/greenlet-3.2.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ee7a6ec486883397d70eec05059353b8e83eca9168b9f3f9a361971e77e0bcd0", size = 1564846, upload-time = "2025-11-04T12:42:15.191Z" }, + { url = "https://files.pythonhosted.org/packages/69/02/b7c30e5e04752cb4db6202a3858b149c0710e5453b71a3b2aec5d78a1aab/greenlet-3.2.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:326d234cbf337c9c3def0676412eb7040a35a768efc92504b947b3e9cfc7543d", size = 1633814, upload-time = "2025-11-04T12:42:17.175Z" }, + { url = "https://files.pythonhosted.org/packages/e9/08/b0814846b79399e585f974bbeebf5580fbe59e258ea7be64d9dfb253c84f/greenlet-3.2.4-cp312-cp312-win_amd64.whl", hash = "sha256:a7d4e128405eea3814a12cc2605e0e6aedb4035bf32697f72deca74de4105e02", size = 299899, upload-time = "2025-08-07T13:38:53.448Z" }, + { url = "https://files.pythonhosted.org/packages/49/e8/58c7f85958bda41dafea50497cbd59738c5c43dbbea5ee83d651234398f4/greenlet-3.2.4-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:1a921e542453fe531144e91e1feedf12e07351b1cf6c9e8a3325ea600a715a31", size = 272814, upload-time = "2025-08-07T13:15:50.011Z" }, + { url = "https://files.pythonhosted.org/packages/62/dd/b9f59862e9e257a16e4e610480cfffd29e3fae018a68c2332090b53aac3d/greenlet-3.2.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cd3c8e693bff0fff6ba55f140bf390fa92c994083f838fece0f63be121334945", size = 641073, upload-time = "2025-08-07T13:42:57.23Z" }, + { url = "https://files.pythonhosted.org/packages/f7/0b/bc13f787394920b23073ca3b6c4a7a21396301ed75a655bcb47196b50e6e/greenlet-3.2.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:710638eb93b1fa52823aa91bf75326f9ecdfd5e0466f00789246a5280f4ba0fc", size = 655191, upload-time = "2025-08-07T13:45:29.752Z" }, + { url = "https://files.pythonhosted.org/packages/f2/d6/6adde57d1345a8d0f14d31e4ab9c23cfe8e2cd39c3baf7674b4b0338d266/greenlet-3.2.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:c5111ccdc9c88f423426df3fd1811bfc40ed66264d35aa373420a34377efc98a", size = 649516, upload-time = "2025-08-07T13:53:16.314Z" }, + { url = "https://files.pythonhosted.org/packages/7f/3b/3a3328a788d4a473889a2d403199932be55b1b0060f4ddd96ee7cdfcad10/greenlet-3.2.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d76383238584e9711e20ebe14db6c88ddcedc1829a9ad31a584389463b5aa504", size = 652169, upload-time = "2025-08-07T13:18:32.861Z" }, + { url = "https://files.pythonhosted.org/packages/ee/43/3cecdc0349359e1a527cbf2e3e28e5f8f06d3343aaf82ca13437a9aa290f/greenlet-3.2.4-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23768528f2911bcd7e475210822ffb5254ed10d71f4028387e5a99b4c6699671", size = 610497, upload-time = "2025-08-07T13:18:31.636Z" }, + { url = "https://files.pythonhosted.org/packages/b8/19/06b6cf5d604e2c382a6f31cafafd6f33d5dea706f4db7bdab184bad2b21d/greenlet-3.2.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:00fadb3fedccc447f517ee0d3fd8fe49eae949e1cd0f6a611818f4f6fb7dc83b", size = 1121662, upload-time = "2025-08-07T13:42:41.117Z" }, + { url = "https://files.pythonhosted.org/packages/a2/15/0d5e4e1a66fab130d98168fe984c509249c833c1a3c16806b90f253ce7b9/greenlet-3.2.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:d25c5091190f2dc0eaa3f950252122edbbadbb682aa7b1ef2f8af0f8c0afefae", size = 1149210, upload-time = "2025-08-07T13:18:24.072Z" }, + { url = "https://files.pythonhosted.org/packages/1c/53/f9c440463b3057485b8594d7a638bed53ba531165ef0ca0e6c364b5cc807/greenlet-3.2.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6e343822feb58ac4d0a1211bd9399de2b3a04963ddeec21530fc426cc121f19b", size = 1564759, upload-time = "2025-11-04T12:42:19.395Z" }, + { url = "https://files.pythonhosted.org/packages/47/e4/3bb4240abdd0a8d23f4f88adec746a3099f0d86bfedb623f063b2e3b4df0/greenlet-3.2.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ca7f6f1f2649b89ce02f6f229d7c19f680a6238af656f61e0115b24857917929", size = 1634288, upload-time = "2025-11-04T12:42:21.174Z" }, + { url = "https://files.pythonhosted.org/packages/0b/55/2321e43595e6801e105fcfdee02b34c0f996eb71e6ddffca6b10b7e1d771/greenlet-3.2.4-cp313-cp313-win_amd64.whl", hash = "sha256:554b03b6e73aaabec3745364d6239e9e012d64c68ccd0b8430c64ccc14939a8b", size = 299685, upload-time = "2025-08-07T13:24:38.824Z" }, + { url = "https://files.pythonhosted.org/packages/22/5c/85273fd7cc388285632b0498dbbab97596e04b154933dfe0f3e68156c68c/greenlet-3.2.4-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:49a30d5fda2507ae77be16479bdb62a660fa51b1eb4928b524975b3bde77b3c0", size = 273586, upload-time = "2025-08-07T13:16:08.004Z" }, + { url = "https://files.pythonhosted.org/packages/d1/75/10aeeaa3da9332c2e761e4c50d4c3556c21113ee3f0afa2cf5769946f7a3/greenlet-3.2.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:299fd615cd8fc86267b47597123e3f43ad79c9d8a22bebdce535e53550763e2f", size = 686346, upload-time = "2025-08-07T13:42:59.944Z" }, + { url = "https://files.pythonhosted.org/packages/c0/aa/687d6b12ffb505a4447567d1f3abea23bd20e73a5bed63871178e0831b7a/greenlet-3.2.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:c17b6b34111ea72fc5a4e4beec9711d2226285f0386ea83477cbb97c30a3f3a5", size = 699218, upload-time = "2025-08-07T13:45:30.969Z" }, + { url = "https://files.pythonhosted.org/packages/dc/8b/29aae55436521f1d6f8ff4e12fb676f3400de7fcf27fccd1d4d17fd8fecd/greenlet-3.2.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b4a1870c51720687af7fa3e7cda6d08d801dae660f75a76f3845b642b4da6ee1", size = 694659, upload-time = "2025-08-07T13:53:17.759Z" }, + { url = "https://files.pythonhosted.org/packages/92/2e/ea25914b1ebfde93b6fc4ff46d6864564fba59024e928bdc7de475affc25/greenlet-3.2.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:061dc4cf2c34852b052a8620d40f36324554bc192be474b9e9770e8c042fd735", size = 695355, upload-time = "2025-08-07T13:18:34.517Z" }, + { url = "https://files.pythonhosted.org/packages/72/60/fc56c62046ec17f6b0d3060564562c64c862948c9d4bc8aa807cf5bd74f4/greenlet-3.2.4-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:44358b9bf66c8576a9f57a590d5f5d6e72fa4228b763d0e43fee6d3b06d3a337", size = 657512, upload-time = "2025-08-07T13:18:33.969Z" }, + { url = "https://files.pythonhosted.org/packages/23/6e/74407aed965a4ab6ddd93a7ded3180b730d281c77b765788419484cdfeef/greenlet-3.2.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:2917bdf657f5859fbf3386b12d68ede4cf1f04c90c3a6bc1f013dd68a22e2269", size = 1612508, upload-time = "2025-11-04T12:42:23.427Z" }, + { url = "https://files.pythonhosted.org/packages/0d/da/343cd760ab2f92bac1845ca07ee3faea9fe52bee65f7bcb19f16ad7de08b/greenlet-3.2.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:015d48959d4add5d6c9f6c5210ee3803a830dce46356e3bc326d6776bde54681", size = 1680760, upload-time = "2025-11-04T12:42:25.341Z" }, + { url = "https://files.pythonhosted.org/packages/e3/a5/6ddab2b4c112be95601c13428db1d8b6608a8b6039816f2ba09c346c08fc/greenlet-3.2.4-cp314-cp314-win_amd64.whl", hash = "sha256:e37ab26028f12dbb0ff65f29a8d3d44a765c61e729647bf2ddfbbed621726f01", size = 303425, upload-time = "2025-08-07T13:32:27.59Z" }, +] + +[[package]] +name = "playwright" +version = "1.56.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "greenlet" }, + { name = "pyee" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/6b/31/a5362cee43f844509f1f10d8a27c9cc0e2f7bdce5353d304d93b2151c1b1/playwright-1.56.0-py3-none-macosx_10_13_x86_64.whl", hash = "sha256:b33eb89c516cbc6723f2e3523bada4a4eb0984a9c411325c02d7016a5d625e9c", size = 40611424, upload-time = "2025-11-11T18:39:10.175Z" }, + { url = "https://files.pythonhosted.org/packages/ef/95/347eef596d8778fb53590dc326c344d427fa19ba3d42b646fce2a4572eb3/playwright-1.56.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:b228b3395212b9472a4ee5f1afe40d376eef9568eb039fcb3e563de8f4f4657b", size = 39400228, upload-time = "2025-11-11T18:39:13.915Z" }, + { url = "https://files.pythonhosted.org/packages/b9/54/6ad97b08b2ca1dfcb4fbde4536c4f45c0d9d8b1857a2d20e7bbfdf43bf15/playwright-1.56.0-py3-none-macosx_11_0_universal2.whl", hash = "sha256:0ef7e6fd653267798a8a968ff7aa2dcac14398b7dd7440ef57524e01e0fbbd65", size = 40611424, upload-time = "2025-11-11T18:39:17.093Z" }, + { url = "https://files.pythonhosted.org/packages/e4/76/6d409e37e82cdd5dda3df1ab958130ae32b46e42458bd4fc93d7eb8749cb/playwright-1.56.0-py3-none-manylinux1_x86_64.whl", hash = "sha256:404be089b49d94bc4c1fe0dfb07664bda5ffe87789034a03bffb884489bdfb5c", size = 46263122, upload-time = "2025-11-11T18:39:20.619Z" }, + { url = "https://files.pythonhosted.org/packages/4f/84/fb292cc5d45f3252e255ea39066cd1d2385c61c6c1596548dfbf59c88605/playwright-1.56.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64cda7cf4e51c0d35dab55190841bfcdfb5871685ec22cb722cd0ad2df183e34", size = 46110645, upload-time = "2025-11-11T18:39:24.005Z" }, + { url = "https://files.pythonhosted.org/packages/61/bd/8c02c3388ae14edc374ac9f22cbe4e14826c6a51b2d8eaf86e89fabee264/playwright-1.56.0-py3-none-win32.whl", hash = "sha256:d87b79bcb082092d916a332c27ec9732e0418c319755d235d93cc6be13bdd721", size = 35639837, upload-time = "2025-11-11T18:39:27.174Z" }, + { url = "https://files.pythonhosted.org/packages/64/27/f13b538fbc6b7a00152f4379054a49f6abc0bf55ac86f677ae54bc49fb82/playwright-1.56.0-py3-none-win_amd64.whl", hash = "sha256:3c7fc49bb9e673489bf2622855f9486d41c5101bbed964638552b864c4591f94", size = 35639843, upload-time = "2025-11-11T18:39:30.851Z" }, + { url = "https://files.pythonhosted.org/packages/f2/c7/3ee8b556107995846576b4fe42a08ed49b8677619421f2afacf6ee421138/playwright-1.56.0-py3-none-win_arm64.whl", hash = "sha256:2745490ae8dd58d27e5ea4d9aa28402e8e2991eb84fb4b2fd5fbde2106716f6f", size = 31248959, upload-time = "2025-11-11T18:39:33.998Z" }, +] + +[[package]] +name = "pyee" +version = "13.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/95/03/1fd98d5841cd7964a27d729ccf2199602fe05eb7a405c1462eb7277945ed/pyee-13.0.0.tar.gz", hash = "sha256:b391e3c5a434d1f5118a25615001dbc8f669cf410ab67d04c4d4e07c55481c37", size = 31250, upload-time = "2025-03-17T18:53:15.955Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/4d/b9add7c84060d4c1906abe9a7e5359f2a60f7a9a4f67268b2766673427d8/pyee-13.0.0-py3-none-any.whl", hash = "sha256:48195a3cddb3b1515ce0695ed76036b5ccc2ef3a9f963ff9f77aec0139845498", size = 15730, upload-time = "2025-03-17T18:53:14.532Z" }, +] + +[[package]] +name = "python-playwright" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "playwright" }, +] + +[package.metadata] +requires-dist = [{ name = "playwright", specifier = ">=1.49" }] + +[[package]] +name = "typing-extensions" +version = "4.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, +] diff --git a/mise.toml b/mise.toml index a1f32c92..6db910e7 100644 --- a/mise.toml +++ b/mise.toml @@ -32,6 +32,10 @@ run = [ "go clean -testcache", "mise cache clear", "rm -rf /tmp/railpack", + # delete all top-level node_modules in examples/, this can cause state issues which cause snapshots to generate incorrectly + "find examples -maxdepth 2 -type d -name node_modules -exec rm -rf {} +", + # same goes for python .venv folders + "find examples -maxdepth 2 -type d -name .venv -exec rm -rf {} +", ] # if a example folder does not have a test.json file, it will be skipped