Skip to content

fix: stop native tfjs addon breaking tests in CI (semantic-search + reverse-image-search)#1106

Merged
cabljac merged 2 commits into
mainfrom
investigate/semantic-search-flaky-tests
Jul 2, 2026
Merged

fix: stop native tfjs addon breaking tests in CI (semantic-search + reverse-image-search)#1106
cabljac merged 2 commits into
mainfrom
investigate/semantic-search-flaky-tests

Conversation

@cabljac

@cabljac cabljac commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

Fixes #355.

Problem

The node.js_22_test CI job fails intermittently with:

The Node.js native addon module (tfjs_binding.node) can not be found ...

Suites fail to load (not fail assertions), which bails the whole lerna run test job. It affects two extensions that depend on TensorFlow: firestore-semantic-search and storage-reverse-image-search. Both are fixed here in one PR because lerna run test --concurrency 1 with nx-bail stops at the first failing extension, so CI can only go green once both are fixed together.

Root cause

  1. Several suites transitively import a module that does require('@tensorflow/tfjs-node') (use_embeddings.ts / feature_vectors.ts).
  2. @tensorflow/tfjs-node loads a platform-specific native addon (tfjs_binding.node) at import time.
  3. CI installs with npm ci --ignore-scripts, so tfjs-node's postinstall that downloads the addon never runs - the addon is absent.
  4. Whether a run passed depended on whatever node_modules was restored from the Lerna cache (keyed on the lockfile hash), so it passed/failed at random, and only in CI.

Fix

firestore-semantic-search: every test that exercises real embeddings is already skipped (needs live model access), so @tensorflow/tfjs-node and the Universal Sentence Encoder are mapped to lightweight stubs via jest moduleNameMapper. No coverage lost.

storage-reverse-image-search: two specs genuinely exercise TensorFlow (load a real model over the network, assert on real tensors/memory), so a blanket stub is not possible. Split unit vs integration:

  • Unit run (default test script) stubs @tensorflow/tfjs-node via moduleNameMapper, fixing the many suites that only mock or never invoke feature_vectors.
  • The two real-tf specs move to jest.integration.config.js (npm run test:integration), which uses the real package. They need the native addon built and network access, so they do not belong in the --ignore-scripts CI job. Preserved, not deleted.
  • The stub lives outside a __mocks__ directory on purpose: manual mocks for node_modules packages are auto-applied by jest and cannot be disabled per-config, which would also break the integration run. moduleNameMapper keeps it scoped to the unit config.

Verification

Reproduced the CI failure locally by removing the native addon: suites failed to load exactly as in CI. With the fix applied and the addon still absent, both extensions' unit suites run green against the Firestore emulator (semantic-search: 11 suites pass, was 5 failing; reverse-image-search: 15 suites pass, was 10 failing). Confirmed in CI that firestore-semantic-search:test now passes.

… in CI

Unit test suites failed to run in CI with 'tfjs_binding.node can not be
found'. The cause is a require-time dependency: several suites transitively
import use_embeddings.ts, which calls require('@tensorflow/tfjs-node'). That
package loads a platform-specific native addon at import time, but CI installs
dependencies with 'npm ci --ignore-scripts', so tfjs-node's postinstall never
downloads the addon. Whether a run passed depended on stale cached node_modules,
making it flaky and CI-only.

Mock @tensorflow/tfjs-node and the Universal Sentence Encoder via jest
moduleNameMapper so unit tests never load the native binary. The only tests
that exercise real embeddings are already skipped (they require live model
access), so no coverage is lost.

Verified against the emulator with the native addon removed: all suites now
run and pass instead of failing to load.
@cabljac cabljac changed the title fix(firestore-semantic-search): stop native tfjs addon breaking tests in CI fix: stop native tfjs addon breaking tests in CI (semantic-search + reverse-image-search) Jul 2, 2026
…sts in CI

Test suites failed to run in CI with 'tfjs_binding.node can not be found'.
Same root cause as firestore-semantic-search: suites transitively import
feature_vectors.ts, which imports @tensorflow/tfjs-node, and that package loads
a platform-specific native addon at import time. CI installs dependencies with
'npm ci --ignore-scripts', so tfjs-node's postinstall never downloads the addon,
so any suite touching feature_vectors fails to load. Whether a run passed
depended on stale cached node_modules, making it flaky and CI-only.

Split unit and integration tests:
- Unit run (default 'test' script) maps @tensorflow/tfjs-node to a lightweight
  stub via moduleNameMapper, so the many suites that only mock or never invoke
  feature_vectors stop crashing at import time.
- The two specs that genuinely exercise TensorFlow (feature_vectors.test.ts and
  feature_vectors.memory.test.ts load a real model over the network and assert
  on real tensors) move to jest.integration.config.js, run via
  'npm run test:integration'. They need the native addon built and network
  access, so they do not belong in the --ignore-scripts CI job.

The stub lives outside a __mocks__ directory on purpose: manual mocks for
node_modules packages are auto-applied by jest and cannot be disabled per
config, which would also break the integration run. Wiring it through
moduleNameMapper keeps it scoped to the unit config.

Verified with the native addon removed and the emulator running: the unit run
previously had 10 suites fail to load; it now runs 15 suites green with 0
failures. The integration config resolves the real tfjs package.

Fixes #355.
@cabljac cabljac force-pushed the investigate/semantic-search-flaky-tests branch from 2f7b5af to 8150388 Compare July 2, 2026 09:41
@cabljac cabljac marked this pull request as ready for review July 2, 2026 09:46
@cabljac cabljac merged commit 95cd509 into main Jul 2, 2026
14 checks passed
@cabljac cabljac deleted the investigate/semantic-search-flaky-tests branch July 2, 2026 10:13
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.

[storage-reverse-image-search]: Fix flaky tests

1 participant