From 1295b63e1fbda37fad8e4a7c5085bdf1cef6f4ff Mon Sep 17 00:00:00 2001 From: kingchenc Date: Thu, 21 May 2026 20:35:18 +0200 Subject: [PATCH] Wire release pipeline to crates.io, PyPI, and npm On every v* tag push the release workflow now publishes the project to all three public registries in parallel: - crates.io: wickra-core then wickra-data then wickra, with a 45-second sleep between each so the registry index can refresh before the next publish step asserts the previous version is available. - PyPI: maturin-action builds wheels for Linux x86_64 + aarch64, macOS x86_64 + aarch64, and Windows x64, plus an sdist; all artefacts upload to PyPI via MATURIN_PYPI_TOKEN. - npm: napi-rs builds a native binary per platform (linux-x64-gnu, darwin-x64, darwin-arm64, win32-x64-msvc), publishes each as its own platform package, then publishes the main `wickra` meta-package that resolves to the right platform at install time. - WASM: wasm-pack builds the bundler-target package and publishes it as `wickra-wasm` on npm, with the auto-generated package.json enriched with the author/repo/license metadata. Package metadata was unified so all targets point at kingchenc/wickra on GitHub; the Node binding is now plain `wickra` (the @wickra/ scope was unnecessary because the bare name was free). README install table updated to match. --- .github/workflows/release.yml | 233 +++++++++++++++++++++++++++------ Cargo.toml | 4 +- README.md | 4 +- bindings/node/package.json | 12 +- bindings/python/pyproject.toml | 6 +- bindings/wasm/Cargo.toml | 5 + 6 files changed, 212 insertions(+), 52 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1852e8aa..6082c71d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,83 +2,230 @@ name: Release on: push: - tags: - - "v*" + tags: ["v*"] workflow_dispatch: +env: + CARGO_TERM_COLOR: always + jobs: - build-wheels: - name: Wheels ${{ matrix.os }} ${{ matrix.target }} - runs-on: ${{ matrix.os }} + # -------------------------------------------------------------------------- + # crates.io: three crates in dependency order + # -------------------------------------------------------------------------- + cargo-publish: + name: Publish to crates.io + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + + - name: Publish wickra-core + run: cargo publish -p wickra-core --token "$CARGO_REGISTRY_TOKEN" + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + + - name: Wait for crates.io index to refresh + run: sleep 45 + + - name: Publish wickra-data + run: cargo publish -p wickra-data --token "$CARGO_REGISTRY_TOKEN" + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + + - name: Wait for crates.io index to refresh + run: sleep 45 + + - name: Publish wickra + run: cargo publish -p wickra --token "$CARGO_REGISTRY_TOKEN" + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + + # -------------------------------------------------------------------------- + # PyPI: cross-platform wheels + sdist + # -------------------------------------------------------------------------- + python-wheels: + name: Build wheels (${{ matrix.target }} on ${{ matrix.os }}) strategy: fail-fast: false matrix: include: - - os: ubuntu-latest - target: x86_64 - - os: ubuntu-latest - target: aarch64 - - os: macos-latest - target: x86_64 - - os: macos-latest - target: aarch64 - - os: windows-latest - target: x64 + - { os: ubuntu-latest, target: x86_64, manylinux: auto } + - { os: ubuntu-latest, target: aarch64, manylinux: auto } + - { os: macos-latest, target: x86_64, manylinux: auto } + - { os: macos-latest, target: aarch64, manylinux: auto } + - { os: windows-latest, target: x64, manylinux: auto } + runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - - - name: Set up Python - uses: actions/setup-python@v5 + - uses: actions/setup-python@v5 with: python-version: "3.11" - - - name: Build wheels - uses: PyO3/maturin-action@v1 + - uses: PyO3/maturin-action@v1 with: working-directory: bindings/python target: ${{ matrix.target }} args: --release --strip --out dist - sccache: "true" - manylinux: auto - - - name: Upload wheels - uses: actions/upload-artifact@v4 + manylinux: ${{ matrix.manylinux }} + - uses: actions/upload-artifact@v4 with: name: wheels-${{ matrix.os }}-${{ matrix.target }} - path: bindings/python/dist/ + path: bindings/python/dist/* - sdist: - name: Source distribution + python-sdist: + name: Build Python sdist runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - - name: Build sdist - uses: PyO3/maturin-action@v1 + - uses: PyO3/maturin-action@v1 with: working-directory: bindings/python command: sdist args: --out dist - - uses: actions/upload-artifact@v4 with: - name: sdist - path: bindings/python/dist/ + name: wheels-sdist + path: bindings/python/dist/* - publish: + python-publish: name: Publish to PyPI - needs: [build-wheels, sdist] + needs: [python-wheels, python-sdist] runs-on: ubuntu-latest - if: startsWith(github.ref, 'refs/tags/v') - permissions: - id-token: write steps: - uses: actions/download-artifact@v4 with: path: dist + pattern: wheels-* merge-multiple: true - - name: Publish to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 + - name: Upload to PyPI + uses: PyO3/maturin-action@v1 with: - packages-dir: dist/ + command: upload + args: --skip-existing dist/* + env: + MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }} + + # -------------------------------------------------------------------------- + # npm: per-platform native binaries + main meta-package + # -------------------------------------------------------------------------- + node-build: + name: Node build (${{ matrix.target }}) + strategy: + fail-fast: false + matrix: + include: + - { host: ubuntu-latest, target: x86_64-unknown-linux-gnu } + - { host: macos-latest, target: x86_64-apple-darwin } + - { host: macos-latest, target: aarch64-apple-darwin } + - { host: windows-latest, target: x86_64-pc-windows-msvc } + runs-on: ${{ matrix.host }} + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: "20" + + - uses: dtolnay/rust-toolchain@stable + with: + targets: ${{ matrix.target }} + + - uses: Swatinem/rust-cache@v2 + + - name: Install Node deps + working-directory: bindings/node + run: npm install + + - name: Build native module + working-directory: bindings/node + run: npx napi build --platform --release --target ${{ matrix.target }} + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: bindings-${{ matrix.target }} + path: bindings/node/wickra.*.node + if-no-files-found: error + + node-publish: + name: Publish to npm + needs: node-build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: "20" + registry-url: "https://registry.npmjs.org" + + - name: Install Node deps + working-directory: bindings/node + run: npm install + + - name: Download all platform binaries + uses: actions/download-artifact@v4 + with: + path: bindings/node/artifacts + pattern: bindings-* + + - name: Move binaries into platform package layout + working-directory: bindings/node + run: npx napi artifacts --dir artifacts + + - name: Prepublish platform packages to npm + working-directory: bindings/node + run: npx napi prepublish -t npm --skip-gh-release + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Publish main package to npm + working-directory: bindings/node + run: npm publish --access public + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + # -------------------------------------------------------------------------- + # WASM: wasm-pack build + npm publish (as `wickra-wasm`) + # -------------------------------------------------------------------------- + wasm-publish: + name: Publish wickra-wasm to npm + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: "20" + registry-url: "https://registry.npmjs.org" + + - uses: dtolnay/rust-toolchain@stable + with: + targets: wasm32-unknown-unknown + + - uses: jetli/wasm-pack-action@v0.4.0 + + - name: Build WASM package (bundler target) + run: wasm-pack build bindings/wasm --target bundler --release --features panic-hook + + - name: Enrich generated package.json with author + repo metadata + working-directory: bindings/wasm/pkg + run: | + node -e " + const fs = require('fs'); + const pkg = JSON.parse(fs.readFileSync('package.json')); + pkg.author = 'kingchenc '; + pkg.repository = { type: 'git', url: 'https://github.com/kingchenc/wickra' }; + pkg.homepage = 'https://github.com/kingchenc/wickra'; + pkg.bugs = { url: 'https://github.com/kingchenc/wickra/issues' }; + pkg.license = 'SEE LICENSE IN LICENSE'; + fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2)); + " + + - name: Publish wickra-wasm to npm + working-directory: bindings/wasm/pkg + run: npm publish --access public + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/Cargo.toml b/Cargo.toml index 1df9f273..283cd64f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,8 +16,8 @@ authors = ["Wickra Contributors"] edition = "2021" rust-version = "1.75" license = "PolyForm-Noncommercial-1.0.0" -repository = "https://github.com/wickra/wickra" -homepage = "https://github.com/wickra/wickra" +repository = "https://github.com/kingchenc/wickra" +homepage = "https://github.com/kingchenc/wickra" readme = "README.md" keywords = ["finance", "trading", "indicators", "technical-analysis", "ta"] categories = ["finance", "mathematics", "science"] diff --git a/README.md b/README.md index ef75a13b..c8f5488c 100644 --- a/README.md +++ b/README.md @@ -107,8 +107,8 @@ inherit it automatically. | Binding | Install | Example | |-------------------|-----------------------------------------------|---------| | Python (PyO3) | `pip install wickra` | `examples/python/backtest.py` | -| Node.js (napi-rs) | `npm install @wickra/wickra` | `bindings/node/__tests__/smoke.test.js` | -| Browser / WASM | `wasm-pack build bindings/wasm --target web` | `bindings/wasm/examples/index.html` | +| Node.js (napi-rs) | `npm install wickra` | `bindings/node/__tests__/smoke.test.js` | +| Browser / WASM | `npm install wickra-wasm` | `bindings/wasm/examples/index.html` | | Rust | `cargo add wickra` | `examples/rust/backtest.rs` | The wickra-core crate is `unsafe`-forbidden, so every binding inherits a diff --git a/bindings/node/package.json b/bindings/node/package.json index 1a23fb03..c965f9f1 100644 --- a/bindings/node/package.json +++ b/bindings/node/package.json @@ -1,7 +1,8 @@ { - "name": "@wickra/wickra", + "name": "wickra", "version": "0.1.0", "description": "Streaming-first technical indicators: incremental, fast, install-free. Node bindings powered by Rust.", + "author": "kingchenc ", "main": "index.js", "types": "index.d.ts", "license": "SEE LICENSE IN LICENSE", @@ -16,8 +17,12 @@ ], "repository": { "type": "git", - "url": "https://github.com/wickra/wickra" + "url": "https://github.com/kingchenc/wickra" }, + "bugs": { + "url": "https://github.com/kingchenc/wickra/issues" + }, + "homepage": "https://github.com/kingchenc/wickra", "files": [ "index.js", "index.d.ts", @@ -47,7 +52,10 @@ "scripts": { "build": "napi build --platform --release", "build:debug": "napi build --platform", + "artifacts": "napi artifacts", "prepublishOnly": "napi prepublish -t npm", + "universal": "napi universal", + "version": "napi version", "test": "node --test __tests__/" }, "devDependencies": { diff --git a/bindings/python/pyproject.toml b/bindings/python/pyproject.toml index d0ccf622..df5bcc9b 100644 --- a/bindings/python/pyproject.toml +++ b/bindings/python/pyproject.toml @@ -45,9 +45,9 @@ bench = [ ] [project.urls] -Homepage = "https://github.com/wickra/wickra" -Repository = "https://github.com/wickra/wickra" -Issues = "https://github.com/wickra/wickra/issues" +Homepage = "https://github.com/kingchenc/wickra" +Repository = "https://github.com/kingchenc/wickra" +Issues = "https://github.com/kingchenc/wickra/issues" [tool.maturin] manifest-path = "Cargo.toml" diff --git a/bindings/wasm/Cargo.toml b/bindings/wasm/Cargo.toml index d7c4d6ce..00beec02 100644 --- a/bindings/wasm/Cargo.toml +++ b/bindings/wasm/Cargo.toml @@ -34,6 +34,11 @@ console_error_panic_hook = { version = "0.1", optional = true } default = [] panic-hook = ["dep:console_error_panic_hook"] +[package.metadata.wasm-pack.profile.release.wasm-bindgen] +debug-js-glue = false +demangle-name-section = true +dwarf-debug-info = false + [package.metadata.wasm-pack.profile.release] # The wasm-opt that ships with wasm-pack is older than the WebAssembly # features rustc enables by default (reference-types, multivalue,