fix(observability): inject TRA support-file listener synchronously (SDK-7121) - #1160
Open
osho-20 wants to merge 2 commits into
Open
fix(observability): inject TRA support-file listener synchronously (SDK-7121)#1160osho-20 wants to merge 2 commits into
osho-20 wants to merge 2 commits into
Conversation
…DK-7121)
setEventListeners deferred the support-file write to an async glob callback
while runs.js proceeded synchronously to md5 hashing and zip archiving. The
injection raced the archive: a lost race shipped an un-instrumented suite, and
md5 caching ("Skipping zip upload...") made the bad zip sticky, so the new
Automate dashboard (TRA) received zero test events while the old dashboard
(independent of the injected plugin) kept working. This is why the symptom was
environment-specific — a slower CI pipeline loses the race.
Switch setEventListeners (and the identical race in the accessibility
setAccessibilityEventListeners glob branch) to glob.sync so the writes complete
before the caller reads the files. Adds a regression test asserting the
observability require is present synchronously after the call returns.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 task
Collaborator
Author
↻ 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 |
Address SDK PR Review coverage-gap finding on the regression test. The fix touched two files (setEventListeners and the accessibility setAccessibilityEventListeners glob branch) but the test only covered the observability path. Add: - accessibility setAccessibilityEventListeners synchronous-injection test (exercises the glob.sync pattern branch), - observability idempotency test (a second call does not double-inject). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
pri-gadhiya
approved these changes
Jul 30, 2026
pri-gadhiya
left a comment
Collaborator
There was a problem hiding this comment.
Verdict: Approve. Root cause is correctly diagnosed, the fix is minimal and correct, and it ships with a genuine regression guard. I verified the load-bearing claims against the source rather than the description.
Confirmed
- The race is real.
runs.js(216/227/230) calls the void-returning listeners, then flows straight intocheckUploadedMd5→archiver.archive(263, 276) with noawaitin between. The old asyncglob(...cb)fired after the archive had already read the file. glob.syncis the right API —globis pinned^7.2.0;glob.sync(pattern, opts)is a valid v7 signature.- Only
runs.jsconsumes these functions — nothing depended on the async behavior. - a11y fix is correctly scoped —
setAccessibilityEventListeners' non-magic branch was already synchronous; only the magic-pattern branch was async, and that's exactly what's fixed. No residual race. - No other async-glob-then-archive races remain — the only other callback-
globusages are the archive stream itself and the md5 walk. - Error-handling parity holds —
glob.syncthrows instead ofif(err) return, but the outertry/catchcatches anddebug-logs it: equivalent outcome. - Test wiring is sound — both helpers resolve
getSupportFilesfrom the samebin/helpers/helpermodule, so the single sinon stub covers both paths; asserted require strings match the injectors exactly.
Worth adding (positive)
- Self-healing cache.
checkSpecsMd5hashes the whole cypress folder, which includes the support file. Post-fix the file is always instrumented → different md5 → the stale un-instrumented zip is no longer a cache hit → fresh upload. Affected customers recover on their first run with the fixed CLI, no manual cache bust. Worth noting in the release note.
Non-blocking nits
- Idempotency is asserted only for the o11y path; the a11y injector has the same
!includes(...)guard, so adding a symmetric assertion would be nice-to-have. test/unit/bin/testObservability/setEventListeners.jsalso houses the a11y test — fine as an SDK-7121 bundle, but the path implies o11y-only.- Please confirm CI is green before merge (I couldn't run the suite locally). The
patchbump is correct.
pri-gadhiya
reviewed
Jul 30, 2026
| if(err) { | ||
| logger.debug('EXCEPTION IN BUILD START EVENT : Unable to parse cypress support files'); | ||
| return; | ||
| } |
Collaborator
There was a problem hiding this comment.
Since we are removing this, how do we know if exception caused issue in build start?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The new Automate dashboard (TRA / Test Observability) received no test events for Cypress runs on a customer's DEV pipeline, while the old Automate dashboard worked and the same suite/CLI/packages worked on another environment. Ref: SDK-7121.
Root cause
setEventListeners(bin/testObservability/helper/helper.js) injects the observability plugin into the user's Cypress support file:It did this inside an async
glob(pattern, {}, cb)callback and returned immediately without awaiting it. Inbin/commands/runs.js, the caller proceeds synchronously to md5 hashing (checkUploadedMd5) and zip archiving (archiver.archive) right after the call. So the injection raced the archive:Md5 caching makes a lost race sticky: once a non-instrumented zip is cached under the original-content md5, every subsequent run logs
"Skipping zip upload since BrowserStack already has your test suite..."and reuses the bad zip. The old Automate dashboard is unaffected because it does not depend on the injected plugin — exactly the reported asymmetry.Reproduction
Calling
setEventListenersand reading the support file synchronously afterwards (as md5/archive do):Fix
setEventListeners→ useglob.syncso the support-file writes complete before the function returns.setAccessibilityEventListeners' glob-pattern branch (bin/accessibility-automation/helper.js).Testing
test/unit/bin/testObservability/setEventListeners.js— asserts the observability require is present synchronously after the call. Fails on unfixed code, passes with the fix.accessibility-automation/cypressunit tests: green (6/6).commands/runs.jsunit file shows the same pre-existing standalone failures with and without this change (unrelatedsetUsageReportingFlagassertions).Release
🤖 Generated with Claude Code