Skip to content
Merged

Ci #2

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
dd22992
chore: switch reqwest to rustls for cross-compilation support
johnpmitsch Apr 16, 2026
a9c5007
chore: rename napi binary to quicknode-sdk, package to @quicknode/sdk…
johnpmitsch Apr 16, 2026
b7cdbda
chore: add package metadata to sdk-core for crates.io compatibility
johnpmitsch Apr 16, 2026
649050b
chore: add Ruby gemspec for release packaging
johnpmitsch Apr 16, 2026
268b1f3
ci: add release workflow with Rust build job
johnpmitsch Apr 16, 2026
71b81c4
ci: add Python wheel build job (4 Linux targets)
johnpmitsch Apr 16, 2026
0f50639
Small changes
johnpmitsch Apr 16, 2026
bf1105f
ci: fix maturin cross-compilation by specifying python interpreter
johnpmitsch Apr 16, 2026
b571f36
ci: build Python wheels for 3.10-3.13 across all targets (16 builds)
johnpmitsch Apr 16, 2026
977dced
ci: update Python version matrix to 3.11-3.14
johnpmitsch Apr 16, 2026
6b0a1b4
ci: add Node.js build job (4 Linux targets); add ESM support and brow…
johnpmitsch Apr 16, 2026
f0495d1
chore: fix sdk.mjs named exports; document sdk.mjs update requirement…
johnpmitsch Apr 16, 2026
2512b0f
ci: strip debug symbols from node .node binaries to reduce artifact size
johnpmitsch Apr 16, 2026
2e9203e
ci: strip debug symbols from Python wheels
johnpmitsch Apr 16, 2026
778c6b6
ci: fix node cross-compilation by passing --cross-compile to napi build
johnpmitsch Apr 16, 2026
f08a0d0
Revert "ci: fix node cross-compilation by passing --cross-compile to …
johnpmitsch Apr 16, 2026
28853dd
ci: explicitly pass --cross-compile to napi build for cross targets
johnpmitsch Apr 16, 2026
cae5c55
ci: remove unsupported --cross-compile flag from napi build
johnpmitsch Apr 16, 2026
182013e
ci: remove cargo-zigbuild from node job (napi-rs uses zig directly)
johnpmitsch Apr 16, 2026
f6d12ad
ci: use zig objcopy to strip cross-compiled node binaries
johnpmitsch Apr 16, 2026
d13d2e6
ci: install llvm for llvm-strip on cross-compiled node binaries
johnpmitsch Apr 16, 2026
996c643
ci: add Ruby gem build job (4 Linux targets)
johnpmitsch Apr 16, 2026
d10dd0f
ci: remove musl targets from Ruby job (cdylib incompatible with musl)
johnpmitsch Apr 16, 2026
f38d066
chore: add just release recipe for version management
johnpmitsch Apr 16, 2026
62c542f
ci: only trigger release workflow on version tags
johnpmitsch Apr 16, 2026
e9d1cfc
chore: update package-lock.json in release recipe
johnpmitsch Apr 16, 2026
3887d1f
chore: cd back after npm install in release recipe
johnpmitsch Apr 16, 2026
35408e1
chore: regenerate uv.lock in release recipe
johnpmitsch Apr 16, 2026
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
246 changes: 246 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
name: Release

on:
push:
tags:
- 'v*'

jobs:
build-rust:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: dtolnay/rust-toolchain@stable

- name: Package crate
run: cargo package -p sdk-core --allow-dirty

- uses: actions/upload-artifact@v4
with:
name: rust-crate
path: target/package/sdk-core-*.crate

build-python:
strategy:
fail-fast: false
matrix:
python-version: ['3.11', '3.12', '3.13', '3.14']
target:
- x86_64-unknown-linux-gnu
- aarch64-unknown-linux-gnu
- x86_64-unknown-linux-musl
- aarch64-unknown-linux-musl
# Placeholder for future macOS support:
# - aarch64-apple-darwin
include:
- target: x86_64-unknown-linux-gnu
cross: false
- target: aarch64-unknown-linux-gnu
cross: true
- target: x86_64-unknown-linux-musl
cross: true
- target: aarch64-unknown-linux-musl
cross: true
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}

- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install maturin
run: pip install "maturin>=1.5,<2.0"

- name: Install Zig
if: matrix.cross
uses: goto-bus-stop/setup-zig@v2

- name: Build wheel
run: |
maturin build --release \
--strip \
--target ${{ matrix.target }} \
${{ matrix.cross && '--zig' || '' }} \
-i python${{ matrix.python-version }} \
--out dist/

- name: Build sdist
if: matrix.target == 'x86_64-unknown-linux-gnu' && matrix.python-version == '3.11'
run: maturin sdist --out dist/

