Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .github/actions/setup-jfrog/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,38 @@ runs:
always-auth=true
EOF
echo "npm configured to use JFrog registry"

# Rewrite lockfile `resolved:` URLs to JFrog. `npm ci` honors the
# lockfile's `resolved:` URL over the `.npmrc` registry; protected
# runners cannot reach `registry.npmjs.org` or the internal
# `npm-proxy.dev.databricks.com` directly, so without this rewrite
# npm hangs ~8 minutes on any package whose `resolved:` points
# elsewhere, then dies with "Exit handler never called".
# The committed lockfile is kept as-generated locally (mixed
# public-npm + dev-proxy URLs) so contributors can `npm ci`
# locally; this step adapts it for CI.
- name: Rewrite lockfile to JFrog registry
shell: bash
run: |
set -euo pipefail
if [ -f package-lock.json ]; then
# Rewrite both public npm and the internal dev-proxy (the
# latter is written by `npm install` when run on a dev
# workstation whose .npmrc points at npm-proxy.dev).
sed -i \
-e 's|https://registry.npmjs.org|https://databricks.jfrog.io/artifactory/api/npm/db-npm|g' \
-e 's|https://npm-proxy.dev.databricks.com|https://databricks.jfrog.io/artifactory/api/npm/db-npm|g' \
package-lock.json
echo "package-lock.json resolved: URLs rewritten to JFrog"
echo "Resolved URL distribution after rewrite:"
grep -oE '"resolved": "https://[^/]+' package-lock.json | sort | uniq -c
# Fail loud if any non-JFrog host remains — a new registry hostname
# added to the tree would otherwise silently hang `npm ci` for 8min.
LEAKS=$(grep -oE '"resolved": "https://[^/]+' package-lock.json | grep -v 'databricks\.jfrog\.io' | sort -u || true)
if [ -n "$LEAKS" ]; then
echo "::error::JFrog rewrite incomplete; non-JFrog hosts remain: $LEAKS"
exit 1
fi
else
echo "no package-lock.json found; skipping rewrite"
fi
55 changes: 41 additions & 14 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ jobs:
labels: linux-ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Pin lockfileVersion to 2
# See CONTRIBUTING.md "Dependency Pins". Modern npm writes v3
# by default; catching drift here prevents silent format upgrades
# from sneaking in via `npm install`.
run: |
actual=$(jq -r '.lockfileVersion' package-lock.json)
if [ "$actual" != "2" ]; then
echo "::error::package-lock.json lockfileVersion is $actual; expected 2. Regenerate with 'npm install --lockfile-version=2'."
exit 1
fi
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 20
Expand All @@ -44,10 +54,15 @@ jobs:
runs-on:
group: databricks-protected-runner-group
labels: linux-ubuntu-latest
timeout-minutes: 20
strategy:
matrix:
# only LTS versions starting from the lowest we support
node-version: ['14', '16', '18', '20']
# LTS versions: 16/18/20 are the currently-supported floor; 22
# is the active LTS and 24 is the new LTS. Node 14 was dropped
# because the modern npm ecosystem (e.g. @dabh/diagnostics@2.0.7+
# via winston) ships ES2021 syntax (||=) that Node 14's V8 cannot
# parse. Node 14 has been EOL upstream since April 2023.
node-version: ['16', '18', '20', '22', '24']
env:
cache-name: cache-node-modules
NYC_REPORT_DIR: coverage_unit_node${{ matrix.node-version }}
Expand All @@ -57,11 +72,6 @@ jobs:
with:
node-version: ${{ matrix.node-version }}
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Set up Python 3.10 for Node 14
if: ${{ matrix.node-version == '14' }}
uses: actions/setup-python@7f4fc3e22c37d6ff65e88745f38bd3157c663f7c # v4
with:
python-version: '3.10'
- uses: ./.github/actions/setup-jfrog
- name: Cache node modules
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
Expand Down Expand Up @@ -89,32 +99,49 @@ jobs:
group: databricks-protected-runner-group
labels: linux-ubuntu-latest
environment: azure-prod
# Cap job time so a wedged matrix entry doesn't hold a runner +
# warehouse session for GitHub's 6-hour default. Tests historically
# complete in <15min; 30min leaves room for warehouse cold-start.
timeout-minutes: 30
strategy:
# Run all matrix entries even if one fails so a Node-version-specific
# network/TLS regression doesn't hide other versions' results.
fail-fast: false
matrix:
# Matches the unit-test matrix so e2e catches Node-version-specific
# behaviors (TLS/cipher defaults, native fetch interaction, lz4 ABI,
# OAuth crypto APIs) that unit tests with mocked I/O can't surface.
node-version: ['16', '18', '20', '22', '24']
env:
E2E_HOST: ${{ secrets.DATABRICKS_HOST }}
E2E_PATH: ${{ secrets.TEST_PECO_WAREHOUSE_HTTP_PATH }}
E2E_ACCESS_TOKEN: ${{ secrets.DATABRICKS_TOKEN }}
E2E_TABLE_SUFFIX: ${{github.sha}}
# Include Node version in the suffix so parallel matrix entries
# don't collide on shared E2E table names. Use underscore (not
# hyphen) — hyphens aren't valid in SQL unquoted identifiers,
# and tests build identifiers as `..._${E2E_TABLE_SUFFIX}`.
E2E_TABLE_SUFFIX: ${{ github.sha }}_node${{ matrix.node-version }}
E2E_CATALOG: peco
E2E_SCHEMA: default
E2E_VOLUME: e2etests
cache-name: cache-node-modules
NYC_REPORT_DIR: coverage_e2e
NYC_REPORT_DIR: coverage_e2e_node${{ matrix.node-version }}

steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 20
node-version: ${{ matrix.node-version }}
- uses: ./.github/actions/setup-jfrog
- name: Cache node modules
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: ~/.npm
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
key: ${{ runner.os }}-${{ matrix.node-version }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
${{ runner.os }}-${{ matrix.node-version }}-build-${{ env.cache-name }}-
${{ runner.os }}-${{ matrix.node-version }}-build-
${{ runner.os }}-${{ matrix.node-version }}-
- name: Run e2e tests
run: |
npm ci
Expand Down
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
# Release History

## 2.0.0

**Breaking changes:**

- **`engines.node` raised from `>=14.0.0` to `>=16.0.0`.** Node 14 is dropped. The modern npm ecosystem ships ES2021 syntax (`||=`) in widely-used transitive deps (e.g. `@dabh/diagnostics@2.0.7+` via `winston`) that Node 14's V8 cannot parse. Node 14 has been EOL upstream since April 2023.
- **`uuid` runtime dep bumped from `^9.0.0` to `^11.1.1`.** uuid 11 is dual-published as ESM and CJS; this driver's CJS-compiled `dist/` continues to `require('uuid')` without changes. Customers whose code constructs uuids via this driver's transitive copy will see the v11 API surface (`v4`, `stringify`, `NIL` — the functions this driver uses — are API-stable across v9→v11).
- **`thrift` runtime dep bumped from `^0.16.0` to `^0.23.0`.** Seven minor versions of the Apache Thrift Node.js client. Clears GHSA-r67j-r569-jrwp (HIGH) and GHSA-526f-jxpj-jmg2.

**Security:**

- Clear all OSV-Scanner HIGH/MED/LOW findings on the lockfile via dep bumps and an `overrides` block pinning 18 transitives to patched versions (databricks/databricks-sql-nodejs#390 by @vikrantpuppala)
- Notably clears GHSA-w5hq-g745-h8pq (uuid v3/v5/v6 buffer-bounds, HIGH 7.5 — not reachable in this driver's usage but visible to customer-side scanners against our lockfile)

**Other:**

- Extend CI matrix to Node 16/18/20/22/24 for both unit and e2e tests (was 14/16/18/20 unit, single-version Node 20 e2e)
- CI: rewrite lockfile `resolved:` URLs to JFrog mirror before `npm ci` so protected runners can fetch
- TypeScript pinned to exact `5.5.4` (constraint: >=5.0 for uuid@11 d.ts, <5.6 to avoid Buffer-generic emit changing published declarations)

## 1.15.0

- Add SPOG routing support: parse `?o=<workspaceId>` from `httpPath` and inject `x-databricks-org-id` on Thrift, telemetry, and feature-flag requests. Expose `customHeaders` on `ConnectionOptions` for caller-supplied headers (databricks/databricks-sql-nodejs#391 by @samikshya-db)
Expand Down
14 changes: 14 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,20 @@ npm run lint:fix
npm run type-check
```

## Dependency Pins

A few entries in `package.json` are pinned more tightly than usual. Don't relax these without understanding why.

- **`typescript: "5.5.4"`** (exact, no caret). This pin has both a floor and a ceiling:

- Floor (TS >= 5.0) is required because `uuid@11`'s shipped `.d.ts` uses `export type * from './types.js'`, a TS 5.0+ feature.
- Ceiling (TS < 5.6) is required because TS 5.6 changed how `@types/node`'s generic `Buffer<TArrayBuffer extends ArrayBufferLike>` declarations get emitted into our published `dist/*.d.ts`. Allowing TS 5.6+ would leak `Buffer<ArrayBufferLike>` into the published types, which fails to compile for consumers on stale `@types/node`.
- If you bump TS, run `npm run build` and `git diff dist/` and verify no `Buffer<...>` generics appear in any `.d.ts`. If they do, you need to either roll back or also bump `@types/node` consumer expectations (a customer-facing change).

- **`overrides.uuid: "^11.1.1"`**. Forces `thrift@0.23.0`'s declared `uuid: ^13.0.0` (ESM-only) down to v11 (dual ESM+CJS). Without this override, the driver's CJS-compiled `dist/` would crash on `require('uuid')` at runtime. Remove this override only after migrating the driver to ESM or when `thrift` drops the uuid dep.

- **`package-lock.json` is pinned to `lockfileVersion: 2`.** Modern npm writes v3 by default. To regenerate the lockfile, run `npm install --lockfile-version=2` so CI's lint step doesn't reject your PR. v2 is kept for compat with older toolchains; revisit when the team is ready to drop them.

## Pull Request Process

1. Update the [CHANGELOG](CHANGELOG.md) with details of your changes, if applicable.
Expand Down
7 changes: 6 additions & 1 deletion lib/connection/auth/tokenProvider/FederationProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,12 @@ export default class FederationProvider implements ITokenProvider {
'Content-Type': 'application/x-www-form-urlencoded',
},
body,
signal: controller.signal,
// node-fetch ships its own AbortSignal shim that differs slightly
// from the native AbortSignal (subtle `this`-typing mismatch on
// onabort handler). TS 4 didn't catch this; TS 5+ does. The two
// are runtime-compatible, so cast through `unknown` (rather than
// `any`) to keep the assertion narrow.
signal: controller.signal as unknown as import('node-fetch').RequestInit['signal'],
});

if (!response.ok) {
Expand Down
Loading
Loading