Skip to content

feat(bigquery-driver): Upgrade @google-cloud/storage to 8 - #11905

Merged
ovr merged 4 commits into
masterfrom
cherry-pick-sdk-upgrade
Sep 16, 2026
Merged

ovr merged 4 commits into
masterfrom
cherry-pick-sdk-upgrade

Conversation

@ovr

@ovr ovr commented Sep 16, 2026

Copy link
Copy Markdown
Member

Check List

  • Tests have been run in packages where changes have been made if available
  • Linter has been run for changed code
  • Tests for the changes have been added if not covered yet
  • Docs have been added / updated if required

Description of Changes Made (if issue reference is not provided)

Bumps @google-cloud/storage from ^7.13.0 to ^8.1.0 in @cubejs-backend/bigquery-driver and @cubejs-backend/base-driver; both use only Storage (plus Bucket in the BigQuery driver), and the getFiles / getSignedUrl / bucket.file surface they touch is unchanged between 7.13.0 and 8.1.0 (verified by diffing the shipped typings — only an optional GetFilesOptions.filter was added, and the default signing version is still v2). This clears one Dependabot alert on the root lockfile, since 7.13.0 pinned fast-xml-parser ^4.4.1 and capped it below the 5.7.0 that GHSA-jr48-27g9-4h5h requires. A follow-up commit keeps fast-xml-parser on the 5.7.2 already in the tree rather than letting the new ^5.3.4 spec re-resolve the whole 5.x group to 5.11.1, which would have split it into two copies and added three transitives — a name → version-set diff confirms 0 new packages against master, with fast-xml-parser going 4.5.6 + 5.7.2 → a single 5.7.2 and strnum 1.0.5 + 2.2.3 → a single 2.2.3. Verified that yarn install --frozen-lockfile is a no-op, tsc on the BigQuery driver is clean, and yarn workspace @cubejs-backend/base-driver unit is 17/17; the BigQuery driver has integration tests only, which need GCP credentials.

