Skip to content

Merge fix/SDK-7138-wdio-upload-attachment - #260

Merged
bsautomation merged 11 commits into
sdk_v9_pre_prodfrom
fix/SDK-7138-wdio-upload-attachment
Sep 30, 2026
Merged

bsautomation merged 11 commits into
sdk_v9_pre_prodfrom
fix/SDK-7138-wdio-upload-attachment

Conversation

@bsautomation

Copy link
Copy Markdown
Contributor

Merge into sdk_v9_pre_prod :by automationbs

shivamku-BS and others added 11 commits August 17, 2026 18:32
…a (SDK-7138)

WebdriverIO had no way to attach a file to a test, hook or build in Test
Reporting. Every sibling SDK ships one (BrowserStack.uploadAttachment in Java,
driver.upload_attachment in Python, page.uploadAttachment in Node), and the
binary's webdriverio language module already handles TEST_ATTACHMENT LogCreated
entries end to end -- only the service-side entry point was missing, so
driver.uploadMedia(...) threw "is not a function" and killed the customer's
hook.

UploadAttachmentModule registers the command the same way CustomTagsModule
registers setCustomTags: on AutomationFrameworkState.CREATE / HookState.POST,
instantiated from loadModules() when the testhub pipeline is up. It resolves the
level (Test / Hook / Build) plus the uuid it hangs off, and emits one
TEST_ATTACHMENT LogCreated entry. The file is not copied -- the binary streams
it from filePath while draining its upload queue, which can outlive this
process.

grpcClient.logCreatedEvent was dropping fileName / fileSize / filePath on the
floor even though the proto and generated types already carry them; without
that the binary has nothing to stream.

Also hardens CLI bootstrap against a degenerate bin-session response, observed
on parallel workers alongside this bug: an empty config made JSON.parse throw in
setConfig, and updateURLSForGRR then dereferenced the undefined config and threw
out of loadModules. That aborted the entire bootstrap, so no module loaded --
custom tags, observability and the rest silently went away and the build
recorded no test results. Both sites now degrade to defaults instead.

Verified against the SDK-7138 reproduction (wdio_mocha upload-media/custom-tags
spec, @wdio/browserstack-service built from main): uploadMedia and
uploadAttachment both register, before-all/after-all hooks and the first test
run clean where they previously died in "before all".
…138)

uploadAttachment runs inside the customer's test body and awaited the binary's
LogCreated ack with no bound, so a wedged binary would stall the calling test
until the framework's own timeout fired. Race the ack against a 10s budget: the
event is already on the wire when the timer wins, so nothing is dropped.

Also re-arm the logCreatedEvent mock per test — afterEach's restoreAllMocks
drops the implementation, so every test after the first was getting a
non-promise back from the ack.
…er's stack (SDK-7138)

uploadAttachment is called from the customer's test body and the next statement is
usually a browser command that the accessibility module wraps with a pre-command scan.
Awaiting the binary round-trip on that stack stalled the following executeAsync scan
under load: chrome sessions issued the scan and then no further WebDriver request,
until the framework timeout fired and the hub reaped the session (reproduced 4/4 in
BStackAutomation at logLevel warn; absent 2/2 with the uploadMedia calls removed).

The ack carries nothing the caller can act on — the binary streams the file from
filePath while draining its own upload queue — so the event is written and its ack
observed off-stack, still bounded so a wedged binary cannot leak a pending timer.
- Drop the hand-written duplicate changeset; keep pr-193.md (the repo's
  generated file) with the complete bullet text.
- updateURLSForGRR: debug-log when the bin-session config has no apis and
  which endpoints keep their defaults, instead of falling back silently.
- uploadAttachmentModule tests: cover a path that exists but is not a
  regular file, and assert the ack-timeout warning actually fires.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…f ack timer

Review follow-ups:
- Register a no-op uploadAttachment/uploadMedia on every browser in
  service.before(); UploadAttachmentModule replaces it when the binary is up.
  Without it the call still threw "uploadMedia is not a function" whenever Test
  Reporting was inactive (classic path, no testhub, CLI down) - the SDK-7138
  symptom. Matches Python/Java, which no-op instead of throwing.
- Snapshot the file into <writable>/UploadedAttachments-<platformIndex>/<level>/
  (counter suffix on collisions) and send the copy's path, so a caller that
  overwrites or deletes the file right after the fire-and-forget call no longer
  attaches the wrong content or nothing. The launcher removes those folders in
  onComplete after the CLI/build stop, as the Python SDK does post-run.
- unref() the ack-timeout timer so a wedged binary cannot hold the worker open.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Snapshots were keyed only on platformIndex, so parallel workers on the
same capability shared UploadedAttachments-<n>/<level>/. The name pick
(existsSync, then copyFileSync) wasn't atomic, so two workers attaching
a same-named file could overwrite each other. The Python and Java SDKs
also use UploadedAttachments-<n>/ in the same directory, and each
SDK's cleanup could delete the others' copies.

Snapshots now go to
UploadedAttachments-wdio-<bin session id>/<worker pid>/<level>/. The
copy uses COPYFILE_EXCL and moves to the next name on EEXIST, and the
launcher removes only this run's folder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@bsautomation
bsautomation requested a review from a team as a code owner September 30, 2026 13:19
@bsautomation
bsautomation requested review from rounak610 and vivianludrick and removed request for a team September 30, 2026 13:19
@coderabbitai

coderabbitai Bot commented Sep 30, 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

Configuration used: Central YAML (base), Organization UI (inherited), Workspace UI (inherited)

Review profile: ASSERTIVE

Plan: Advanced

Run ID: f32b98b6-f735-4ae4-b38d-ef8d939ddd16

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

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

@bsautomation
bsautomation merged commit c844aac into sdk_v9_pre_prod Sep 30, 2026
21 of 24 checks passed
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