feat(webdriver-utils): env-var overrides for staging/percy-dev testing#2274
feat(webdriver-utils): env-var overrides for staging/percy-dev testing#2274bhokaremoin wants to merge 1 commit into
Conversation
Replace manual node_modules edits with env vars that default to prod: - PERCY_ENABLE_DEV=true injects projectId:'percy-dev' once at the shared browserstackExecutor chokepoint (covers begin/end + automate/playwright getTiles); omitted entirely when unset, so prod payloads are unchanged. - PERCY_CDP_DOMAIN overrides the Playwright driver CDP host. - PERCY_AUTOMATE_DOMAIN overrides the Automate debug-URL host. Adopts the existing Python percy-appium-app PERCY_ENABLE_DEV convention so one export works across JS + Python. Adds tests for on/off/non-screenshot paths and host overrides. Usage runbook lives in internal docs (not this public repo) to avoid exposing staging cluster hostnames. 🤖 Generated with Claude Opus 4.8 (1M context) via Claude Code + Compound Engineering v2.50.0 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
bhokaremoin
left a comment
There was a problem hiding this comment.
Claude Code Review (automated) — 2 inline finding(s). Full report in the PR comment below. Verdict: Passed.
| } | ||
| const options = this.requestPostOptions(command); | ||
| const baseUrl = `https://cdp.browserstack.com/wd/hub/session/${this.sessionId}/execute`; | ||
| const cdpDomain = process.env.PERCY_CDP_DOMAIN || 'cdp.browserstack.com'; |
There was a problem hiding this comment.
[Low] Optional: allowlist override domains
PERCY_CDP_DOMAIN (and PERCY_AUTOMATE_DOMAIN in the providers) is interpolated verbatim into an outbound HTTPS URL. This is a developer-only, default-off override, and anyone able to set env vars in the run already holds a broader trust boundary — so this is not blocking. If you want cheap hardening, validate the value against an allowlist of trusted suffixes (.browserstack.com, .bsstag.com, .bs-local.com) and throw otherwise.
Suggestion: optional defense-in-depth; safe to ship as-is.
Reviewer: stack:code-reviewer
| // customer payloads are byte-identical to today. Mirrors the Python SDK's | ||
| // PERCY_ENABLE_DEV convention (percy-appium-app app_automate.py). | ||
| if (action === 'percyScreenshot' && process.env.PERCY_ENABLE_DEV === 'true') { | ||
| args = { ...args, projectId: 'percy-dev' }; |
There was a problem hiding this comment.
[Low] Optional: future-proof the spread
{ ...args, projectId: 'percy-dev' } assumes args is a plain object and always overrides projectId. Verified all current percyScreenshot call sites pass plain object literals and none set projectId, so this is correct today — purely a defensive note.
Suggestion (optional):
| args = { ...args, projectId: 'percy-dev' }; | |
| args = (args && typeof args === 'object' && !Array.isArray(args)) ? { ...args, projectId: 'percy-dev' } : { projectId: 'percy-dev' }; |
Reviewer: stack:code-reviewer
Claude Code PR ReviewPR: #2274 • Head: 364dded • Reviewers: stack:code-reviewer SummaryAdds three developer-only, default-off environment-variable overrides to Review Table
FindingsAll findings below are Low severity for this PR's context (an internal, env-gated, default-off developer override). The original reviewer rated [1] Critical and [2]/[3] High; those severities are downgraded here after verifying the real call sites and threat model — documented so the rationale is transparent.
Verdict: PASS — Small, focused, well-tested change that defaults to byte-identical production behavior when the new env vars are unset. Remaining findings are optional Low-severity hardening/nits, not blockers. |
364dded to
ae01e19
Compare
Summary
Replaces the manual
node_modules/@percy/webdriver-utilsedits devs currently make to run Percy against staging (percy-devproject) with environment variables that ship in the package and default to current production behavior.PERCY_ENABLE_DEV=trueprojectId: 'percy-dev'intopercyScreenshotpayloadsprojectIdfield (prod, byte-identical to today)PERCY_CDP_DOMAINcdp.browserstack.comPERCY_AUTOMATE_DOMAINautomate.browserstack.comKey decisions
projectIdsites (percyScreenshotBegin/End, automate + playwrightgetTiles) converge on the sharedgenericProvider.browserstackExecutor(action, args)method.projectIdis injected there once, gated onaction === 'percyScreenshot'(excludesgetSessionDetailsetc.).PERCY_ENABLE_DEVconvention already shipped in the Pythonpercy-appium-appSDK (app_automate.py), so one export works across JS + Python — rather than inventing a divergent new var.PERCY_ENABLE_DEVis unset, JS sends noprojectIdfield (server treats absent ≡percy-prod), so customer payloads are unchanged. A customer can't accidentally misroute a prod build.AA_DOMAINenv-var precedent (automateProvider.js).Usage
The per-environment export blocks / staging hostnames live in internal docs (not this public repo) to avoid exposing staging cluster hostnames. The shipped knobs here default to production.
Testing
percyScreenshotactions, andPERCY_CDP_DOMAIN/PERCY_AUTOMATE_DOMAINhost overrides with prod fallbacks.webdriver-utilssuite: 238/238 pass.yarn lintclean at repo root.Follow-ups (separate repo)
percy-appium-app: add the samePERCY_ENABLE_DEVprojectIdline toexecute_percy_screenshot_begin/_end(currently onlyexecute_percy_screenshotsets it) for full begin/end/screenshot parity.Post-Deploy Monitoring & Validation
percy-devproject.browserstack_executorpayloads and CDP/automate URLs are byte-identical to pre-change (covered by the "byte-identical to prod" unit test).projectIdin its executor payload, or routing to a non-prod host ⇒ revert this commit.🤖 Generated with Claude Opus 4.8 (1M context) via Claude Code