Note for reviewers: @google-cloud/storage raised engines.node from >=14 to >=22 in v8, while all packages/* declare >=20.0.0. Nothing breaks at runtime (Docker images are node 24, CI runs 24/26), but the declared floor is worth revisiting separately.

🤖 Generated with Claude Code

@ovr
ovr requested a review from a team as a code owner September 16, 2026 15:37
@github-actions github-actions Bot added driver:bigquery Issues related to the BigQuery driver data source driver labels Sep 16, 2026
@claude

claude Bot commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Claude finished @ovr's task in 3m 55s —— View job


Review of #11905 — approve with 2 low-severity notes (0 high, 0 medium, 2 low)

Full review
  • Read the diff (two package.json bumps + yarn.lock)
  • Verified @google-cloud/storage 7→8 against every call site
  • Checked lockfile resolutions and duplicate copies
  • Checked engines and cross-package version consistency
  • Resolved stale review threads
  • Posted findings

Compatibility check

All three usages are compatible with v8:

  • packages/cubejs-base-driver/src/storage-fs/gcs.fs.ts:1new Storage({credentials, projectId}) / new Storage(undefined), storage.bucket(), bucket.getFiles({prefix}), file.getSignedUrl({action, expires})
  • packages/cubejs-bigquery-driver/src/BigQueryDriver.ts:22,163,363,373,375Storage, Bucket, bucket.file(), bucket.getFiles(), file.getSignedUrl()
  • packages/cubejs-base-driver/test/unit/storage-fs.test.ts:78new Storage(undefined)

None of these are on v8's removal list, and storage-fs.test.ts:78 constructs a real Storage, so the module genuinely loads under CJS despite v8 moving to teeny-request@11node-fetch@3 (ESM-only). That is the one failure mode a type-check alone would have missed, and it's covered.

Version consistency is right: @google-cloud/storage appears in exactly two package.json files and both moved to ^8.1.0 in lockstep, so there's no split-major hazard where base-driver and the BigQuery driver hand Bucket/Storage objects across a version boundary. Both packages declare "node": ">=20.0.0".

The fast-xml-parser claim in the PR body holds: the old ^4.4.1 ceiling is gone and every caret consumer now lands on 5.11.1, above the 5.7.0 floor GHSA-jr48-27g9-4h5h requires. The remaining 5.7.2 copy is also above it.

Findings

# Location Severity Concern
1 yarn.lock:12769 low ^5.3.4 re-resolved the caret group to 5.11.1 though the present 5.7.2 satisfies it, stranding a second 5.x copy
2 packages/cubejs-bigquery-driver/package.json:43 low nothing in CI exercises the v8 getFiles / getSignedUrl path

Both posted inline: #discussion_r4027928769, #discussion_r4027930536.

One correction to the inline note on finding 1: anynum@1.0.1 enters via strnum@2.4.2 (yarn.lock:20868), which fast-xml-parser@5.11.1 requires — not via teeny-request@11, whose deps are the proxy agents, node-fetch and stream-events. It still disappears if the caret group stays on 5.7.2.

Not worth an inline comment

yarn.lock now carries two majors each of retry-request (7 and 9) and teeny-request (9 and 11), because @google-cloud/bigquery@^7.7.0 still pulls the old pair through @google-cloud/common. Unavoidable in this PR; bumping @google-cloud/bigquery to 8 would collapse both, but that's a separate change with a real API surface to check.

Worth confirming out-of-band since I had no registry access here: that @google-cloud/storage@8.1.0's own engines.node is satisfied by >=20.0.0. If v8 moved its floor to 22, the two packages' engines need to follow. yarn install --frozen-lockfile succeeding in CI would surface an engines mismatch as a warning, not a failure.

Review threads

The thread listing returned 0 of my own threads (no unresolved threads at all on this PR), so none resolved and none re-affirmed.

· branch [`cherry-pick-sdk-upgrade`](https://github.com/cube-js/cube/tree/cherry-pick-sdk-upgrade)

Comment thread yarn.lock Outdated
"@cubejs-backend/shared": "1.7.39",
"@google-cloud/bigquery": "^7.7.0",
"@google-cloud/storage": "^7.13.0",
"@google-cloud/storage": "^8.1.0",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Verification gap on this major bump: nothing that runs in CI exercises the v8 GCS data path.

The two call sites that matter are bucket.getFiles(...) / file.getSignedUrl(...) in packages/cubejs-bigquery-driver/src/BigQueryDriver.ts:373-375 and the same pair in packages/cubejs-base-driver/src/storage-fs/gcs.fs.ts:39-43. Against the real SDK, the only coverage is new Storage(undefined) in packages/cubejs-base-driver/test/unit/storage-fs.test.ts:78, which just asserts the constructor doesn't throw — it never touches getFiles or getSignedUrl. The BigQuery driver's own tests are integration-only and need GCP credentials, so they don't run here either.

So a v8 behaviour change in either method's options shape or return tuple would land green. Worth adding a unit test that mocks Storage and asserts the getFiles/getSignedUrl call shapes against v8's types, or running the BigQuery export-bucket integration test once manually and noting the result on this PR.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One addition to this, since it changes how much the green build is worth: tsc passing gives no signal on the option shape either.

BigQueryDriver.ts:163 calls new Storage(this.options), and this.options is the full BigQuery options object built at BigQueryDriver.ts:126-153scopes, keyFilename, exportBucket, exportBucketCsvEscapeSymbol, pollTimeout, pollMaxInterval, location, userAgent, plus a spread of user ...config. None of the last six are StorageOptions keys. TypeScript only applies excess-property checks to object literals, so passing a variable means every one of them is accepted silently. A clean tsc is not evidence that storage 8 tolerates them.

So the cheapest thing that would cover the upgrade here is not the getFiles/getSignedUrl mock, it is the constructor smoke test base-driver already has at test/unit/storage-fs.test.ts:74 (new Storage(undefined)), applied to the shape this driver actually passes:

expect(() => new Storage({
  scopes: ["https://www.googleapis.com/auth/bigquery", "https://www.googleapis.com/auth/drive"],
  projectId: "p",
  exportBucket: "b",
  pollTimeout: 600000,
  userAgent: "CubeDev_Cube/1.7.39",
} as any)).not.toThrow();

That needs a runnable unit path in this package first — package.json:18 is "test": "yarn integration"jest --verbose dist/test, so a *.unit.test.ts added here compiles but is never invoked without GCP credentials.

@claude

claude Bot commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Claude finished @ovr's task in 5m 54s —— View job


Approve with two things to settle — 0 high, 2 medium

Full review
  • Gather context (diff, PR commits)
  • Verify @google-cloud/storage 7 → 8 API compatibility for the usages in both packages
  • Audit the yarn.lock hunks (fast-xml-parser / strnum resolution)
  • Verify install / tsc / unit tests
  • Handle prior review threads
  • Post review

Verdict

The lockfile is clean and the PR body's claims hold up where I could check them. Two medium findings, both about what the upgrade is not covered by rather than about the upgrade being wrong.

What checks out

The API-compatibility claim is correct for the actual call sites. Both consumers use a narrow surface:

  • packages/cubejs-base-driver/src/storage-fs/gcs.fs.ts:1new Storage(), storage.bucket(), bucket.getFiles({ prefix }), file.getSignedUrl({ action, expires })
  • packages/cubejs-bigquery-driver/src/BigQueryDriver.ts:22 — the same four plus bucket.file()

None of those signatures moved in 7 → 8.

The dedupe analysis is right, and there are no orphans. I checked every old transitive entry the diff leaves behind, and each still has a live consumer via @google-cloud/bigquery@7@google-cloud/common@5 (yarn.lock:3302):

entry still needed by
@google-cloud/paginator@^5.0.0 bigquery@7 (yarn.lock:3290), common@5
@google-cloud/projectify@^4.0.0 common@5 (yarn.lock:3306)
@google-cloud/promisify@^4.0.0 bigquery@7 (yarn.lock:3292), common@5 (yarn.lock:3307)
retry-request@^7.0.0 common@5 (yarn.lock:3313)
teeny-request@^9.0.0 common@5 (yarn.lock:3314), retry-request@7 (yarn.lock:19566)

So the remaining duplicates genuinely straddle majors, as stated. uuid@^8.0.0 was correctly dropped from the shared uuid@8.3.2 key (yarn.lock:21836) — ^8.3.0/^8.3.2 keep it alive.

The fast-xml-parser fix in 38c13de is sound. ^5.3.4 is folded onto the existing fast-xml-parser@5.7.2 key (yarn.lock:12749) alongside the AWS SDK's exact 5.7.2 pin (yarn.lock:1124), 5.7.2 satisfies >= 5.7.0 so GHSA-jr48-27g9-4h5h stays closed, and reverting the strnum collapse back to ^2.2.3 is right since the 2.4.2 requirement only came from 5.11.1.

base-driver's 17/17 is a real signal, not an incidental one. packages/cubejs-base-driver/test/unit/storage-fs.test.ts:74 constructs new Storage(undefined) against the actual SDK, so that suite does exercise storage 8's constructor. Good test to have had in place before this bump.

No lockfile drift elsewhere. The other four lockfiles (docs-mintlify, the three vizard ones) contain no @google-cloud/storage, and the root resolutions block (package.json:68) does not touch it.

Findings

  1. [medium] Uncovered new Storage(this.options) in the BigQuery driver, and tsc cannot validate it. BigQueryDriver.ts:163 passes the full BigQuery options object — scopes, keyFilename, exportBucket, exportBucketCsvEscapeSymbol, pollTimeout, pollMaxInterval, location, userAgent, plus a spread of user ...config. Excess-property checks apply only to object literals, so passing a variable means a clean build says nothing about whether storage 8 accepts those keys. Nothing runs it either: packages/cubejs-bigquery-driver/package.json:18 is integration-only. Folded into the existing open thread on this rather than opening a near-duplicate.

  2. [medium] ESM-only node-fetch@3 is now on the GCS code path. Storage 8 → retry-request@9teeny-request@11node-fetch@^3.3.2 (yarn.lock:16746), which is "type": "module" with no CJS entry. Both packages compile to CommonJS and declare engines: { "node": ">=20.0.0" }, but require() of ESM only works from Node 20.19 onward. Storage 7's chain was all-CJS (teeny-request@9node-fetch@2), and storage 8 still pins gaxios@^6.0.2 → node-fetch 2, so teeny-request 11 is the first ESM-only dep reachable from these calls. Docker images are on node:24.18.0 so shipped images are fine; the exposure is a self-hosted install on Node 20.0–20.18. Posted inline at packages/cubejs-bigquery-driver/package.json:43.

What I could not verify

This runner has no node_modules and no registry access, so I could not reproduce yarn install --frozen-lockfile, yarn tsc, or the base-driver unit run, and could not read teeny-request@11.0.1's own package.json to settle whether finding 2 is a hard require() or a dynamic import(). The lockfile-consistency and call-site analysis above is from the checked-out tree and holds independently.

Review threads

The listing returned 2 of my own threads. Resolved 1 (PRRT_kwDOCOH19M6jAQrq's sibling on yarn.lock, the fast-xml-parser@5.11.1 duplicate — verified fixed at yarn.lock:12749 by 38c13de). Re-affirmed 1 (PRRT_kwDOCOH19M6jAQrq, missing GCS coverage in the BigQuery driver — still live, and finding 1 was added to it as a reply rather than posted as a new thread). Neither new finding was a duplicate of an existing thread.

· `cherry-pick-sdk-upgrade`

"@cubejs-backend/shared": "1.7.39",
"@google-cloud/bigquery": "^7.7.0",
"@google-cloud/storage": "^7.13.0",
"@google-cloud/storage": "^8.1.0",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Storage 8 puts an ESM-only node-fetch on the GCS code path, which engines: { "node": ">=20.0.0" } (package.json:12, same in base-driver package.json:12) does not guarantee is loadable.

The new transitive chain in this diff:

@google-cloud/storage@8.1.0
  -> retry-request@^9.0.1        (yarn.lock:19568)
       -> teeny-request@^11.0.0  (yarn.lock:21046)
  -> teeny-request@^11.0.1
       -> node-fetch@^3.3.2      -> 3.3.2 (yarn.lock:16746)

node-fetch@3 is "type": "module" with no CJS entry. Both of these packages compile to CommonJS ("main": "dist/src/index.js", base-driver package.json:14), so reaching it goes through require(). require() of ESM only works from Node 20.19 / 22.12 onward — below that it throws ERR_REQUIRE_ESM. The declared floor is >=20.0.0, which admits 20.0 through 20.18.

This is new to this path. Storage 7.13.0's chain was retry-request@^7.0.0teeny-request@^9.0.0node-fetch@^2.6.9, all CJS, and storage 8 still pins gaxios@^6.0.2 (→ gaxios@6.6.0, node-fetch@^2.6.9, yarn.lock:13131), so gaxios is not what changed. gaxios@7 in the lockfile does depend on node-fetch 3 already, but nothing in the storage/bigquery chain resolves to it — teeny-request 11 is the first ESM-only dependency the GCS calls in BigQueryDriver.unload() and extractFilesFromGCS() can reach.

The published Docker images are unaffected — packages/cubejs-docker/latest.Dockerfile:1 is node:24.18.0-trixie-slim. The exposure is a user who npm i @cubejs-backend/server on a Node 20.x older than 20.19 and configures an export bucket; they get a load-time crash rather than a resolution error at install.

Two things to settle before merge:

  1. Whether teeny-request@11.0.1 is itself ESM (in which case the require() is unavoidable) or CJS with a dynamic import() of node-fetch (in which case it degrades gracefully). Worth confirming from the installed node_modules/teeny-request/package.json — I couldn't check it here, this runner has no node_modules and no registry access.
  2. If it is a hard require(), raise the floor to ">=20.19.0" in both manifests so the incompatibility surfaces at install time. A silent ERR_REQUIRE_ESM on the pre-aggregation export path is a much worse failure mode than an EBADENGINE.

Fix this →

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Correction on the floor number, from this round: @google-cloud/storage@8 declares engines.node: ">=22" itself, so ">=20.19.0" is not high enough — the required floor in both packages/cubejs-bigquery-driver/package.json:12 and packages/cubejs-base-driver/package.json:12 is ">=22". And the failure is not only the runtime ERR_REQUIRE_ESM described above: Yarn 1 classic hard-errors on an engine mismatch between a package and its dependency, so a self-hosted yarn install on Node 20 breaks at install time. Both manifests still say ">=20.0.0", so this thread stays open; the fix should bump the declared floor to >=22 in this PR rather than defer it.

ovr and others added 3 commits September 16, 2026 18:08
`@google-cloud/storage ^7.13.0` -> `^8.1.0` in `@cubejs-backend/bigquery-driver`
and `@cubejs-backend/base-driver`. Both use only `Storage` (and `Bucket` in the
BigQuery driver), unchanged across 7 -> 8.

This also clears 1 Dependabot alert on the root lockfile: `@google-cloud/storage@7.13.0`
pinned `fast-xml-parser ^4.4.1`, capping it below the 5.7.0 that GHSA-jr48-27g9-4h5h
needs; 8.1.0 depends on `^5.3.4`, which resolves to 5.11.1. The only remaining
copies are 5.7.2 and 5.11.1.

Verified: `yarn install --frozen-lockfile` is a no-op, `yarn tsc`, and
`yarn workspace @cubejs-backend/base-driver unit` (17/17). The BigQuery driver
has integration tests only, which need GCP credentials.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…d/storage 8

`fast-xml-parser@5.11.1` (new, via `@google-cloud/storage@8.1.0`) requires
`strnum ^2.4.2`, which landed alongside the `strnum ^2.2.3` that the pinned
`fast-xml-parser@5.7.2` already required. 2.4.2 satisfies `^2.2.3`, so the
`^2.2.3` spec key moves onto the 2.4.2 entry and the 2.2.3 entry drops.

Key merged onto the surviving entry rather than deleted and re-resolved, so
yarn picks nothing new.

Verified by a name -> version-set diff of the lockfile: 0 new packages,
0 added versions, `strnum@2.2.3` removed, multi-version packages 390 -> 389.
`yarn install --frozen-lockfile` passes and leaves the lock unmodified; a
non-frozen `yarn install` is a no-op (nothing to re-resolve or prune).

The other duplicates this upgrade brought in are not collapsible:
`@google-cloud/paginator` 5/7, `projectify` 4/6, `promisify` 4/6,
`retry-request` 7/9, `teeny-request` 9/11 and `@nodable/entities` 2/3 all
straddle majors, held down by the `@google-cloud/bigquery@7.7.0` subtree and
`@aws-sdk/xml-builder`; `fast-xml-parser@5.7.2` is an exact pin from
`@aws-sdk/xml-builder`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
….11.1

Adding `@google-cloud/storage@8`'s `fast-xml-parser ^5.3.4` made yarn re-resolve
the whole 5.x group to 5.11.1, even though the 5.7.2 already in the tree satisfies
`^5.3.4`. That split 5.x into two copies — `@aws-sdk/xml-builder`'s exact `5.7.2`
pin cannot follow the bump — and pulled in three packages that were not in the
lockfile before: `@nodable/entities@3.0.0`, `is-unsafe@2.0.2`, `anynum@1.0.1`.

Merges `^5.0.7`, `^5.3.4` and `^5.4.1` back onto the 5.7.2 entry and drops the
5.11.1 one; a non-frozen `yarn install` then prunes the three orphans. 5.7.2 is
still above the 5.7.0 that GHSA-jr48-27g9-4h5h requires, so the alert stays closed.

This supersedes the `strnum` collapse in 111df0d, which is reverted here: that
duplicate only existed because 5.11.1 required `strnum ^2.4.2`. With 5.11.1 gone,
`strnum` is back to a single 2.2.3 on its own.

Net effect on the lockfile versus master, by name -> version-set diff:

| package | master | before | after |
| --- | --- | --- | --- |
| `fast-xml-parser` | 4.5.6, 5.7.2 | 5.7.2, 5.11.1 | 5.7.2 |
| `strnum` | 1.0.5, 2.2.3 | 2.4.2 | 2.2.3 |
| `@nodable/entities` | 2.1.0 | 2.1.0, 3.0.0 | 2.1.0 |
| `is-unsafe` | - | 2.0.2 | - |
| `anynum` | - | 1.0.1 | - |

0 new packages against master. `yarn install --frozen-lockfile` passes and leaves
the lock unmodified, `tsc` on the BigQuery driver is clean, and
`yarn workspace @cubejs-backend/base-driver unit` is 17/17.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ovr
ovr force-pushed the cherry-pick-sdk-upgrade branch from 38c13de to 80aade9 Compare September 16, 2026 16:08
@claude

claude Bot commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Claude finished @ovr's task in 4m 20s —— View job


Review: dependency-only bump, no blocking defect — 1 medium (re-affirmed), 1 low (new inline comment)

Full review
  • Read the diff and the changed files
  • Verify the @google-cloud/storage API surface actually used
  • Check lockfile consistency and duplicate resolutions
  • Check engines / Node floor implications
  • Check CI coverage of the GCS export path
  • Resolve stale review threads, dedupe findings

Review threads

The listing returned 2 threads first-authored by me, both on packages/cubejs-bigquery-driver/package.json:43. 0 resolved, 2 re-affirmed — neither concern is addressed by the current head:

  • the ESM/engines thread: engines.node is still ">=20.0.0" in packages/cubejs-base-driver/package.json:12 and packages/cubejs-bigquery-driver/package.json:12, and the lock still resolves teeny-request@^11node-fetch@^3.3.2;
  • the verification-gap thread: no tests added; the only real-SDK call in a unit test is still new Storage(undefined) at packages/cubejs-base-driver/test/unit/storage-fs.test.ts:78.

One new inline comment this round (yarn.lock, fast-xml-parser pin durability). The engines finding was skipped as a duplicate of the existing open thread rather than re-posted.

API surface

The used surface checks out against the call sites: storage.bucket() / bucket.getFiles({ prefix }) / file.getSignedUrl({ action, expires }) in packages/cubejs-base-driver/src/storage-fs/gcs.fs.ts:37-46, plus bucket.file() and the same getFiles/getSignedUrl pair in packages/cubejs-bigquery-driver/src/BigQueryDriver.ts:363-378. Nothing in the diff touches call sites, and new Storage(this.options) (BigQueryDriver.ts:163) is unchanged behaviour.

Caveat on the stated verification method: a typings diff cannot show a changed runtime default (signing version, retry/timeout defaults live in code, not types), so "only an optional GetFilesOptions.filter was added" doesn't by itself cover the getSignedUrl default. The v8 release notes / upgrade guide are the right source there. I couldn't check them — this runner has no network access to the npm registry or GitHub releases.

Coverage

Better than the PR body implies. .github/workflows/drivers-tests.yml filters on packages/cubejs-bigquery-driver/** (not just src/**), so this PR does trigger Drivers tests, and bigquery-export-bucket-gcs is in the matrix — that job exercises getFiles + getSignedUrl against real GCS. It was still in_progress at review time (run 35119985117); its result is the evidence that matters for this PR, more than any unit test would be.

Note that packages/cubejs-base-driver/src/** is the filter for base-driver, and this PR changes only its package.json — so the base-driver half of the bump rides on the BigQuery job alone.

Lockfile

The name-level claim holds: no new package names, and fast-xml-parser / strnum each collapse to one version. Version-level duplicates do go up, though — @google-cloud/paginator 5.0.0 + 7.0.1, projectify 4.0.0 + 6.0.1, promisify 4.0.0 + 6.0.1, retry-request 7 + 9, teeny-request 9 + 11 — because @google-cloud/bigquery@^7.7.0 still pulls the v4/v5 generation. Unavoidable until BigQuery is bumped; worth stating plainly rather than leaving "0 new packages" to carry it.

uuid@^8.0.0 dropping out of the merged range (yarn.lock:21589) is correct — storage 8 no longer depends on it, and 8.3.2 stays for the other consumers.

Not flagged

No security surface: the change adds no code, and getSignedUrl expiry stays at 1h (gcs.fs.ts:43). No performance or error-handling delta. No comments added, so nothing to review under the comment rules.
· branch cherry-pick-sdk-upgrade

Comment thread yarn.lock
strnum "^1.0.5"

fast-xml-parser@^5.0.7, fast-xml-parser@^5.4.1:
fast-xml-parser@5.7.2, fast-xml-parser@^5.0.7, fast-xml-parser@^5.3.4, fast-xml-parser@^5.4.1:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This dedup is hand-merged and nothing enforces it, so it will come undone on the next lockfile touch.

^5.3.4 was moved onto this entry by hand — commit 80aade9 (fix(deps): Keep fast-xml-parser on 5.7.2 instead of re-resolving to 5.11.1) deleted the separate fast-xml-parser@^4.4.1 → 4.5.6 block and folded the range in here alongside 5.7.2, ^5.0.7, ^5.4.1. That is valid — 5.7.2 satisfies ^5.3.4 — but it is a lockfile-only fact. ^5.3.4 comes from a transitive dependent (yarn.lock:3334), ^5.0.7 from another (yarn.lock:1195), and ^5.4.1 from a third (yarn.lock:20081); none of those ranges appear in any package.json in the repo, and the root resolutions block (package.json:68-74es5-ext, lodash, @types/node, @types/ramda, thrift) has no fast-xml-parser key.

So the only thing keeping all four ranges on one resolution is that this hunk currently says so. Any yarn upgrade that revisits the entry, or a dependabot bump to one of the three dependents, is free to re-resolve ^5.3.4 (and the others) to the newest matching publish — 5.11.1 — and re-split the entry into the two blocks that 80aade9 just collapsed. The regression is silent: dedup is not something CI asserts, so it lands green and the duplicate copy reappears.

Making it durable is a one-line addition to the root resolutions:

"fast-xml-parser": "5.7.2",

That pins every range — ^5.0.7, ^5.3.4, ^5.4.1 — to the single 5.7.2 entry regardless of what the transitive dependents ask for next, which is the invariant 80aade9 was reaching for. Worth a short comment on the entry too, noting why it is pinned rather than floating, so a future bump does not read it as stale and lift it.

Same reasoning applies to 8554df3 (Collapse the duplicate strnum introduced by @google-cloud/storage 8) if that collapse was also achieved by editing the lockfile rather than by a resolution.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Not doing this — an exact resolutions pin on this package would cause a worse and quieter failure than the duplicate it prevents.

1. It would silently override a vendor pin that actually moves. @aws-sdk/xml-builder pins fast-xml-parser exactly, and that pin is not static:

@aws-sdk/xml-builder pins
3.972.0 5.2.5
3.972.21 (current) 5.7.2
3.972.30 5.7.3
3.972.40 (dependency dropped)

A root "fast-xml-parser": "5.7.2" would have forced 5.7.3 back down to 5.7.2 on the very next aws-sdk bump, against what the vendor deliberately chose — and because CI runs --frozen-lockfile, nothing would flag it.

2. It would block security patches on a package that just had one. The whole reason this PR exists is GHSA-jr48-27g9-4h5h (fast-xml-parser < 5.7.0). Exact-pinning the package Dependabot most recently filed an alert against means the next advisory needs someone to remember to edit resolutions by hand. Every existing entry in that block is there for a deliberate reason (es5-ext protestware avoidance, @types/node unification, thrift); none is a dedupe.

3. The premise overstates the risk. "Nothing enforces it" is true of every one of the ~3000 entries in yarn.lock — the lockfile is the enforcement, and this repo runs yarn install --frozen-lockfile in 15 places across 6 workflows, so nothing re-resolves in CI. The only thing that can re-split the entry is a deliberate dependency bump, which is a reviewed PR with the lockfile diff visible.

Same answer for 8554df3: that strnum collapse was reverted in 80aade9 anyway, since it only existed because the re-resolved 5.11.1 required strnum ^2.4.2.

If this drifts on a future bump, the fix is the same key-merge, applied then, with the version-set diff to prove it — not a standing pin on a CVE-prone parser.

…l-vm-modules

`@google-cloud/storage@8` pulls in `teeny-request@11`, which reaches node-fetch
through a dynamic import:

```js
const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
```

node-fetch 3 is ESM-only, so under Jest's CJS VM the import callback is never
installed and the first HTTP call throws before it reaches the network:

```
BigQueryDriver > unload
  TypeError: A dynamic import callback was invoked without --experimental-vm-modules
```

`NODE_OPTIONS=--experimental-vm-modules` is already how athena, base-driver,
clickhouse, databricks-jdbc, prestodb and testing-drivers handle the same
problem; this applies it to the remaining driver `integration*` scripts so the
next dependency that goes ESM-only doesn't reopen this one suite at a time.

| package | scripts |
| --- | --- |
| bigquery | `integration:bigquery` |
| crate | `integration:crate` |
| dremio | `integration:dremio` |
| druid | `integration`, `integration:druid` |
| duckdb | `integration:duckdb` |
| firebolt | `integration:firebolt` |
| materialize | `integration:materialize` |
| mongobi | `integration`, `integration:mongobi` |
| mysql | `integration:mysql` |
| mysql-aurora-serverless | `integration` |
| pinot | `integration:pinot` |
| postgres | `integration:postgres` |
| questdb | `integration:questdb` |
| trino | `integration`, `integration:trino` |
| vertica | `integration:vertica` |

Reproduced the failure against the real `teeny-request@11` in a throwaway Jest
suite and confirmed the flag fixes it (fails without, passes with). `yarn
lint:npm` passes and every `packages/*-driver/package.json` still parses.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added driver:mongodb Issues relating to the MongoBI driver driver:mysql Issues relating to the MySQL/MariaDB driver driver:postgres Issues relating to the Postgres driver driver:mysql-aurora-serverless Issues relating to the AWS MySQL Aurora Serverless driver driver:druid Issues relating to the Druid driver driver:crate driver:dremio driver:questdb driver:firebolt driver:duckdb driver:trino Issues relating to the Trino driver driver:materialize driver:pinot labels Sep 16, 2026
@claude

claude Bot commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Claude finished @ovr's task in 4m 51s —— View job


Dependency upgrade looks mechanically sound — 0 high, 2 medium, 2 low. 1 new inline comment; 3 prior threads re-affirmed, 0 resolved.

Full review
  • Read the diff (package.json changes + yarn.lock)
  • Verify lockfile consistency / no new packages
  • Check @google-cloud/storage v8 API surface usage in base-driver & bigquery-driver
  • Check the --experimental-vm-modules test change
  • Resolve stale review threads / dedupe findings
  • Post review

What holds up

The v8 surface actually used is small and unchanged. BigQueryDriver.ts:163-164 (new Storage, storage.bucket) and BigQueryDriver.ts:363-379 (bucket.file, bucket.getFiles({ prefix }), file.getSignedUrl({ action, expires })) mirror gcs.fs.ts:32-48 exactly, and no other call is made. grep confirms only two manifests declare the dependency and both moved to ^8.1.0 together, so there's no version skew producing two copies of Storage in one install.

BaseDriver.ts:703 reaches GCS through await import('./storage-fs/gcs.fs.js'), so @google-cloud/storage is never loaded unless an export bucket is configured. That materially limits the blast radius of the engine bump below — it's an install-time problem, not a startup one.

The --experimental-vm-modules diagnosis in 69eac09 is correct and the fix lands where the failure is: .github/actions/integration/*.sh drives the suites through yarn lerna run integration:<db>, so the script-level NODE_OPTIONS is inherited.

Findings

1. Declared Node floor is now wrong — medium. packages/cubejs-base-driver/package.json:12 and packages/cubejs-bigquery-driver/package.json:12 still say "node": ">=20.0.0" while @google-cloud/storage@8 requires >=22. Covered by the existing thread on packages/cubejs-bigquery-driver/package.json:43, where I replied with a correction: the floor needs >=22, not the >=20.19.0 originally proposed there, and the failure mode is an install-time hard error under Yarn 1 classic (The engine "node" is incompatible with this module), not just an npm warning. The official Docker images are node:24.18.0 (packages/cubejs-docker/latest.Dockerfile:1) so that path is unaffected; self-hosted npm/yarn installs on Node 20 are not. Deferring this to a follow-up means the packages ship advertising a floor they don't support.

2. --experimental-vm-modules added to integration* but not the sibling unit scripts — low. Posted inline on packages/cubejs-crate-driver/package.json:35; six unit scripts across crate, dremio, duckdb, pinot, trino and mysql-aurora-serverless still run bare jest, which is inconsistent with the commit's own stated rationale and with clickhouse/athena/prestodb, which carry the flag on both.

3. "0 new packages" is true by name, not by version — low, informational. Five resolutions are new to the tree: @google-cloud/paginator@7.0.1, @google-cloud/projectify@6.0.1, @google-cloud/promisify@6.0.1, retry-request@9.0.1, teeny-request@11.0.1. The practical consequence is that the BigQuery driver now loads two HTTP stacks in one process — teeny-request@9node-fetch@2 via @google-cloud/bigquery@7, and teeny-request@11node-fetch@3 via storage 8 — with two different proxy-agent implementations reading HTTPS_PROXY. Not a defect, but worth stating in the PR body, which currently reads as if the dependency graph were untouched. uuid@^8.0.0 being dropped from the storage entry is a genuine reduction.

4. The upgraded path is unverified against a live bucket — medium. unload / getSignedUrl is the only production code this change affects, and it's reachable only through the credential-gated integration:bigquery job. The PR body confirms those weren't run locally, and the --experimental-vm-modules fix was derived from a synthetic repro rather than a green BigQuery run. Covered by the existing thread on packages/cubejs-bigquery-driver/package.json:43. At review time the Build and Drivers tests runs were both still in_progress — the BigQuery leg of Build going green is what should gate the merge, since it's the only thing that exercises v8's signer.

Review threads

The listing returned 3 threads first-authored by claude, one page, hasNextPage: false. Resolved 0 — all three are still live against the current tree:

thread site why it stays open
PRRT_kwDOCOH19M6jAQrq bigquery package.json:43 verification gap; integration suite still the only coverage
PRRT_kwDOCOH19M6jAnw7 bigquery package.json:43 both manifests still declare ">=20.0.0"
PRRT_kwDOCOH19M6jA8Gk yarn.lock:12634 root resolutions (package.json:68-74) still has no fast-xml-parser key, so the hand-merged dedup isn't enforced against the next yarn install

Re-affirmed 3, resolved 0, 1 new inline comment posted.

· branch `cherry-pick-sdk-upgrade`

"test": "yarn integration",
"integration": "npm run integration:crate",
"integration:crate": "jest --verbose dist/test",
"integration:crate": "NODE_OPTIONS=--experimental-vm-modules jest --verbose dist/test",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The flag went onto the integration* scripts but not the sibling unit scripts in the same packages, so the commit's stated goal — "so the next dependency that goes ESM-only doesn't reopen this one suite at a time" — is only half met.

Still running bare jest:

  • packages/cubejs-crate-driver/package.json:36
  • packages/cubejs-dremio-driver/package.json:19
  • packages/cubejs-duckdb-driver/package.json:33
  • packages/cubejs-pinot-driver/package.json:33
  • packages/cubejs-trino-driver/package.json:33
  • packages/cubejs-mysql-aurora-serverless-driver/package.json:18

Nothing is broken today — teeny-request@11's import('node-fetch') only fires on an actual HTTP call, and these unit suites mock the connection. But push.yml:137 runs lerna run unit across every package, and BaseDriver.ts:703 already reaches GCS through await import('./storage-fs/gcs.fs.js'), so the first unit test that exercises an unload path fails with the same A dynamic import callback was invoked without --experimental-vm-modules.

Two options: add the flag to those six unit scripts for parity with clickhouse/athena/prestodb (which already have it on both), or set NODE_OPTIONS once at the workflow level in push.yml and drop it from the 29 individual scripts. The per-script approach is what the repo already does, so parity is the smaller change.

@codecov

codecov Bot commented Sep 16, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 60.67%. Comparing base (8d67b00) to head (69eac09).

Additional details and impacted files
@@           Coverage Diff           @@
##           master   #11905   +/-   ##
=======================================
  Coverage   60.67%   60.67%           
=======================================
  Files         240      240           
  Lines       19297    19297           
  Branches     3914     3914           
=======================================
  Hits        11709    11709           
  Misses       7040     7040           
  Partials      548      548           
Flag Coverage Δ
cube-backend 60.67% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ovr
ovr merged commit 4822088 into master Sep 16, 2026
103 of 107 checks passed
@ovr
ovr deleted the cherry-pick-sdk-upgrade branch September 16, 2026 17:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

data source driver driver:bigquery Issues related to the BigQuery driver driver:crate driver:dremio driver:druid Issues relating to the Druid driver driver:duckdb driver:firebolt driver:materialize driver:mongodb Issues relating to the MongoBI driver driver:mysql Issues relating to the MySQL/MariaDB driver driver:mysql-aurora-serverless Issues relating to the AWS MySQL Aurora Serverless driver driver:pinot driver:postgres Issues relating to the Postgres driver driver:questdb driver:trino Issues relating to the Trino driver

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant