Merge pull request #954 from ClickHouse/main #7
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
| name: "publish: client" | |
| # Publish + release for @clickhouse/client (the Node.js client). | |
| # | |
| # Split out of the former all-in-one publish.yml so each client package | |
| # publishes on its own. Two triggers, like the standalone-package workflows: | |
| # - push to `release` -> publishes the "head" pre-release tag (internal beta). | |
| # - manual workflow_dispatch -> publishes the "latest" tag and pushes the | |
| # release git tag. The `main` branch never publishes. | |
| # Both use npm OIDC authentication with provenance, and both deploy through the | |
| # protected `npm-publish` environment (release branch only + manual approval). | |
| # | |
| # The push trigger is path-scoped to this package's own sources, the shared | |
| # common sources it bundles via the `src/common` symlink | |
| # (packages/client-common/src), and the repo-root files its published tarball | |
| # depends on (README/LICENSE, the bundled skills/, and the shared | |
| # lockfile/tsconfig). So a change to only one client no longer republishes the | |
| # others, but a change to the shared common sources publishes a new head build | |
| # for every client that bundles them. | |
| # | |
| # Before publishing, a smoke test packs the freshly built package into a | |
| # tarball, installs it into a throwaway app, and runs ESM + CJS checks against | |
| # it (.scripts/smoke_test_pack.sh). After a successful publish, the `e2e` job | |
| # waits for the version to surface on the npm registry, installs that exact | |
| # version into a tiny downstream project, and verifies it is usable. | |
| permissions: | |
| contents: read | |
| id-token: write # Required for npm OIDC authentication and provenance | |
| concurrency: | |
| # event_name separates the head (push) and latest (workflow_dispatch) runs so | |
| # a manual publish never cancels an in-progress head publish (or vice versa). | |
| group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| on: | |
| # for the latest workflow | |
| workflow_dispatch: | |
| # for the head workflow | |
| push: | |
| branches: | |
| - release | |
| paths: | |
| - "packages/client-node/**" | |
| # The Node client bundles the common sources via the src/common symlink. | |
| - "packages/client-common/**" | |
| - "skills/**" | |
| - "package.json" | |
| - "package-lock.json" | |
| - "tsconfig.base.json" | |
| - "README.md" | |
| - "LICENSE" | |
| - ".github/workflows/publish-client.yml" | |
| env: | |
| # Network resilience: npm's default of 2 fetch retries is not enough for | |
| # the transient registry errors (ECONNRESET) we regularly hit in CI. | |
| NPM_CONFIG_FETCH_RETRIES: "5" | |
| NPM_CONFIG_FETCH_RETRY_MINTIMEOUT: "10000" | |
| NPM_CONFIG_FETCH_RETRY_MAXTIMEOUT: "60000" | |
| NPM_CONFIG_FETCH_TIMEOUT: "600000" | |
| jobs: | |
| head: | |
| name: "Publish @clickhouse/client (head)" | |
| if: github.ref == 'refs/heads/release' && github.event_name == 'push' | |
| runs-on: ubuntu-latest | |
| environment: npm-publish | |
| outputs: | |
| version: ${{ steps.version.outputs.version }} | |
| packages: "@clickhouse/client" | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 | |
| with: | |
| node-version: 24 | |
| registry-url: "https://registry.npmjs.org" | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Set head pre-release version | |
| id: version | |
| run: | | |
| BASE_VERSION=$(node -p "require('./packages/client-node/package.json').version") | |
| HEAD_VERSION="${BASE_VERSION}-head.${GITHUB_SHA::7}.${GITHUB_RUN_ATTEMPT}" | |
| echo "Setting version to: $HEAD_VERSION" | |
| npm --workspace @clickhouse/client version --no-git-tag-version "$HEAD_VERSION" | |
| echo "export default \"$HEAD_VERSION\";" > packages/client-node/src/version.ts | |
| echo "version=$HEAD_VERSION" >> "$GITHUB_OUTPUT" | |
| - name: Build the package | |
| run: npm --workspace @clickhouse/client run build | |
| - name: Smoke test the packed tarball | |
| run: .scripts/smoke_test_pack.sh @clickhouse/client | |
| - name: Publish @clickhouse/client with head tag | |
| run: | | |
| npm --workspace @clickhouse/client publish \ | |
| --access public \ | |
| --provenance \ | |
| --tag head | |
| publish: | |
| name: "Publish @clickhouse/client" | |
| if: github.ref == 'refs/heads/release' && github.event_name == 'workflow_dispatch' | |
| runs-on: ubuntu-latest | |
| environment: npm-publish | |
| permissions: | |
| contents: write # Required to push the release git tag | |
| id-token: write # Required for npm OIDC authentication and provenance | |
| outputs: | |
| version: ${{ steps.version.outputs.version }} | |
| packages: "@clickhouse/client" | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 | |
| with: | |
| node-version: 24 | |
| registry-url: "https://registry.npmjs.org" | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Get the release version | |
| id: version | |
| run: | | |
| BASE_VERSION=$(node -p "require('./packages/client-node/package.json').version") | |
| echo "Using version: $BASE_VERSION" | |
| echo "version=$BASE_VERSION" >> "$GITHUB_OUTPUT" | |
| - name: Build the package | |
| run: npm --workspace @clickhouse/client run build | |
| - name: Smoke test the packed tarball | |
| run: .scripts/smoke_test_pack.sh @clickhouse/client | |
| - name: Publish @clickhouse/client to the latest tag (implicit) | |
| run: | | |
| npm --workspace @clickhouse/client publish \ | |
| --access public \ | |
| --provenance | |
| - name: Create and push release git tag | |
| env: | |
| RELEASE_VERSION: ${{ steps.version.outputs.version }} | |
| run: .scripts/push_release_tag.sh "client-${RELEASE_VERSION}" | |
| e2e: | |
| name: e2e (node ${{ matrix.node }}) | |
| needs: [head, publish] | |
| # Runs whether the published version came from the head job or the manual | |
| # latest publish. | |
| if: | | |
| always() && | |
| (needs.head.result == 'success' || needs.publish.result == 'success') | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: true | |
| matrix: | |
| node: [20, 22, 24, 26] | |
| defaults: | |
| run: | |
| working-directory: tests/e2e/install | |
| env: | |
| PUBLISHED_VERSION: ${{ needs.head.outputs.version || needs.publish.outputs.version }} | |
| PUBLISHED_PACKAGES: ${{ needs.head.outputs.packages || needs.publish.outputs.packages }} | |
| steps: | |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | |
| - name: Start ClickHouse (stable) in Docker | |
| uses: hoverkraft-tech/compose-action@11beaa1c2dae4e8ed7b1665aa074723b6cecb0e4 # v3.0.0 | |
| env: | |
| CLICKHOUSE_VERSION: latest | |
| with: | |
| compose-file: "docker-compose.yml" | |
| down-flags: "--volumes" | |
| - name: Setup NodeJS ${{ matrix.node }} | |
| uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 | |
| with: | |
| node-version: ${{ matrix.node }} | |
| registry-url: "https://registry.npmjs.org" | |
| - name: Wait for ${{ env.PUBLISHED_VERSION }} to be available on npm | |
| run: | | |
| set -euo pipefail | |
| if [ -z "${PUBLISHED_VERSION}" ]; then | |
| echo "PUBLISHED_VERSION is empty; cannot wait for npm publication." >&2 | |
| exit 1 | |
| fi | |
| if [ -z "${PUBLISHED_PACKAGES}" ]; then | |
| echo "PUBLISHED_PACKAGES is empty; cannot wait for npm publication." >&2 | |
| exit 1 | |
| fi | |
| read -r -a packages <<< "${PUBLISHED_PACKAGES}" | |
| # Poll the registry for up to ~5 minutes per package. New versions | |
| # usually surface in seconds, but the registry CDN can lag. | |
| max_attempts=60 | |
| sleep_seconds=5 | |
| for pkg in "${packages[@]}"; do | |
| echo "Waiting for ${pkg}@${PUBLISHED_VERSION} to be available on npm..." | |
| attempt=1 | |
| while true; do | |
| if npm view "${pkg}@${PUBLISHED_VERSION}" version >/dev/null 2>&1; then | |
| echo " ${pkg}@${PUBLISHED_VERSION} is available." | |
| break | |
| fi | |
| if [ "$attempt" -ge "$max_attempts" ]; then | |
| echo "Timed out waiting for ${pkg}@${PUBLISHED_VERSION} on npm" >&2 | |
| exit 1 | |
| fi | |
| echo " attempt ${attempt}/${max_attempts}: not available yet, sleeping ${sleep_seconds}s..." | |
| attempt=$((attempt + 1)) | |
| sleep "$sleep_seconds" | |
| done | |
| done | |
| - name: Install dependencies | |
| run: npm install | |
| - name: Install the packages at the published version | |
| run: | | |
| set -euo pipefail | |
| read -r -a packages <<< "${PUBLISHED_PACKAGES}" | |
| specs=() | |
| for pkg in "${packages[@]}"; do | |
| specs+=("${pkg}@${PUBLISHED_VERSION}") | |
| done | |
| npm install "${specs[@]}" | |
| - name: Type check | |
| run: npx tsc --noEmit | |
| - name: Run client code | |
| env: | |
| EXPECTED_VERSION: ${{ env.PUBLISHED_VERSION }} | |
| run: node src/index.ts | |
| # End-to-end integration against the installed package and a live | |
| # single-node ClickHouse (started above): create/insert/select, stream, | |
| # and confirm a bad query surfaces as a ClickHouseError. | |
| - name: Run integration tests against the published package | |
| run: node src/integration.ts |