Skip to content

ci: replace browser-driver-manager with browser-actions/setup-chrome#1345

Draft
Garbee wants to merge 10 commits into
developfrom
garbee/chore/standardize-chrome-env-vars
Draft

ci: replace browser-driver-manager with browser-actions/setup-chrome#1345
Garbee wants to merge 10 commits into
developfrom
garbee/chore/standardize-chrome-env-vars

Conversation

@Garbee

@Garbee Garbee commented May 19, 2026

Copy link
Copy Markdown
Member

Summary

  • Drops browser-driver-manager in favor of browser-actions/setup-chrome across every browser job in tests.yml. Default Chrome is stable, but the CHROME_VERSION GitHub repository variable can pin a version when needed.
  • Standardizes Chrome / ChromeDriver discovery in every suite around two env vars: CHROME_TEST_PATH and CHROMEDRIVER_TEST_PATH. They are populated by the action and exported via $GITHUB_ENV.
  • Fixes the failing webdriverio test:export job: test/esmTest.mjs now reads both env vars, so the spawned ChromeDriver and the launched Chrome come from the same setup-chrome install instead of mixing the pinned chromedriver@^146 against whatever Chrome the runner image happens to ship (148 today).

Per-suite changes

  • webdriverio: removes the loadBdmEnv dotenv loader; axe-webdriverio.spec.ts and test/esmTest.mjs consume CHROME_TEST_PATH / CHROMEDRIVER_TEST_PATH directly.
  • webdriverjs: drops the BDM cache-dir dotenv loader from test-utils.ts.
  • cli: now reads CHROME_TEST_PATH / CHROMEDRIVER_TEST_PATH directly from process.env. The legacy BDM ~/.browser-driver-manager/.env auto-load is preserved as a silent back-compat shim — see Backwards compatibility below. Existing --chrome-path / --chromedriver-path CLI flags and the chromedriver npm fallback are untouched.
  • puppeteer: puppeteerOpts() and test/esmTest.mjs now set executablePath from CHROME_TEST_PATH when present.
  • playwright: chromium.launch() conditionally takes executablePath from CHROME_TEST_PATH.
  • test/wdio: goog:chromeOptions.binary is set from CHROME_TEST_PATH when present.

Workflow changes (.github/workflows/tests.yml)

  • Six jobs (puppeteer, cli, webdriverjs, webdriverio, playwright, wdio_globals_test) now run:
    - uses: browser-actions/setup-chrome@2e1d749697dd1612b833dba4a722266286fbefcd # v2.1.2
      id: setup-chrome
      with:
        chrome-version: ${{ vars.CHROME_VERSION || 'stable' }}
        install-chromedriver: true
        install-dependencies: true
    - run: |
        echo "CHROME_TEST_PATH=${{ steps.setup-chrome.outputs.chrome-path }}" >> "$GITHUB_ENV"
        echo "CHROMEDRIVER_TEST_PATH=${{ steps.setup-chrome.outputs.chromedriver-path }}" >> "$GITHUB_ENV"
  • The Playwright job drops npx playwright install --with-deps since install-dependencies: true on setup-chrome covers the OS libs and Playwright launches our binary via executablePath.
  • Root browser-driver-manager dep removed; package-lock.json refreshed.

Public-facing documentation

