Skip to content

Verify the published package on clean installs before promoting to latest#64

Merged
wudidapaopao merged 4 commits into
chdb-io:mainfrom
ShawnChen-Sirius:ci/verify-published-package
Jul 1, 2026
Merged

Verify the published package on clean installs before promoting to latest#64
wudidapaopao merged 4 commits into
chdb-io:mainfrom
ShawnChen-Sirius:ci/verify-published-package

Conversation

@ShawnChen-Sirius

@ShawnChen-Sirius ShawnChen-Sirius commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Problem

The release workflow builds the native addon and runs the suite in the build tree, so
it only ever tests the in-place build, never the artifact users install. That is the gap
#50 fell through: the Linux @chdb/lib-* binary had the build machine's absolute rpath
(/home/runner/work/chdb-node/chdb-node/libchdb.so) baked in, which loaded fine on the CI
build box and threw cannot open shared object file on every clean host.

First principles: what a user runs is the packed tarball, with @chdb/lib-* resolved
through optionalDependencies and loaded by rpath at the installed location, on a clean
machine. None of that is exercised by "build then test in place." So: test what users get,
and gate latest on it.

Change

  • test/pack/installed.test.mjs imports chdb by name (never the source tree), so
    it exercises the packed files, the platform binary resolved via optionalDependencies, its
    rpath at the installed location, and the subpath exports. The first import 'chdb' loads
    the native addon from where npm put it — the exact why this path /home/runner/work/chdb-node/chdb-node/libchdb.so #50 failure point. It then runs
    version(), a stateless query, an async query, a Session insert/query/stream round-trip,
    and a chdb/connection subpath resolution.

  • prebuild-publish.yml becomes publish → verify → promote:

    • a stable release is published to a holding dist-tag (unverified); prereleases stay on next;
    • a verify matrix (every target platform x Node 18/20/22) installs the just-published
      chdb from npm into a clean dir and runs the installed-package tests;
    • promote moves latest only after verify is green on every leg. If verify fails on any
      platform, users on latest never see the broken release.

Validation

Locally: npm pack -> clean npm install ./chdb-*.tgz (real @chdb/lib-* pulled from npm)
-> the installed-package tests pass 5/5. The same flow would have failed at import 'chdb'
on the #50 build.

Notes

  • The unit suite (test/v3, source correctness) still runs in-tree on PRs; the new
    installed-package suite is the release-time artifact gate. Separate concerns.
  • @chdb/lib-* subpackages publish before verify, but nobody installs them directly — they
    are pulled transitively only by a chdb version, which is gated by the latest
    promotion, so a bad binary can't reach users via latest.
  • Bun/Deno legs can be added to the verify matrix as a follow-up.

Fixes the class of bug behind #50.


Additional change: sync @clickhouse/client 1.23.0 release

@clickhouse/client 1.23.0 was published to npm on 2026-06-29 (GitHub release tag client-1.23.0 at commit 70ad405) — the first stable release carrying the connection injection point from clickhouse-js#879/#880. This is the first end-to-end path where users can npm install chdb @clickhouse/client and get a working chDB integration without pinning a pre-release. Three follow-ups landed in the second commit of this PR:

  1. peerDependencies['@clickhouse/client']: ">=1.23.0" (optional). Marked optional in peerDependenciesMeta so users installing chdb without chdb/connection aren't forced to pull it in. Users who DO import from chdb/connection with an older @clickhouse/client now get a clear npm warning instead of a runtime TS error / undefined field surprise.

  2. skip_list.json#syncedAgainst.ref: mainclient-1.23.0. Follows the sync-policy table's third row ("After next release: latest released tag"). lastSyncedSha bumped to 70ad405, lastSyncedAt to 2026-07-01.

  3. runner.mjs auto-detects the upstream Vitest layout. client-1.23.0 was cut before clickhouse-js#931 (which merged 2026-06-30 and moved the config/setup into packages/client-node/). The release tag still has the OLD repo-root layout (vitest.node.setup.ts at root, test:node:integration script at root); main has the NEW per-package layout. runner.mjs now probes for both setup-file locations and picks the right npm-script incantation for each.

Verification (clean env):

rm -rf .chdb-runner
npm run build:ts                                    → clean
npx vitest run test/v3/connection/contract.test.ts  → 13/13
node tests/clickhouse-js/runner.mjs                 → detected upstream layout: pre-931
                                                      Test Files 26 pass / 2 skip (28)
                                                      Tests 170 pass / 41 skip / 0 fail (211)

The 10-test drop vs. the previous main run (180 → 170) is because the pre-#931 test:node:integration script only invokes the client-node integration suite; the post-#931 packages/client-node script pulls the shared common tests in as well. ChdbConnection coverage is identical across both — every previously-passing case that surfaces the adapter still passes.