- uses: actions/upload-artifact@v4
with:
name: python-${{ matrix.target }}-py${{ matrix.python-version }}
path: dist/*

build-node:
strategy:
fail-fast: false
matrix:
target:
- x86_64-unknown-linux-gnu
- aarch64-unknown-linux-gnu
- x86_64-unknown-linux-musl
- aarch64-unknown-linux-musl
# Placeholder for future macOS support:
# - aarch64-apple-darwin
include:
- target: x86_64-unknown-linux-gnu
cross: false
- target: aarch64-unknown-linux-gnu
cross: true
- target: x86_64-unknown-linux-musl
cross: true
- target: aarch64-unknown-linux-musl
cross: true
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}

- uses: actions/setup-node@v4
with:
node-version: '20'

- name: Install Zig
if: matrix.cross
uses: goto-bus-stop/setup-zig@v2

- name: Install npm dependencies
working-directory: npm
run: npm install

- name: Build native module
working-directory: npm
run: |
npx napi build --release \
--platform \
--target ${{ matrix.target }} \
--cargo-cwd ../crates/node
Comment thread
cursor[bot] marked this conversation as resolved.

- name: Strip debug symbols
run: |
if [ "${{ matrix.cross }}" = "true" ]; then
sudo apt-get install -y llvm
llvm-strip npm/index.*.node
else
strip npm/index.*.node
fi

- uses: actions/upload-artifact@v4
with:
name: node-${{ matrix.target }}
path: npm/index.*.node
Comment thread
cursor[bot] marked this conversation as resolved.

build-ruby:
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-unknown-linux-gnu
cross: false
gem_platform: x86_64-linux
- target: aarch64-unknown-linux-gnu
cross: true
gem_platform: aarch64-linux
# musl targets are excluded: Rust cdylib is incompatible with musl (no dynamic linker).
# Users on musl Linux (e.g. Alpine) will use the source gem which compiles on install.
# Placeholder for future macOS support:
# - target: aarch64-apple-darwin
# cross: false
# gem_platform: arm64-darwin
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}

- uses: ruby/setup-ruby@v1
with:
ruby-version: '3.3'

- name: Install Zig
if: matrix.cross
uses: goto-bus-stop/setup-zig@v2

- name: Install cargo-zigbuild
if: matrix.cross
run: cargo install cargo-zigbuild

- name: Build native extension (cross)
if: matrix.cross
run: |
cargo zigbuild --release -p sdk-ruby --target ${{ matrix.target }}
cp target/${{ matrix.target }}/release/libquicknode_sdk.so ruby/lib/quicknode_sdk.so

- name: Build native extension (native)
if: '!matrix.cross'
run: |
cargo build --release -p sdk-ruby
cp target/release/libquicknode_sdk.so ruby/lib/quicknode_sdk.so

- name: Strip debug symbols
run: |
if [ "${{ matrix.cross }}" = "true" ]; then
sudo apt-get install -y llvm
llvm-strip ruby/lib/quicknode_sdk.so
else
strip ruby/lib/quicknode_sdk.so
fi

- name: Build platform gem
working-directory: ruby
run: |
ruby -e "
spec = Gem::Specification.load('quicknode_sdk.gemspec')
spec.platform = Gem::Platform.new('${{ matrix.gem_platform }}')
spec.extensions = []
spec.files += ['lib/quicknode_sdk.so']
File.write('quicknode_sdk_platform.gemspec', spec.to_ruby)
"
gem build quicknode_sdk_platform.gemspec
rm quicknode_sdk_platform.gemspec

- name: Build source gem
if: matrix.target == 'x86_64-unknown-linux-gnu'
working-directory: ruby
run: gem build quicknode_sdk.gemspec

- uses: actions/upload-artifact@v4
with:
name: ruby-${{ matrix.target }}
path: ruby/*.gem

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:
- uses: actions/checkout@v4

- uses: actions/download-artifact@v4
with:
path: artifacts/
merge-multiple: true

- uses: softprops/action-gh-release@v2
with:
files: artifacts/**/*
generate_release_notes: true
draft: false
prerelease: ${{ contains(github.ref, '-rc') || contains(github.ref, '-beta') }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ Core clients are tested using mocked API calls with wiremock. All functions maki
- When adding a new type with `#[cfg_attr(feature = "node", napi(object))]`, also add it to the named `export type { ... }` block in `npm/sdk.d.ts` — this is the user-facing type file and is not auto-updated by napi-rs
- When adding a new `#[napi(string_enum)]` Rust enum, it generates a TypeScript `const enum` in `npm/index.d.ts`. In `npm/sdk.d.ts`, these must be re-exported using a regular `export { ... }` (not `export type { ... }`), otherwise TypeScript consumers cannot use them as values (e.g., `StreamDataset.Block`)
- When updating `sdk.js` wrapper methods, verify the argument types match the underlying napi-rs constructor/method signature (object vs primitive)
- When adding a new export to `sdk.js`, also add it to the named exports in `npm/sdk.mjs` — ESM named exports cannot be spread dynamically and must be listed explicitly
- `python/sdk/__init__.pyi` is overwritten by `just python-build` — edit `init_manual_override.pyi` instead

### Security
Expand Down
14 changes: 14 additions & 0 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,17 @@ test:

lint:
cargo clippy --workspace --lib --tests -- -D warnings

# Bump version across all manifests, commit, and tag for release.
# Usage: just release 0.2.0
release version:
sed -i.bak 's/^version = ".*"/version = "{{version}}"/' Cargo.toml && rm Cargo.toml.bak
sed -i.bak 's/^version = ".*"/version = "{{version}}"/' pyproject.toml && rm pyproject.toml.bak
uv lock
sed -i.bak 's/"version": ".*"/"version": "{{version}}"/' npm/package.json && rm npm/package.json.bak
cd npm && npm install --package-lock-only && cd ..
sed -i.bak 's/s\.version *= *".*"/s.version = "{{version}}"/' ruby/quicknode_sdk.gemspec && rm ruby/quicknode_sdk.gemspec.bak
git add Cargo.toml pyproject.toml uv.lock npm/package.json npm/package-lock.json ruby/quicknode_sdk.gemspec
git commit -m "chore: release v{{version}}"
git tag v{{version}}
@echo "Tagged v{{version}}. Push with: git push && git push origin v{{version}}"
Comment thread
cursor[bot] marked this conversation as resolved.
5 changes: 4 additions & 1 deletion crates/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ version.workspace = true
edition.workspace = true
license.workspace = true
description = "Core library for quicknode sdk"
repository = "https://github.com/quiknode-labs/sdk"
keywords = ["quicknode", "blockchain", "web3", "sdk"]
categories = ["api-bindings", "web-programming"]

[lints]
workspace = true
Expand All @@ -19,7 +22,7 @@ extension-module = ["pyo3/extension-module"]
thiserror = "1.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
reqwest = { version = "0.13.2", features = ["json", "query"] }
reqwest = { version = "0.13.2", default-features = false, features = ["json", "query", "rustls", "http2"] }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Dropped system-proxy feature disables proxy environment variable support

Medium Severity

Switching reqwest to default-features = false drops the system-proxy default feature (alongside charset). The developer re-added rustls and http2 explicitly but missed system-proxy, which enables reading HTTP_PROXY/HTTPS_PROXY/NO_PROXY environment variables via hyper-util. The SDK's HTTP client will now silently ignore system proxy configuration, breaking usage in corporate or proxy-dependent environments.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 977dced. Configure here.

pyo3 = { workspace = true, optional = true, features = ["experimental-async"] }
pyo3-async-runtimes = { workspace = true, optional = true, features = ["tokio-runtime"] }
napi = { workspace = true, optional = true, features = ["async", "tokio_rt"] }
Expand Down
2 changes: 1 addition & 1 deletion crates/node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "sdk-node"
version.workspace = true
edition.workspace = true
license.workspace = true
description = "Node.js bindings for my-sdk"
description = "Node.js bindings for quicknode sdk"

[lints]
workspace = true
Expand Down
9 changes: 9 additions & 0 deletions npm/browser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Native Node.js bindings (.node files compiled from Rust) cannot run in
// browser environments — they are binary extensions that require the Node.js
// runtime and OS-level dynamic linking. Bundlers (Webpack, Vite, etc.) that
// 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. ' +
'This package requires Node.js.'
);
2 changes: 1 addition & 1 deletion npm/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -953,7 +953,7 @@ export interface Webhook {
status: string
network: string
createdAt: string
updatedAt: string
updatedAt?: string
templateId?: string
notificationEmail?: string
/** Destination-specific configuration as a JSON string. */
Expand Down
4 changes: 2 additions & 2 deletions npm/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 14 additions & 5 deletions npm/package.json
Original file line number Diff line number Diff line change
@@ -1,24 +1,33 @@
{
"name": "@quicknode/sdk",
"name": "@quicknode/sdk-next",
"version": "0.1.0",
"description": "Quicknode SDK",
"main": "sdk.js",
"types": "sdk.d.ts",
"exports": {
".": {
"import": "./sdk.mjs",
"require": "./sdk.js",
"types": "./sdk.d.ts"
}
},
"browser": "./browser.js",
"files": [
"index.js",
"index.d.ts",
"sdk.js",
"sdk.d.ts",
"sdk.mjs",
"browser.js",
"*.node"
],
"napi": {
"binaryName": "my-sdk",
"binaryName": "quicknode-sdk",
"targets": [
"x86_64-apple-darwin",
"aarch64-apple-darwin",
"x86_64-unknown-linux-gnu",
"aarch64-unknown-linux-gnu",
"x86_64-pc-windows-msvc"
"x86_64-unknown-linux-musl",
"aarch64-unknown-linux-musl"
]
},
"scripts": {
Expand Down
Loading