Brings user-facing install guidance in line with the @puppeteer/browsers recommendation 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 with npx @puppeteer/browsers install chrome@stable --path ~/.cache/puppeteer-browsers (and the equivalent chromedriver command). The --path keeps binaries in a stable shared location instead of polluting whatever directory npx happens to be invoked from.
  • Docs now also explain why callers must supply both the Chrome and ChromeDriver paths (either via --chrome-path/--chromedriver-path for 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 with session not created.
  • packages/cli/src/bin/index.ts:134-143: the SessionNotCreatedError "ChromeDriver only supports" branch now recommends npx @puppeteer/browsers install … --path ~/.cache/puppeteer-browsers and instructs users to pass both --chrome-path and --chromedriver-path. Same trigger, same process.exit(2); only the help text was updated.

Backwards compatibility

Earlier versions of @axe-core/cli documented browser-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:

  • BDM is no longer mentioned anywhere we surface — READMEs, runtime errors, error-handling docs, and test-setup assertions all point at @puppeteer/browsers.
  • The CLI still auto-loads ~/.browser-driver-manager/.env on startup if it exists (with quiet: true so it's a no-op when the file's absent). dotenv remains a CLI dependency for this shim only. dotenv doesn't override entries already in process.env, so shell-exported values and explicit flags always win.

Net effect: any setup that worked on develop keeps working on this branch. The other shipped packages (@axe-core/{webdriverjs,webdriverio,puppeteer,playwright}) only had test files and docs touched — no src/ changes, no public API surface change.

No QA Required

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.
@Garbee Garbee self-assigned this May 19, 2026
Garbee added 3 commits May 19, 2026 18:17
`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.
Comment thread .github/workflows/tests.yml Outdated
- 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

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

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.

Comment thread .github/workflows/tests.yml Outdated
cache: 'npm'
- run: npm ci
- run: npx playwright install --with-deps
- uses: browser-actions/setup-chrome@v1

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

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.

Comment thread .github/workflows/tests.yml Outdated
node-version: ${{ matrix.node }}
cache: 'npm'
- run: npm ci
- uses: browser-actions/setup-chrome@v1

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

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 =

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

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.

Comment thread packages/webdriverio/test/esmTest.mjs Outdated
'goog:chromeOptions': {
args: ['--headless', '--no-sandbox']
args: ['--headless', '--no-sandbox'],
...(chromeBinary && { binary: chromeBinary })

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

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) {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

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 && {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

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.

@Garbee

Garbee commented May 19, 2026

Copy link
Copy Markdown
Member Author

Env-var contract for reviewers

Every browser test suite reads two env vars now:

  • CHROME_TEST_PATH → passed to the launcher as the Chrome binary (goog:chromeOptions.binary for selenium/webdriverio, executablePath for puppeteer/playwright).
  • CHROMEDRIVER_TEST_PATH → used by the suites that spawn chromedriver standalone (webdriverio export harness, webdriverjs, cli).

Both are populated by browser-actions/setup-chrome in CI and exported via \$GITHUB_ENV. Both are optional locally — unset means the library auto-discovers. Override the CI Chrome version by setting the CHROME_VERSION repository variable.

The original failure (PR #1344) was a Chrome/chromedriver version mismatch in packages/webdriverio/test/esmTest.mjs; the actual one-line fix is in that file (now reads CHROMEDRIVER_TEST_PATH first). Everything else in the diff is harmonizing the other suites + workflow so this doesn't recur the next time the runner image rolls.

Comment thread test/wdio/wdio.conf.ts
Comment on lines +69 to +70
'--no-sandbox',
'--disable-dev-shm-usage'

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

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.

@Garbee Garbee marked this pull request as ready for review May 20, 2026 13:04
@Garbee Garbee requested a review from a team as a code owner May 20, 2026 13:04
Copilot AI review requested due to automatic review settings May 20, 2026 13:04

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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-chrome and export CHROME_TEST_PATH / CHROMEDRIVER_TEST_PATH for 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.

Comment thread test/wdio/wdio.conf.ts Outdated
Comment thread packages/playwright/test/axe-playwright.spec.ts Outdated
Comment thread packages/webdriverio/test/esmTest.mjs Outdated
Comment thread .github/workflows/tests.yml

@chutchins25 chutchins25 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude suggested several places that may be public facing and may need to be updated with install guidance.

  • packages/cli/README.md:17
  • packages/webdriverjs/README.md:15
  • packages/webdriverio/README.md:23
  • packages/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?

@Garbee Garbee marked this pull request as draft May 20, 2026 14:55
@Garbee

Garbee commented May 20, 2026

Copy link
Copy Markdown
Member Author

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.

@Garbee Garbee marked this pull request as ready for review May 20, 2026 15:35

@chutchins25 chutchins25 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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?

@Garbee

Garbee commented May 20, 2026

Copy link
Copy Markdown
Member Author

Looking into the readme thing. But ~/.cache/puppeteer is incorrect. When you use this installer like this, it installs to the path you give it (or present working directory by default). So, that location isn't known in advance.

Let me try to get the messaging updated to be clear about that.

Garbee added 2 commits May 20, 2026 12:16
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.

@chutchins25 chutchins25 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Looks good to me now!

@Garbee Garbee marked this pull request as draft June 1, 2026 21:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants