ci: replace browser-driver-manager with browser-actions/setup-chrome#1345
ci: replace browser-driver-manager with browser-actions/setup-chrome#1345Garbee wants to merge 10 commits into
Conversation
Standardize Chrome and ChromeDriver discovery across every browser test suite around two env vars (CHROME_TEST_PATH, CHROMEDRIVER_TEST_PATH) and move CI from pinned chrome@145 via browser-driver-manager to browser-actions/setup-chrome, defaulting to 'latest' and overridable via the CHROME_VERSION repository variable. - workflow: drop the four BDM install steps and the Playwright install; install chrome+driver via browser-actions/setup-chrome in puppeteer, cli, webdriverjs, webdriverio, playwright, and wdio_globals_test; export the action outputs through $GITHUB_ENV. - webdriverio export harness now reads CHROME_TEST_PATH and CHROMEDRIVER_TEST_PATH (fixes Chrome 148 vs chromedriver 146 mismatch that broke test:esm on Ubuntu 24 runners). - puppeteer and playwright honor CHROME_TEST_PATH via executablePath. - test/wdio honors CHROME_TEST_PATH via goog:chromeOptions.binary. - remove browser-driver-manager dotenv loaders from webdriverio, webdriverjs, and cli; drop browser-driver-manager and the cli's dotenv dep from package.json; refresh package-lock.json.
`latest` follows Canary; `stable` matches what most users actually run and what the runner image installs by default.
Chromium installed by setup-chrome cannot start its zygote sandbox on
GitHub's Ubuntu 24 runners, so the session is killed immediately
("Chrome instance exited"). Mirrors the args the other browser suites
already pass for the same reason.
Drop the CI-implementation hint from the assertion failures and instead walk the developer through installing Chrome / ChromeDriver locally with @puppeteer/browsers and exporting the printed path into the env var.
| - shell: 'script -q -e -c "bash {0}"' | ||
| run: npx browser-driver-manager install chrome@145 | ||
| working-directory: packages/puppeteer | ||
| - uses: browser-actions/setup-chrome@v1 |
There was a problem hiding this comment.
The same setup-chrome block repeats in six jobs intentionally — composite actions aren't worth introducing for a five-line snippet, and YAML anchors don't play nicely with uses:. To override Chrome version repo-wide: set a CHROME_VERSION repository variable (Settings → Variables) to something like 120 or beta; unset it to track stable. install-chromedriver: true guarantees a version-matched driver beside the browser, and we hoist both outputs into $GITHUB_ENV so subsequent npm run steps inherit them — that's what fixes the original mismatch where the chromedriver npm pin and the runner-image Chrome had drifted apart.
| cache: 'npm' | ||
| - run: npm ci | ||
| - run: npx playwright install --with-deps | ||
| - uses: browser-actions/setup-chrome@v1 |
There was a problem hiding this comment.
Playwright now gets the same setup-chrome treatment instead of npx playwright install --with-deps. install-dependencies: true on the action covers the OS libs, and Playwright launches our binary via executablePath (see axe-playwright.spec.ts), so we never download Playwright's own Chromium build in CI. Local dev is unaffected because the spec falls back to Playwright's bundled Chromium when CHROME_TEST_PATH is empty.
| node-version: ${{ matrix.node }} | ||
| cache: 'npm' | ||
| - run: npm ci | ||
| - uses: browser-actions/setup-chrome@v1 |
There was a problem hiding this comment.
This job had no Chrome install step before. Now it gets the same env-var contract as the rest. Pair this with the --no-sandbox / --disable-dev-shm-usage flags added to wdio.conf.ts — without those the setup-chrome Chromium binary's zygote can't sandbox itself on Ubuntu 24 (restricted user-namespace clone) and Chrome exits immediately. That's the regression that initially failed this job after the workflow change.
| import { getFreePort, connectToChromeDriver } from './testUtils.js'; | ||
|
|
||
| const { default: { path: chromedriverPath } } = await import('chromedriver'); | ||
| const chromedriverPath = |
There was a problem hiding this comment.
This is the actual fix for PR #1344. Previously this harness used the chromedriver npm package (pinned ^146) and launched it against whatever Chrome the runner image had (148), producing the "session not created — only supports Chrome 146" failure. Reading CHROMEDRIVER_TEST_PATH first means CI uses the setup-chrome-installed driver (version-matched to CHROME_TEST_PATH); the npm package stays as the local-dev fallback so npm test without env vars still works.
| 'goog:chromeOptions': { | ||
| args: ['--headless', '--no-sandbox'] | ||
| args: ['--headless', '--no-sandbox'], | ||
| ...(chromeBinary && { binary: chromeBinary }) |
There was a problem hiding this comment.
Spread is conditional so the unset case leaves capabilities untouched and webdriverio's Selenium Manager finds a system Chrome. Setting binary: undefined here would override Selenium Manager and break local dev.
| options.args.push('--no-sandbox', '--disable-setuid-sandbox'); | ||
| } | ||
|
|
||
| if (process.env.CHROME_TEST_PATH) { |
There was a problem hiding this comment.
Same fallback pattern as the playwright and wdio configs: when CI set CHROME_TEST_PATH, use that binary; otherwise let Puppeteer launch its bundled Chromium. The previous /usr/bin/google-chrome-stable hardcode in the sibling esmTest.mjs is gone for the same reason — system Chrome paths aren't portable across runner images, and now we don't need to guess.
| browser = await chromium.launch({ | ||
| args: ['--disable-dev-shm-usage'] | ||
| args: ['--disable-dev-shm-usage'], | ||
| ...(process.env.CHROME_TEST_PATH && { |
There was a problem hiding this comment.
Playwright supports launching arbitrary Chromium-compatible binaries via executablePath. Conditional spread preserves the local-dev path: unset env var → Playwright's bundled Chromium; set env var → setup-chrome's binary. No --with-deps install needed in the workflow because setup-chrome's install-dependencies: true handles the OS libs.
Env-var contract for reviewersEvery browser test suite reads two env vars now:
Both are populated by The original failure (PR #1344) was a Chrome/chromedriver version mismatch in |
| '--no-sandbox', | ||
| '--disable-dev-shm-usage' |
There was a problem hiding this comment.
These flags didn't matter before this PR — wdio_globals_test had no explicit Chrome install and Selenium Manager auto-discovered the system Chrome with whatever defaults it needed. Now that we point wdio at setup-chrome's Chromium explicitly, Ubuntu 24's restricted user-namespace clone prevents the zygote from sandboxing itself and Chromium exits immediately on session create. Every other browser suite already passes --no-sandbox for the same reason (see linked Selenium issue) — this brings wdio in line.
There was a problem hiding this comment.
Pull request overview
This pull request migrates the CI browser setup away from browser-driver-manager to browser-actions/setup-chrome, and standardizes how test suites locate Chrome/ChromeDriver via CHROME_TEST_PATH and CHROMEDRIVER_TEST_PATH.
Changes:
- Updated CI workflow browser installation to use
browser-actions/setup-chromeand exportCHROME_TEST_PATH/CHROMEDRIVER_TEST_PATHfor multiple jobs. - Removed Browser Driver Manager env loading (
dotenv+~/.browser-driver-manager/.env) from several suites and adjusted tests to read the standardized env vars. - Updated Puppeteer/Playwright/WebDriverIO/WDIO globals configs to optionally use the Chrome binary provided by
CHROME_TEST_PATH.
Reviewed changes
Copilot reviewed 13 out of 14 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
.github/workflows/tests.yml |
Replaces browser-driver-manager install steps with browser-actions/setup-chrome and exports Chrome/ChromeDriver paths via $GITHUB_ENV. |
package.json |
Removes root dependency on browser-driver-manager. |
package-lock.json |
Removes browser-driver-manager and updates the lockfile accordingly. |
packages/cli/package.json |
Drops dotenv dependency from the CLI package. |
packages/cli/src/lib/utils.ts |
Removes BDM .env loading; relies on process.env for Chrome/ChromeDriver paths. |
packages/cli/src/lib/webdriver.test.ts |
Updates assertions/messages to require standardized env vars (no BDM install instructions). |
packages/playwright/test/axe-playwright.spec.ts |
Launches Playwright Chromium with executablePath from CHROME_TEST_PATH when present. |
packages/puppeteer/test/utils.ts |
Sets Puppeteer executablePath from CHROME_TEST_PATH when present. |
packages/puppeteer/test/esmTest.mjs |
Uses CHROME_TEST_PATH instead of a hardcoded /usr/bin/google-chrome-stable path. |
packages/webdriverjs/test/test-utils.ts |
Removes BDM .env loading and updates env var requirement messages. |
packages/webdriverio/test/testUtils.js |
Removes loadBdmEnv helper and related dotenv usage. |
packages/webdriverio/test/axe-webdriverio.spec.ts |
Stops loading BDM env; consumes standardized env vars directly. |
packages/webdriverio/test/esmTest.mjs |
Uses CHROMEDRIVER_TEST_PATH when available and optionally sets Chrome binary via CHROME_TEST_PATH. |
test/wdio/wdio.conf.ts |
Adds CI-safe Chrome flags and optionally sets Chrome binary via CHROME_TEST_PATH. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
chutchins25
left a comment
There was a problem hiding this comment.
Claude suggested several places that may be public facing and may need to be updated with install guidance.
packages/cli/README.md:17packages/webdriverjs/README.md:15packages/webdriverio/README.md:23packages/cli/src/bin/index.ts:134-140(runtime error printed to axe-cli users when Chrome/ChromeDriver can't be located)
The new in-test assertion messages already point at npx @puppeteer/browsers install …. Would it be good to bring the above READMEs and CLI runtime message in line?
|
Doc updates are good catches. I'll look into it. Runtime error though, not sure. I really need to look into the specifics of that one. The changes here shouldn't be too impactful to any existing code in this regard. Drafting until I rectify those things. |
chutchins25
left a comment
There was a problem hiding this comment.
One last documentation update thought.
The runtime error in packages/cli/src/bin/index.ts:147 correctly tells users to pass both --chrome-path AND --chromedriver-path — because @puppeteer/browsers installs Chrome to ~/.cache/puppeteer (not on PATH), so the bundled chromedriver npm fallback can't auto-discover it. The README, however, only shows
--chromedriver-path:
Each command prints the resolved binary path. Pass the ChromeDriver path to axe via --chromedriver-path .
A user following the README verbatim would hit the exact SessionNotCreatedError that the runtime-message update is designed to recover from. Should we update the README so they agree for this case?
|
Looking into the readme thing. But Let me try to get the messaging updated to be clear about that. |
Recommend `npx @puppeteer/browsers install ... --path ~/.cache/puppeteer-browsers` so binaries live in a stable shared location, and explain that both the Chrome and ChromeDriver paths must be wired into the user's setup — otherwise ChromeDriver auto-discovers the system Chrome (almost never the same version) and fails with `session not created`.
Bring the runtime CLI version-mismatch error and the test-suite env-var setup assertions in line with the README guidance: both now suggest `@puppeteer/browsers install ... --path ~/.cache/puppeteer-browsers` so binaries land in a stable shared location instead of polluting whatever directory `npx` happens to be invoked from.
Previous axe-cli versions documented `browser-driver-manager` as the install path and silently auto-loaded the env vars it wrote to `~/.browser-driver-manager/.env`. Earlier commits in this PR removed that auto-load along with the dotenv dependency, which would have silently broken existing BDM users. Restore the auto-load (with a comment explaining its legacy purpose) and the dotenv dep. BDM is no longer recommended anywhere — README, runtime errors, and test guidance all point at `@puppeteer/browsers` — but users who already set BDM up keep working without changes.
Summary
browser-driver-managerin favor ofbrowser-actions/setup-chromeacross every browser job intests.yml. Default Chrome isstable, but theCHROME_VERSIONGitHub repository variable can pin a version when needed.CHROME_TEST_PATHandCHROMEDRIVER_TEST_PATH. They are populated by the action and exported via$GITHUB_ENV.webdriveriotest:exportjob:test/esmTest.mjsnow reads both env vars, so the spawned ChromeDriver and the launched Chrome come from the samesetup-chromeinstall instead of mixing the pinnedchromedriver@^146against whatever Chrome the runner image happens to ship (148 today).Per-suite changes
loadBdmEnvdotenv loader;axe-webdriverio.spec.tsandtest/esmTest.mjsconsumeCHROME_TEST_PATH/CHROMEDRIVER_TEST_PATHdirectly.test-utils.ts.CHROME_TEST_PATH/CHROMEDRIVER_TEST_PATHdirectly fromprocess.env. The legacy BDM~/.browser-driver-manager/.envauto-load is preserved as a silent back-compat shim — see Backwards compatibility below. Existing--chrome-path/--chromedriver-pathCLI flags and thechromedrivernpm fallback are untouched.puppeteerOpts()andtest/esmTest.mjsnow setexecutablePathfromCHROME_TEST_PATHwhen present.chromium.launch()conditionally takesexecutablePathfromCHROME_TEST_PATH.goog:chromeOptions.binaryis set fromCHROME_TEST_PATHwhen present.Workflow changes (
.github/workflows/tests.yml)puppeteer,cli,webdriverjs,webdriverio,playwright,wdio_globals_test) now run:npx playwright install --with-depssinceinstall-dependencies: trueonsetup-chromecovers the OS libs and Playwright launches our binary viaexecutablePath.browser-driver-managerdep removed;package-lock.jsonrefreshed.Public-facing documentation
Brings user-facing install guidance in line with the
@puppeteer/browsersrecommendation that test-assertion messages already use:packages/cli/README.md,packages/webdriverjs/README.md,packages/webdriverio/README.md,packages/webdriverjs/error-handling.md,packages/webdriverio/error-handling.md: BDM install instructions replaced withnpx @puppeteer/browsers install chrome@stable --path ~/.cache/puppeteer-browsers(and the equivalent chromedriver command). The--pathkeeps binaries in a stable shared location instead of polluting whatever directorynpxhappens to be invoked from.--chrome-path/--chromedriver-pathfor the CLI or the equivalent setup-builder calls in the library packages): if only the new ChromeDriver is wired up, it auto-discovers the system Chrome — which almost never matches the new ChromeDriver version — and fails withsession not created.packages/cli/src/bin/index.ts:134-143: theSessionNotCreatedError"ChromeDriver only supports" branch now recommendsnpx @puppeteer/browsers install … --path ~/.cache/puppeteer-browsersand instructs users to pass both--chrome-pathand--chromedriver-path. Same trigger, sameprocess.exit(2); only the help text was updated.Backwards compatibility
Earlier versions of
@axe-core/clidocumentedbrowser-driver-manager(BDM) as the install path and silently auto-loaded the env-var paths BDM wrote to~/.browser-driver-manager/.env. To avoid silently breaking existing users on that flow:@puppeteer/browsers.~/.browser-driver-manager/.envon startup if it exists (withquiet: trueso it's a no-op when the file's absent).dotenvremains a CLI dependency for this shim only.dotenvdoesn't override entries already inprocess.env, so shell-exported values and explicit flags always win.Net effect: any setup that worked on
developkeeps working on this branch. The other shipped packages (@axe-core/{webdriverjs,webdriverio,puppeteer,playwright}) only had test files and docs touched — nosrc/changes, no public API surface change.No QA Required