🤖 Generated with Claude Code

Note

Verify the published npm package on clean installs before promoting to latest

  • Stable releases now publish under the unverified dist-tag instead of latest; a new verify job in prebuild-publish.yml installs the package into a clean temp dir across 4 OSes and Node 18/20/22, runs the new installed.test.mjs suite, and retries up to 6 times for registry propagation.
  • A new promote job moves the latest dist-tag to the verified version only after all matrix checks pass; prereleases continue to publish directly under next.
  • npm retry/backoff env vars and cache: npm are added to all CI workflows to reduce flakiness from transient registry errors.
  • The clickhouse-js test runner gains a detectLayout() function to handle both pre- and post-#931 upstream repo layouts automatically.
  • Behavioral Change: stable releases are no longer immediately available under latest; consumers relying on npm install chdb will get the version only after cross-platform verification completes.

Macroscope summarized 79d3a39.

@ShawnChen-Sirius ShawnChen-Sirius requested a review from Copilot July 1, 2026 00:32
@ShawnChen-Sirius

Copy link
Copy Markdown
Contributor Author

@chibugai, review it

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Updates the release workflow to validate the published chdb artifact (as installed from npm) on clean machines before promoting a stable release to the latest dist-tag, preventing regressions like the absolute-rpath failure in #50.

Changes:

  • Adds an installed-package Vitest suite that imports chdb by package name to exercise optionalDependency resolution, native loading, and subpath exports.
  • Refactors the release workflow into publish → verify (matrix clean installs) → promote (move latest after verification), with stable releases published initially under unverified.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
test/pack/installed.test.mjs New installed-from-npm test suite to validate native loading, basic queries, Session round-trip, and chdb/connection export.
.github/workflows/prebuild-publish.yml Adds verify/promote jobs and changes stable publish dist-tag to unverified until verified across OS/Node matrix.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread test/pack/installed.test.mjs Outdated
ShawnChen-Sirius added a commit to ShawnChen-Sirius/chdb-node that referenced this pull request Jul 1, 2026
…t-connection races

Addresses Copilot review comment on PR chdb-io#64 (test/pack/installed.test.mjs:17).

The suite mixes the standalone default connection (`version()` /
`query()` / `queryAsync()`) with a `Session` that binds its own temp
data directory. libchdb's single-active-data-directory-per-process
constraint means those two cannot coexist mid-flight — if Vitest ever
runs the `it(...)` blocks concurrently (or someone enables
`--sequence.shuffle`), the standalone call can race the Session's
setup/teardown and either surface `version().libchdb === 'unknown'`
or throw on the concurrent `query()`.

Fix: replace `describe(...)` with `describe.sequential(...)` so the
cases run one-at-a-time regardless of Vitest's default concurrency
setting or shuffle flags. Coverage is unchanged; only the ordering
guarantee tightens.

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
wudidapaopao
wudidapaopao previously approved these changes Jul 1, 2026
ShawnChen-Sirius added a commit to ShawnChen-Sirius/chdb-node that referenced this pull request Jul 1, 2026
…t-connection races

Addresses Copilot review comment on PR chdb-io#64 (test/pack/installed.test.mjs:17).

The suite mixes the standalone default connection (`version()` /
`query()` / `queryAsync()`) with a `Session` that binds its own temp
data directory. libchdb's single-active-data-directory-per-process
constraint means those two cannot coexist mid-flight — if Vitest ever
runs the `it(...)` blocks concurrently (or someone enables
`--sequence.shuffle`), the standalone call can race the Session's
setup/teardown and either surface `version().libchdb === 'unknown'`
or throw on the concurrent `query()`.

Fix: replace `describe(...)` with `describe.sequential(...)` so the
cases run one-at-a-time regardless of Vitest's default concurrency
setting or shuffle flags. Coverage is unchanged; only the ordering
guarantee tightens.

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
@ShawnChen-Sirius ShawnChen-Sirius force-pushed the ci/verify-published-package branch 3 times, most recently from b6dd48a to aa35c71 Compare July 1, 2026 08:55
ShawnChen-Sirius and others added 4 commits July 1, 2026 21:17
…omoting to latest

The release workflow built the native addon and ran the suite in the build tree, so it
only ever tested the in-place build, never the artifact users install. A binary with the
build machine's absolute rpath (chdb-io#50) therefore passed CI and broke on every clean host.

Fix: test what users actually get, then gate 'latest' on it.

- test/pack/installed.test.mjs imports `chdb` BY NAME (never the source tree), so it
  exercises the packed files, the @chdb/lib-* binary resolved through optionalDependencies,
  its rpath at the installed location, and the subpath exports. The first `import 'chdb'`
  loads the native addon from where npm put it — exactly the chdb-io#50 failure point.

- prebuild-publish.yml now publishes a stable release to a holding tag ('unverified', and
  prereleases stay on 'next'), then a `verify` matrix (every target platform x Node 18/20/22)
  installs the just-published chdb from npm into a clean dir and runs the installed-package
  tests, and only then does `promote` move 'latest'. If verify fails on any platform, users
  on 'latest' never see the broken release.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ndency + runner layout-detect

@clickhouse/client 1.23.0 was published to npm on 2026-06-29 (GitHub
release tag `client-1.23.0` at commit `70ad405`) — the first stable
release carrying the `connection` injection point from PR #879/#880.
This is the first end-to-end path where users can `npm install chdb
@clickhouse/client` and get a working chDB integration without pinning
a pre-release. Follow-ups:

Marked optional in `peerDependenciesMeta` so users who install `chdb`
without using `chdb/connection` are not forced to pull in
`@clickhouse/client`. Users who DO import from `chdb/connection` and
have an older `@clickhouse/client` will get a clear npm warning
instead of a runtime `Property 'connection' does not exist on type ...`
TypeScript error / `undefined` at construction.

Per the sync-policy table in this file ("After next release: latest
released tag"). `lastSyncedSha` bumped to `70ad405` (the release
tag's commit), `lastSyncedAt` to 2026-07-01.

`client-1.23.0` was cut BEFORE PR #931 (which merged 2026-06-30 as
commit `199f9946` and moved the Vitest config/setup into
`packages/client-node/`). So the release tag still has the OLD
repo-root layout (`vitest.node.setup.ts`, root `test:node:integration`
script), while `main` has the NEW per-package layout.

`runner.mjs` now probes for both:

  - post-#931 (main, and any release cut after #931):
      patch `packages/client-node/vitest.setup.ts`
      run  `npm --prefix packages/client-node run test:integration`
  - pre-#931 (client-1.23.0 release):
      patch `vitest.node.setup.ts` at the repo root
      run  `npm run test:node:integration -- --config vitest.node.config.ts`

Detection is done by probing which setup file exists on disk; cheaper
and more robust than parsing package.json scripts.

  rm -rf .chdb-runner
  npm run build:ts                                   → clean
  npx vitest run test/v3/connection/contract.test.ts → 13/13 ✓
  node tests/clickhouse-js/runner.mjs                → detected upstream layout: pre-931
                                                       patching /vitest.node.setup.ts
                                                       Test Files 26 passed / 2 skipped (28)
                                                       Tests 170 passed / 41 skipped / 0 failed (211)

The 10-test drop vs. the previous main run (180 → 170) is because the
pre-#931 `test:node:integration` script only invokes the client-node
integration suite (client-common's tests are exercised via a separate
script on that layout), while the post-#931 `packages/client-node`
script pulls the shared common tests in. Coverage of `ChdbConnection`
is identical; every previously-passing case that surfaces the adapter
still passes.

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
…t-connection races

Addresses Copilot review comment on PR chdb-io#64 (test/pack/installed.test.mjs:17).

The suite mixes the standalone default connection (`version()` /
`query()` / `queryAsync()`) with a `Session` that binds its own temp
data directory. libchdb's single-active-data-directory-per-process
constraint means those two cannot coexist mid-flight — if Vitest ever
runs the `it(...)` blocks concurrently (or someone enables
`--sequence.shuffle`), the standalone call can race the Session's
setup/teardown and either surface `version().libchdb === 'unknown'`
or throw on the concurrent `query()`.

Fix: replace `describe(...)` with `describe.sequential(...)` so the
cases run one-at-a-time regardless of Vitest's default concurrency
setting or shuffle flags. Coverage is unchanged; only the ordering
guarantee tightens.

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
The test/connection/sanitizer workflows installed with a plain
`npm install --ignore-scripts` and no dependency cache, so every leg of
every push re-fetched the whole tree from the registry with no retry
cushion. That is the class behind the ubuntu-latest ECONNRESET seen on
this PR: with ~18 legs each re-downloading, a single transient socket
reset reddens a job.

- actions/setup-node `cache: npm` on every job, so a warm cache serves
  deps offline and the registry is hit only on a cache miss.
- Workflow-level npm fetch-retry/timeout env so a transient reset retries
  instead of failing the job.

Kept `npm install` (not `npm ci`): the committed lockfile is not
ci-clean because @mastra/core's nested ai@6.x / @ai-sdk / @opentelemetry
subtree is not recorded in it, and the resolution differs across npm
majors, so `npm ci` reds every leg. `npm install` reconciles the
partial lock; the cache + retry are what remove the flake. Syncing the
lockfile for `npm ci` is a separate follow-up.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ShawnChen-Sirius ShawnChen-Sirius force-pushed the ci/verify-published-package branch from aa35c71 to 79d3a39 Compare July 1, 2026 09:20
@wudidapaopao wudidapaopao merged commit fab8787 into chdb-io:main Jul 1, 2026
17 checks passed
ShawnChen-Sirius added a commit that referenced this pull request Jul 7, 2026
…w integrations

Additive minor release on top of 3.1.0 (2026-06-24). No breaking changes;
existing 3.1.0 APIs continue to work unchanged. libchdb bits are unchanged
(chdb-core v26.5.1-rc.1 packaged as @chdb/lib-* 26.5.2 — no republish
needed, the subpackage-matrix job will idempotent-skip).

## What's new

### Layer 3 fluent query builder SDK (#55, #59)

First-class typed fluent query API — Kysely-/Drizzle-style:

    const db = connect({ session })
    const rows = await db
      .from('users')
      .where(r => r.age.gt(18))
      .select('id', 'name')
      .execute()

- `src/layer3/{builder,execute,compile,dialect,introspection,connect,types,codegen}/`
- `chdb-gen-types` CLI — generates row types from a schema (Drizzle /
  Prisma / raw SQL sources)
- `.stream()` terminal with server-side parameter binding
- Arrow C Data Interface support: register JS columnar data as
  `arrowstream()` tables
- 12 new test files under `test/v3/layer3/`

### Cross-language agent-tool contract + 2 framework adapters (#61, #66)

- `chdb/ai-sdk` — Vercel AI SDK tools (`generateText`/`streamText`)
- `chdb/mastra` — Mastra tools + `ChDBVector` (HNSW RAG store) + `ChDBStore`
- Both are thin wrappers over `ChDBTool.call()` from `integrations/agents/`,
  which implements the cross-language contract vendored from `chdb-io/chdb`
  (`chdb/agents/CONTRACT.md`, chdb-io/chdb#597).
- 7 canonical tools: `run_select_query` / `list_databases` / `list_tables` /
  `describe_table` / `get_sample_data` / `list_functions` / `attach_file`
- 5 pillars enforced: engine-level readonly=2 (P1), value-vs-identifier
  separation (P2), truncation flag (P3), error envelope for model
  self-correction (P4), resource/source controls (P5)
- Behavior verified against the shared `conformance/cases.jsonl` fixture

### `chdb/hypequery` DatabaseAdapter (#63, #65)

Lets `@hypequery/clickhouse` query builder run on embedded chDB instead
of a remote ClickHouse server. Uses hypequery's own `substituteParameters`
(imported, not copied) so rendered SQL stays byte-identical to hypequery's
built-in HTTP adapter.

### `chdb/connection` stabilization for @clickhouse/client 1.23.0

- `peerDependency: "@clickhouse/client: >=1.23.0"` (optional) — old client
  triggers a clear npm warning instead of a runtime TS error
- Parity runner switched to track `ClickHouse/clickhouse-js` release tag
  `client-1.23.0` (per the sync-policy table; #52 shipped the initial hook)
- Runner auto-detects upstream Vitest layout (pre-/post-clickhouse-js#931)
- Runner re-synced when clickhouse-js reorganized into a monorepo (#62)

### AI-discovery docs (#60)

- Top-level `AGENTS.md` + `llms-full.txt`
- Per-subpath `AGENTS.md` (`src/layer3/`, `src/connection/`, etc.)
- All packaged in `files` so agents crawling the installed tarball find them

## Fixes / infrastructure

- Bind `null` / `undefined` query params as SQL `\N` (contributor
  @dfrankland, #68) — matches `@clickhouse/client` behavior
- `close()`-mid-flight engine abort + ResultSet teardown race (#56)
- `ChDBVector` HNSW granularity / filter binding / dimension guard (#61)
- Release workflow: publish → `unverified` dist-tag → clean-install verify
  matrix → promote to `latest` (#64). A broken release now never reaches
  `latest` users.
- CI: cache deps + harden npm registry fetch against transient resets

## User-facing installation matrix

```
npm install chdb                                    # base + Layer 3 SDK
npm install chdb @clickhouse/client                 # + chdb/connection
npm install chdb @hypequery/clickhouse              # + chdb/hypequery
npm install chdb ai zod                             # + chdb/ai-sdk
npm install chdb @mastra/core zod                   # + chdb/mastra
```

Native libchdb: chdb-core v26.5.1-rc.1 (packaged as @chdb/lib-* 26.5.2),
unchanged from 3.1.0.

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
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