Skip to content

feat(cli): apply the server SDK config override (v8) - #302

Open
kamal-kaur04 wants to merge 6 commits into
v8from
SDK-7954-server-config-override-v8
Open

kamal-kaur04 wants to merge 6 commits into
v8from
SDK-7954-server-config-override-v8

Conversation

@kamal-kaur04

Copy link
Copy Markdown
Collaborator

What is this about?

In a binary-flow (central-auth) build, the SDK Config Server's sdk_config becomes the effective config for any key; parallelsPerPlatform is the primary one. The binary merges it and forwards two keys in the Start/ConnectBinSession config:

  • serverSdkConfig: the normalised server config;
  • serverSdkConfigKeys: the keys the server actually overrode.

This PR is the v8 port of #301 (v9): the service applies exactly those keys and maps ppp onto WebdriverIO's concurrency.

Isolation: the new code runs only when the binary sends an object serverSdkConfig and an array serverSdkConfigKeys. With no override, on the fallback path, or with an older binary, behaviour is identical to main.

What it does:

  • Options merge (src/cli/index.ts applyServerConfig, called right after setConfig in loadModules, in the launcher and in every worker; v8 has a single call site):
    • Only the listed keys are deep-merged into the service options: objects recursive, arrays element-wise, null replaces.
    • The renames getBinConfig makes are mapped back: browserStackLocalOptions → opts, and testContextOptions → setSessionName/setSessionStatus/sessionName*.
    • Merge logic: CLIUtils.applyServerSdkConfig.
  • Runner concurrency (src/launcher.ts _applyServerConfigToRunner, right after the binary starts in onPrepare, CLI flow only):
    • A listed parallelsPerPlatform sets each capability's maxInstances (the key the v8 runner reads first) and raises config.maxInstances to at least capabilities × ppp. The runner builds its schedule after onPrepare, so this takes effect.
    • A server platforms[i] is layered onto capability i, with flattened keys put back under bstack:options.
    • A listed accessibility re-derives the launcher's accessibility flag.
  • Precedence: server > CLI > env > wdio.conf. A server ppp beats a user-written maxInstances.

