From c969fd8802e7df1b8d5194f9db63c89174157395 Mon Sep 17 00:00:00 2001 From: John Mitsch Date: Tue, 21 Apr 2026 15:37:25 -0400 Subject: [PATCH 1/2] NPM release workflow --- .github/workflows/publish-npm.yml | 77 +++++++++++++++++++++++++++++++ .github/workflows/release.yml | 10 ++-- README.md | 72 ++++++++++++++++++++++++----- npm/browser.js | 2 +- npm/package-lock.json | 8 ++-- npm/package.json | 7 +-- 6 files changed, 150 insertions(+), 26 deletions(-) create mode 100644 .github/workflows/publish-npm.yml diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml new file mode 100644 index 0000000..b2361d2 --- /dev/null +++ b/.github/workflows/publish-npm.yml @@ -0,0 +1,77 @@ +name: Publish npm + +on: + workflow_dispatch: + inputs: + tag: + description: 'Git tag to publish (e.g. v3.0.0-alpha.4)' + required: true + npm_tag: + description: 'npm dist-tag (next, latest, beta)' + required: true + default: 'next' + +jobs: + publish: + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ inputs.tag }} + + - uses: actions/setup-node@v4 + with: + node-version: '20' + registry-url: 'https://registry.npmjs.org' + + - name: Download node .node artifacts from GitHub release + run: | + mkdir -p npm/artifacts + gh release download "${{ inputs.tag }}" \ + --pattern 'index.*.node' \ + --dir npm/artifacts + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Verify required binaries are present + run: | + required=( + index.linux-x64-gnu.node + index.linux-arm64-gnu.node + index.linux-x64-musl.node + index.linux-arm64-musl.node + index.darwin-arm64.node + ) + for f in "${required[@]}"; do + test -f "npm/artifacts/$f" || { echo "Missing $f"; exit 1; } + done + + - name: Move binaries into npm/ + working-directory: npm + run: mv artifacts/*.node . && rmdir artifacts + + - name: Install npm deps + working-directory: npm + run: npm ci + + - name: Assemble per-platform sub-packages + working-directory: npm + run: npx napi prepublish --skip-gh-release + + - name: Publish per-platform packages + working-directory: npm + run: | + for pkg_dir in npm/*/; do + echo "Publishing $pkg_dir" + (cd "$pkg_dir" && npm publish --access public --tag "${{ inputs.npm_tag }}") + done + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Publish main package + working-directory: npm + run: npm publish --access public --tag "${{ inputs.npm_tag }}" + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 420d651..0c2d295 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,9 +1,8 @@ name: Release on: - push: - tags: - - 'v*' + release: + types: [published] jobs: build-rust: @@ -225,7 +224,6 @@ jobs: release: needs: [build-rust, build-python, build-node, build-ruby] runs-on: ubuntu-latest - if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') permissions: contents: write steps: @@ -239,8 +237,6 @@ jobs: - uses: softprops/action-gh-release@v2 with: files: artifacts/**/* - generate_release_notes: true - draft: false - prerelease: ${{ contains(github.ref, '-rc') || contains(github.ref, '-beta') }} + tag_name: ${{ github.event.release.tag_name }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/README.md b/README.md index c18221d..0c889f3 100644 --- a/README.md +++ b/README.md @@ -3459,25 +3459,75 @@ The first publish claims the `quicknode-sdk` name permanently. Published version #### All bindings together (Python / Node / Ruby) -macOS (Apple Silicon) artifacts are built locally rather than on GitHub Actions to avoid the ~10× runner cost. Linux artifacts are still built by CI on tag push. +macOS (Apple Silicon) artifacts are built locally rather than on GitHub Actions to avoid the ~10× runner cost. Linux artifacts are built by CI when a GitHub release is published. -```bash -# 1. Bump versions, commit, tag -just release 0.2.0 +1. **Bump versions and commit:** + ```bash + just release 0.2.0 + git push + ``` -# 2. Push -git push && git push origin v0.2.0 +2. **Create the GitHub release** via the GitHub UI: + - **Releases → Draft a new release**. + - **Choose a tag** → type `v0.2.0` → **Create new tag on publish**. + - Target branch: `main`. + - Fill in title and notes (or click **Generate release notes**). + - Click **Publish release**. -# 3. Wait for CI to finish and publish the GitHub release with Linux artifacts. + This creates + pushes the tag and triggers `.github/workflows/release.yml`, which builds Linux artifacts and attaches them to the release. -# 4. Build macOS arm64 artifacts locally and append them to the release -just macos-build-and-publish 0.2.0 -``` +3. **Build macOS arm64 artifacts locally and append them to the release:** + ```bash + just macos-build-and-publish 0.2.0 + ``` -Step 4 requires the [`gh` CLI](https://cli.github.com/) authenticated to the repo. Intel macOS (`x86_64-apple-darwin`) is not shipped — users on Intel Macs install from source. +Step 3 requires the [`gh` CLI](https://cli.github.com/) authenticated to the repo. Intel macOS (`x86_64-apple-darwin`) is not shipped — users on Intel Macs install from source. `just release` does **not** bump the Rust crate version (that's managed separately in `crates/core/Cargo.toml`). If you want the Rust crate to move in lockstep with a binding release, bump it manually in the same commit. +#### npm publish (`@quicknode/sdk`) + +The Node package is published to npm as `@quicknode/sdk`. During the 3.x pre-release period, publishes use the `next` dist-tag so `npm install @quicknode/sdk` continues to resolve to the legacy 2.x release while `npm install @quicknode/sdk@next` pulls the rewrite. + +The npm publish uses [napi-rs's multi-package layout](https://napi.rs/docs/deep-dive/release): one main package plus per-platform sub-packages (`@quicknode/sdk-linux-x64-gnu`, `@quicknode/sdk-darwin-arm64`, etc.) declared as `optionalDependencies`. Publishing is triggered manually via a GitHub Actions workflow so the macOS binary (built locally) can be uploaded to the GitHub release before publish. + +**One-time setup:** +- An `NPM_TOKEN` with publish access to `@quicknode/sdk*` packages must be set as a GitHub Actions secret. Use an npm Automation token. + +**Per-release flow:** + +1. **Bump the npm version** in `npm/package.json` (e.g. `3.0.0-alpha.4` → `3.0.0-alpha.5`), commit, and push to `main`. + +2. **Create the GitHub release** via the GitHub UI: + - Go to **Releases → Draft a new release**. + - Click **Choose a tag**, type the new tag (e.g. `v3.0.0-alpha.5`), and select **Create new tag on publish**. + - Target branch: `main`. + - Fill in the title and release notes (or click **Generate release notes**). + - Click **Publish release**. + + Publishing the release creates + pushes the tag, which triggers `.github/workflows/release.yml`. CI builds the Linux `.node` artifacts and attaches them to the release you just created. + +3. **Wait for `release.yml` to finish.** Confirm the four Linux `index.*.node` artifacts are attached to the release. + +4. **Build and upload the macOS arm64 binary** locally (Apple Silicon Mac required): + ```bash + just node-build + gh release upload v3.0.0-alpha.5 npm/index.darwin-arm64.node + ``` + +5. **Trigger the publish workflow.** From the GitHub UI: **Actions → Publish npm → Run workflow**, then enter the tag (`v3.0.0-alpha.5`) and npm dist-tag (`next`). Or via CLI: + ```bash + gh workflow run publish-npm.yml -f tag=v3.0.0-alpha.5 -f npm_tag=next + ``` + +6. **Verify.** + ```bash + npm view @quicknode/sdk dist-tags + # Expected: next: 3.0.0-alpha.5, latest: 2.6.0 (unchanged) + ``` + +Users can install the pre-release with `npm install @quicknode/sdk@next`. + ## License MIT diff --git a/npm/browser.js b/npm/browser.js index 47bf184..5494451 100644 --- a/npm/browser.js +++ b/npm/browser.js @@ -4,6 +4,6 @@ // encounter this package in a browser target will load this shim instead, // producing a clear error rather than a cryptic binary load failure. throw new Error( - '@quicknode/sdk-next does not support browser environments. ' + + '@quicknode/sdk does not support browser environments. ' + 'This package requires Node.js.' ); diff --git a/npm/package-lock.json b/npm/package-lock.json index acac2f0..fd44ef4 100644 --- a/npm/package-lock.json +++ b/npm/package-lock.json @@ -1,12 +1,12 @@ { - "name": "@quicknode/sdk-next", - "version": "0.1.0", + "name": "@quicknode/sdk", + "version": "3.0.0-alpha.4", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "@quicknode/sdk-next", - "version": "0.1.0", + "name": "@quicknode/sdk", + "version": "3.0.0-alpha.4", "license": "MIT", "devDependencies": { "@napi-rs/cli": "^2.18.0", diff --git a/npm/package.json b/npm/package.json index 51359a4..a08bee6 100644 --- a/npm/package.json +++ b/npm/package.json @@ -1,6 +1,6 @@ { - "name": "@quicknode/sdk-next", - "version": "0.1.0", + "name": "@quicknode/sdk", + "version": "3.0.0-alpha.4", "description": "Quicknode SDK", "main": "sdk.js", "types": "sdk.d.ts", @@ -27,7 +27,8 @@ "x86_64-unknown-linux-gnu", "aarch64-unknown-linux-gnu", "x86_64-unknown-linux-musl", - "aarch64-unknown-linux-musl" + "aarch64-unknown-linux-musl", + "aarch64-apple-darwin" ] }, "scripts": { From d703a2d30af8555754064b77081011cc056318c5 Mon Sep 17 00:00:00 2001 From: John Mitsch Date: Tue, 21 Apr 2026 15:47:04 -0400 Subject: [PATCH 2/2] update wf path --- .github/workflows/publish-npm.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml index b2361d2..2336709 100644 --- a/.github/workflows/publish-npm.yml +++ b/.github/workflows/publish-npm.yml @@ -61,9 +61,9 @@ jobs: run: npx napi prepublish --skip-gh-release - name: Publish per-platform packages - working-directory: npm + working-directory: npm/npm run: | - for pkg_dir in npm/*/; do + for pkg_dir in */; do echo "Publishing $pkg_dir" (cd "$pkg_dir" && npm publish --access public --tag "${{ inputs.npm_tag }}") done