Testing

  • Unit: 1167 passed vs 1146 on origin/v8; build and tsc pass. (v8 has no lint config; v9's eslint config run over the touched files is clean.)

  • E2E: this service × binary https://github.com/browserstack/browserstack-binary/pull/1967, mock config server, wdio 8.46 mocha, 12 specs × Win11 chrome + edge:

    Row Specs Peak concurrent Applied keys
    ppp-up (local 1 → server 3) 24/24 6 (caps maxInstances [3,3], config.maxInstances 6) parallelsPerPlatform
    ppp-down (local 3 → server 1) 24/24 2 (caps maxInstances [1,1]) parallelsPerPlatform
    no override, head vs origin/v8 24/24 each 4 / 4 none; config sent and runner caps after onPrepare identical
    fetch-fail (HTTP 500) 24/24 4 none
    echo-only 24/24 4 none
    multi-key (ppp 3 + skipSessionName + platforms[0] latest-1) 24/24 6 parallelsPerPlatform, platforms, testContextOptions (chrome ran latest-1, 0 sessions named)
    server sessionNameFormat: "x" + ppp 3 24/24 6 all sessions named and marked, no TypeError
  • v8 differences from v9:

    • ppp goes to each capability's maxInstances (not wdio:maxInstances).
    • v8's getBinConfig leaves a key out of platforms[i] when the same key is also set at the top level, so the server must spell such a key the way the capability does.
    • Only the first half of the v9 sessionNameFormat fix is needed: v8 reads it only from the service options.

Fixes after review / key matrix

  • applyServerPlatform: a server platforms[i] key that the capability holds both at the top level and in bstack:options is now written to bstack:options (getBinConfig flattens that copy last, so it is the one sent).
  • sessionNameFormat: a server value (always a string) is no longer mapped onto the option, which the automate module calls as a function. Previously every session failed naming/marking.

Key matrix (run on v9 #301, same logic on v8 — one combined override build + early-keys build + no-override control; mock config server, v9 service × binary #1967)

Key (local → server) Verdict Notes
parallelsPerPlatform ✅ runner maxInstances/per-capability set from the server value; peak follows it
browserstackLocal (both directions) + opts (localIdentifier, forceLocal) ✅ local:true with the server id, tunnel started --force-local, none left afterwards
accessibility false → true ✅ chrome sessions scanned (edge is not A11y-supported)
testObservability (both directions) ✅ O11y build with all tests / no O11y build
testContextOptions skipSessionName / skipSessionStatus (both directions) ✅
buildIdentifier ✅
networkLogs, consoleLogs, seleniumVersion, platforms browserVersion / os / osVersion ✅ reach the hub caps
userName / accessKey / hubUrl ✅ ignored binary-internal keys, never merged
buildName / projectName ⚠️ reach Automate; O11y/A11y builds keep the local identity (created at build start, before the merge)
accessibilityOptions.wcagVersion ⚠️ caps carry the server value; the A11y build keeps the local one (created at build start)
debug ⚠️ a per-capability value the user set beats the server's top-level value; target platforms[i] for those
logLevel ⚠️ changes the binary's log only; the service logger level is fixed at construction
buildTag (top level) ⚠️ merged, but nothing after the merge consumes it
accessibility true → false ⚠️ no scans, but caps keep accessibility:true; the no-override decline control shows the same (pre-existing)
testObservabilityOptions.buildTag ➖ WDIO-only keys inside it are dropped by the binary's yml-style validation
testOrchestrationOptions, testManagementOptions, framework ➖ consumed before the merge (build start / before bootstrap)
appended platform ➖ inert: no worker for an entry beyond the wdio.conf capabilities
null on a top-level key ➖ not listed, nothing changes
turboScale 💥 treated like any key: session naming/status move to the TurboScale API, so sessions aren't named/marked. Don't override it from the server
null on a capability key 💥 null replaces, and the hub rejects that platform's sessions. Rails must not send null for capability keys
percy, app / skipAppOverride not run Percy needs a project/token; App Automate needs an Appium sample. Both are decided at build start

Pre-existing (reproduce without an override, not changed here): stopBuild returns 401 when O11y and A11y are both off; a local sessionNameFormat function never reaches the CLI-flow module.

Limitations (documented)

  • Server platforms entries beyond the wdio.conf capabilities are inert.
  • Some flags never take the server value:
    • flags the worker service captures in its constructor (observability, accessibility, turboScale);
    • options read before the binary starts (e.g. the test-orchestration spec expansion and credentials).
  • Jasmine and multiremote don't use the CLI flow, so they get no override.
  • testContextOptions is listed as overridden on every override build (the server echo differs from the synthesised local value); applying it is a no-op.

Sibling PRs (SDK-7954)

Related Jira task/s

Release (mandatory for every PR — required for the ready-for-review label)

Version bump: (required — tick exactly one)

  • minor (backwards-compatible feature)
  • patch (bug fix or other small change)

Release notes type: (optional)

  • New Feature
  • Bug Fix
  • Other Improvement

Release notes (customer-facing): (optional but encouraged)

  • Server-side configuration overrides from BrowserStack now take effect for WebdriverIO v8 builds, for example parallelsPerPlatform (parallel sessions per capability). Your wdio.conf remains the fallback.

Release notes (internal): (required — engineer-facing; what actually changed / why)

  • BrowserstackCLI.applyServerConfig applies exactly the binary-listed overridden keys (serverSdkConfigKeys) of serverSdkConfig to the service options after setConfig, in the launcher and workers. The binary's renamed keys are mapped back to the service spellings.
  • The launcher maps a listed parallelsPerPlatform onto each capability's maxInstances and raises config.maxInstances, and layers server platforms[i] onto capability i.
  • Runs only when the binary sends an override; otherwise behaviour is identical to main.

Checklist

  • Ready to review
  • Has it been tested locally?

PR Validations

Run Tests: Comment RUN_TESTS to trigger sanity tests.

🤖 Generated with Claude Code

kamal-kaur04 and others added 2 commits October 22, 2026 19:16
On the CLI flow the binary forwards the server's sdk_config as serverSdkConfig
with the list of overridden keys. The service deep-merges exactly those keys
into its options in the main process and every worker, mapping the keys
getBinConfig renames back to their option names. In onPrepare a server
parallelsPerPlatform becomes each capability's maxInstances, with
maxInstances raised to fit, and server platforms layer onto the capability at
the same index. Without the key list nothing changes.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The option is a function; a server value can only be a string, which the
automate module then called, so no session was named or marked.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Central YAML (base), Organization UI (inherited), Workspace UI (inherited); Enforced overrides: Organization
  • Review profile: ASSERTIVE
  • Plan: Enterprise
  • Run ID: 8cfc2890-eb82-4e1d-8d73-73dcf56b4929

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@kamal-kaur04

kamal-kaur04 commented Oct 22, 2026 •

Copy link
Copy Markdown
Collaborator Author

⚠️ Needs human review

File Status
cli/test/modules/testhub/index.test.js ✅ All Clear
cli/test/modules/testhub/lib/server-config.test.js ✅ All Clear
packages/@browserstack/testhub/lib/server-config.js ✅ All Clear
wdio-browserstack-service/.changeset/pr-302.md ✅ All Clear
wdio-browserstack-service/packages/browserstack-service/src/cli/cliUtils.ts issue
wdio-browserstack-service/packages/browserstack-service/src/cli/index.ts ✅ All Clear
wdio-browserstack-service/packages/browserstack-service/src/constants.ts ✅ All Clear
wdio-browserstack-service/packages/browserstack-service/src/launcher.ts ✅ All Clear
wdio-browserstack-service/packages/browserstack-service/src/util.ts ✅ All Clear
wdio-browserstack-service/packages/browserstack-service/tests/cli/cliUtils.test.ts ✅ All Clear
wdio-browserstack-service/packages/browserstack-service/tests/cli/index.test.ts ✅ All Clear
wdio-browserstack-service/packages/browserstack-service/tests/launcher.test.ts ✅ All Clear

Change map (generated deterministically from the diff)

graph LR
  subgraph nbinary["binary"]
    ncli_test_modules_testhub_lib_server_config_test_js["server-config.test.js<br/>~43 lines"]
    npackages__browserstack_testhub_lib_server_config_js["server-config.js<br/>~43 lines"]
    ncli_test_modules_testhub_index_test_js["index.test.js<br/>~26 lines"]
  end
  subgraph nwdio_service["wdio-service"]
    nwdio_browserstack_service_packages_browserstack_service_src_cli_cliUtils_ts["⚠ cliUtils.ts<br/>~133 lines"]
    nwdio_browserstack_service_packages_browserstack_service_tests_cli_cliUtils_test_ts["⚠ cliUtils.test.ts<br/>~133 lines"]
    nwdio_browserstack_service_packages_browserstack_service_src_launcher_ts["⚠ launcher.ts<br/>~56 lines"]
    nwdio_browserstack_service_packages_browserstack_service_tests_launcher_test_ts["⚠ launcher.test.ts<br/>~56 lines"]
    nwdio_browserstack_service_packages_browserstack_service_src_cli_index_ts["index.ts<br/>~47 lines"]
    nwdio_browserstack_service_packages_browserstack_service_tests_cli_index_test_ts["index.test.ts<br/>~47 lines"]
    nwdio_browserstack_service__changeset_pr_302_md["pr-302.md<br/>~5 lines"]
    nwdio_browserstack_service_packages_browserstack_service_src_util_ts["util.ts<br/>~4 lines"]
    nwdio_browserstack_service_packages_browserstack_service_src_constants_ts["constants.ts<br/>~2 lines"]
  end
  nsvc_Observability_TRA(["Observability/TRA"])
  nsvc_collector_observability_browserstack_com(["collector-observability.browserstack.com"])
  ncli_test_modules_testhub_lib_server_config_test_js --> nsvc_Observability_TRA
  ncli_test_modules_testhub_lib_server_config_test_js --> nsvc_collector_observability_browserstack_com
  npackages__browserstack_testhub_lib_server_config_js --> nsvc_Observability_TRA
  npackages__browserstack_testhub_lib_server_config_js --> nsvc_collector_observability_browserstack_com
Loading

↻ This verdict comment is the review anchor — it's updated in place on each run (the gate posts its status separately).

— SDK PR Review Agent

@kamal-kaur04
kamal-kaur04 marked this pull request as ready for review October 22, 2026 15:29
@kamal-kaur04
kamal-kaur04 requested a review from a team as a code owner October 22, 2026 15:29
@kamal-kaur04
kamal-kaur04 removed the request for review from a team October 22, 2026 15:29
@github-actions

Copy link
Copy Markdown
Contributor

🟢 SDK PR Review gate is green — the SDK PR Review Agent has run on the current head commit (verdict: success).

This gate confirms a review ran on the latest commit. The verdict itself is advisory — read the findings and use your judgement; it does not block merge. A native GitHub reviewer approval is still separately required by branch protection before this PR can merge.

1 similar comment
@github-actions

Copy link
Copy Markdown
Contributor

🟢 SDK PR Review gate is green — the SDK PR Review Agent has run on the current head commit (verdict: success).

This gate confirms a review ran on the latest commit. The verdict itself is advisory — read the findings and use your judgement; it does not block merge. A native GitHub reviewer approval is still separately required by branch protection before this PR can merge.

@kamal-kaur04

Copy link
Copy Markdown
Collaborator Author

RUN_TESTS

@minionhelperappqa

Copy link
Copy Markdown

[SDK Wdio Test] TRA build state: failed | Stability 96% — verdict: success. Passed: 51, Failed: 2, Aggregate: 53. TRA: https://observability.browserstack.com/builds/azom2gxpig0ovgfynctygobpml32dqul81jvnyef

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

🔴 SDK PR Review gate is red. Pending:

  • The SDK PR Review Agent has not been run on the current head commit yet — run the SDK PR Review Agent (its verdict is advisory; this gate only requires that it ran on the latest commit).

It turns green once the SDK PR Review Agent has run on the current head commit (any verdict — the gate only requires that the review ran). A native reviewer approval is separately required by branch protection before merge.

@kamal-kaur04

Copy link
Copy Markdown
Collaborator Author

RUN_TESTS

@github-actions

Copy link
Copy Markdown
Contributor

🟢 SDK PR Review gate is green — the SDK PR Review Agent has run on the current head commit (verdict: failure).

This gate confirms a review ran on the latest commit. The verdict itself is advisory — read the findings and use your judgement; it does not block merge. A native GitHub reviewer approval is still separately required by branch protection before this PR can merge.

…per key

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@kamal-kaur04

Copy link
Copy Markdown
Collaborator Author

On the review-gate findings at 8f8fba8:

  • 🔴 bstack:options captured once in applyServerPlatform: fixed in 41dc016. capability['bstack:options'] is re-read for every key, and the server platform entry is cloned first. Two tests cover it ("keeps routing into bstack:options after the entry merges a bstack:options key", "does not share objects with the server platform entry"). Suite 1170/0. The same fix is on feat(cli): apply the server SDK config override #301 (869e19e).
  • Server ppp a no-op when a capability sets wdio:maxInstances: not on v8.
    • The v8 runner builds its schedule from capabilities.maxInstances first (@wdio/cli 8.46 launcher.js:178), which is the key _applyServerConfigToRunner writes. It also raises config.maxInstances to at least capabilities × ppp.
    • E2E: ppp-up gave caps maxInstances [3,3], peak 6; ppp-down gave [1,1], peak 2 (both 24/24).

@github-actions

Copy link
Copy Markdown
Contributor

🔴 SDK PR Review gate is red. Pending:

  • The SDK PR Review Agent has not been run on the current head commit yet — run the SDK PR Review Agent (its verdict is advisory; this gate only requires that it ran on the latest commit).

It turns green once the SDK PR Review Agent has run on the current head commit (any verdict — the gate only requires that the review ran). A native reviewer approval is separately required by branch protection before merge.

@minionhelperappqa

Copy link
Copy Markdown

[SDK Wdio Test] TRA build state: failed | Stability 96% — verdict: success. Passed: 51, Failed: 2, Aggregate: 53. TRA: https://observability.browserstack.com/builds/0c6rmx0741vlttjrlctmpoqaomzsajjlvtko7gnq

@github-actions

Copy link
Copy Markdown
Contributor

🟢 SDK PR Review gate is green — the SDK PR Review Agent has run on the current head commit (verdict: failure).

This gate confirms a review ran on the latest commit. The verdict itself is advisory — read the findings and use your judgement; it does not block merge. A native GitHub reviewer approval is still separately required by branch protection before this PR can merge.

…to it

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

🔴 SDK PR Review gate is red. Pending:

  • The SDK PR Review Agent has not been run on the current head commit yet — run the SDK PR Review Agent (its verdict is advisory; this gate only requires that it ran on the latest commit).

It turns green once the SDK PR Review Agent has run on the current head commit (any verdict — the gate only requires that the review ran). A native reviewer approval is separately required by branch protection before merge.

@github-actions

Copy link
Copy Markdown
Contributor

🟢 SDK PR Review gate is green — the SDK PR Review Agent has run on the current head commit (verdict: pending).

This gate confirms a review ran on the latest commit. The verdict itself is advisory — read the findings and use your judgement; it does not block merge. A native GitHub reviewer approval is still separately required by branch protection before this PR can merge.

@kamal-kaur04

Copy link
Copy Markdown
Collaborator Author

On the remaining review-gate warning at 4d19751: a new key without : (e.g. platformName) is routed into bstack:options by CLIUtils.applyServerPlatform. This is equivalent placement for the CLI flow, so no change.

  • Why the placement doesn't change what the hub gets. The hub never receives the runner capability as-is: in the CLI flow the binary builds each driver's caps from its merged platforms[i]. That entry is the service's own flattened view:
    • getBinConfig spreads bstack:options into the platform entry next to the top-level keys;
    • the binary merges the server's platforms[i] against that flattened entry;
    • so a key lands in the same flattened entry whether the service writes it at the capability's top level or under bstack:options.
  • Why new keys go to bstack:options. Only a new key that the capability lacks is routed there, and only when the capability already has bstack:options and the key has no vendor prefix. That mirrors how getBinConfig flattened the user's own bstack:options keys (os, osVersion, deviceName, buildName, …), which are the platform keys the server is expected to send.
  • Evidence (E2E):
    • v9 combined override build: server platforms[1] os: OS X, osVersion: Sonoma (new keys for that capability) → edge ran on OS X Sonoma.
    • multi-key rows on both lines: server platforms[0].browserVersion: latest-1 → chrome ran latest-1, 24/24.
  • Same code on feat(cli): apply the server SDK config override #301, where the final gate pass is ✅ with no findings.

This is an ungrounded item. A non-author reviewer comment confirming the placement clears it on the gate.

@github-actions

Copy link
Copy Markdown
Contributor

🟢 SDK PR Review gate is green — the SDK PR Review Agent has run on the current head commit (verdict: pending).

This gate confirms a review ran on the latest commit. The verdict itself is advisory — read the findings and use your judgement; it does not block merge. A native GitHub reviewer approval is still separately required by branch protection before this PR can merge.

1 similar comment
@github-actions

Copy link
Copy Markdown
Contributor

🟢 SDK PR Review gate is green — the SDK PR Review Agent has run on the current head commit (verdict: pending).

This gate confirms a review ran on the latest commit. The verdict itself is advisory — read the findings and use your judgement; it does not block merge. A native GitHub reviewer approval is still separately required by branch protection before this PR can merge.

@kamal-kaur04

Copy link
Copy Markdown
Collaborator Author

RUN_TESTS

@07souravkunda 07souravkunda left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approving.

@minionhelperappqa

Copy link
Copy Markdown

[SDK Wdio Test] TRA build state: failed | Stability 96% — verdict: success. Passed: 51, Failed: 2, Aggregate: 53. TRA: https://observability.browserstack.com/builds/eru2wpa6s0cco4boktzwhbpitea8tdrrp8em3zfl

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants