Files
wickra/.github/workflows/ci.yml
T
kingchenc 3fcf2094f1 ci(wasm): install wasm-pack via taiki-e prebuilt instead of jetli's stale 0.10
jetli/wasm-pack-action@v0.4.0 with no version: input installs whatever
wasm-pack the action's bundled installer fetches — currently a ~0.10.x
release whose 'build' subcommand does not yet accept --features. Our
build invocation 'wasm-pack build … --features panic-hook' now fails
with

    error: Found argument '--features' which wasn't expected, or isn't
    valid in this context
    USAGE: wasm-pack build --release --target <target>

even though that exact command worked on past runs where the action
happened to install a newer wasm-pack. (The bundler-target release.yml
job passed for v0.2.1 only because it shared the same cached install
on that runner.)

wasm-pack's --features top-level flag has been stable since 0.12.0, so
the fix is to install a fresh wasm-pack each run. Switch both the ci.yml
'WASM build' step and the release.yml 'wasm-publish' job to the same
taiki-e/install-action prebuilt-binary installer we already use for
cargo-llvm-cov and cargo-fuzz. taiki-e tracks the latest wasm-pack
release and the install is a single binary download — no compile, no
shell installer.

The wasm-pack invocations themselves are unchanged.
2026-05-23 23:00:13 +02:00

318 lines
12 KiB
YAML

name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
CARGO_TERM_COLOR: always
RUSTFLAGS: "-D warnings"
jobs:
rust:
name: Rust ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable branch, 2026-03-27
with:
components: rustfmt, clippy
- name: Cache cargo
uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
- name: Format check
run: cargo fmt --all -- --check
- name: Clippy (workspace, all targets)
run: cargo clippy -p wickra-core -p wickra -p wickra-data -p wickra-wasm --all-targets -- -D warnings
- name: Build
run: cargo build -p wickra-core -p wickra -p wickra-data --verbose
- name: Tests (default features)
run: cargo test -p wickra-core -p wickra -p wickra-data --verbose
- name: Tests (live-binance feature)
run: cargo test -p wickra-data --features live-binance --verbose
- name: Compile benches (smoke)
run: cargo build -p wickra --benches --verbose
- name: Compile examples
# All runnable examples now live in the dedicated wickra-examples crate
# (examples/rust/src/bin/*.rs) which enables the live-binance feature
# on its wickra-data dep, so a single --bins build covers backtest,
# live_binance, fetch_btcusdt, multi_timeframe, parallel_assets and
# streaming.
run: cargo build -p wickra-examples --bins
# Verify the crates still build and test on their declared minimum supported
# Rust version. The workspace pins rust-version = "1.86" — that floor is
# set by criterion 0.8.2 (the bench dev-dep), which itself rolled past the
# clap_lex 1.1.0 / edition2024 / Rust 1.85 floor and now needs 1.86; the
# earlier rayon-core 1.13.0 (1.80) and clap_lex (1.85) requirements are
# subsumed. bindings/node pins rust-version = "1.88" because napi-build
# 2.3.2 requires it (and that subsumes the older 1.77 floor needed for
# `cargo::` directives). Without this job an accidental use of a newer
# API would only surface for downstream users.
msrv:
name: ${{ matrix.name }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- name: MSRV workspace (Rust 1.86)
toolchain: "1.86"
packages: "-p wickra-core -p wickra -p wickra-data"
- name: MSRV node binding (Rust 1.88)
toolchain: "1.88"
packages: "-p wickra-node"
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install Rust ${{ matrix.toolchain }}
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable branch, 2026-03-27
with:
toolchain: ${{ matrix.toolchain }}
- name: Cache cargo
uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
- name: Build on MSRV
run: cargo build ${{ matrix.packages }} --verbose
- name: Test on MSRV
run: cargo test ${{ matrix.packages }} --verbose
# Code coverage for the pure-Rust crates, uploaded to Codecov.
coverage:
name: Coverage
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable branch, 2026-03-27
with:
components: llvm-tools-preview
- name: Cache cargo
uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
- name: Install cargo-llvm-cov
uses: taiki-e/install-action@6c1f7cf125e42770ff087ea443901b487cc5471a # v2.79.5
with:
tool: cargo-llvm-cov
- name: Generate coverage (lcov)
run: >
cargo llvm-cov
-p wickra-core -p wickra -p wickra-data
--features wickra-data/live-binance
--lcov --output-path lcov.info
- name: Upload to Codecov
uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1
with:
files: lcov.info
fail_ci_if_error: false
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
# Supply-chain audit: security advisories, license policy, banned crates,
# and source restrictions. Configured by deny.toml at the repo root.
supply-chain:
name: Supply-chain (cargo-deny)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: cargo-deny
uses: EmbarkStudios/cargo-deny-action@a531616d8ce3b9177443e48a1159bc945a099823 # v2.0.19
with:
command: check
# Time-boxed fuzz smoke. Each target runs for ~30 s with libfuzzer; any panic
# fails the job. The goal is to catch a regression in the harness (e.g. a
# newly added indicator that panics on a particular input shape), not to
# discover novel bugs — long fuzz campaigns should be run on dedicated
# infrastructure with persistent corpora.
fuzz-smoke:
name: Fuzz (smoke)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install nightly Rust
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable branch, 2026-03-27
with:
toolchain: nightly
- name: Cache cargo
uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
with:
workspaces: fuzz
- name: Install cargo-fuzz
# Use the prebuilt binary from taiki-e/install-action instead of
# `cargo install cargo-fuzz --locked`. The latter resolves the
# version graph from cargo-fuzz's own Cargo.lock, which pins to
# rustix 0.36.5 — a version that still uses internal `rustc_*`
# attributes the modern nightly compiler rejects, so the install
# never gets off the ground. The prebuilt binary avoids the entire
# transitive-dep compile.
uses: taiki-e/install-action@6c1f7cf125e42770ff087ea443901b487cc5471a # v2.79.5
with:
tool: cargo-fuzz
- name: Fuzz csv_reader (30 s)
run: cargo +nightly fuzz run --target x86_64-unknown-linux-gnu csv_reader -- -max_total_time=30
working-directory: fuzz
- name: Fuzz binance_envelope (30 s)
run: cargo +nightly fuzz run --target x86_64-unknown-linux-gnu binance_envelope -- -max_total_time=30
working-directory: fuzz
- name: Fuzz indicator_update (30 s)
run: cargo +nightly fuzz run --target x86_64-unknown-linux-gnu indicator_update -- -max_total_time=30
working-directory: fuzz
- name: Fuzz indicator_update_candle (30 s)
run: cargo +nightly fuzz run --target x86_64-unknown-linux-gnu indicator_update_candle -- -max_total_time=30
working-directory: fuzz
- name: Fuzz tick_aggregator (30 s)
run: cargo +nightly fuzz run --target x86_64-unknown-linux-gnu tick_aggregator -- -max_total_time=30
working-directory: fuzz
python:
name: Python ${{ matrix.python-version }} on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: ["3.9", "3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable branch, 2026-03-27
- name: Cache cargo
uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: ${{ matrix.python-version }}
- name: Install Python dev dependencies
run: |
python -m pip install --upgrade pip
python -m pip install maturin pytest numpy hypothesis
- name: Build wheel
working-directory: bindings/python
run: maturin build --release --out dist
- name: Install wheel
shell: bash
working-directory: bindings/python
run: python -m pip install --find-links dist --force-reinstall wickra
- name: Run Python tests
working-directory: bindings/python
run: pytest -v
wasm:
name: WASM build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install Rust toolchain (with wasm target)
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable branch, 2026-03-27
with:
targets: wasm32-unknown-unknown
- name: Cache cargo
uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
- name: Install wasm-pack
# jetli/wasm-pack-action@v0.4.0 with no `version:` input installs an
# old wasm-pack (~0.10.x) whose `build` subcommand does not yet accept
# `--features`, so `wasm-pack build … --features panic-hook` fails
# with "Found argument '--features' which wasn't expected". Use the
# same taiki-e prebuilt-binary installer we already use for
# cargo-llvm-cov and cargo-fuzz; it tracks the latest wasm-pack
# release, which has `--features` as a top-level flag (since 0.12).
uses: taiki-e/install-action@6c1f7cf125e42770ff087ea443901b487cc5471a # v2.79.5
with:
tool: wasm-pack
- name: Build WASM package
run: wasm-pack build bindings/wasm --target web --release --features panic-hook
- name: Run WASM tests
run: wasm-pack test --node bindings/wasm
- name: Verify generated artefacts
run: |
test -f bindings/wasm/pkg/wickra_wasm.js
test -f bindings/wasm/pkg/wickra_wasm_bg.wasm
test -f bindings/wasm/pkg/wickra_wasm.d.ts
node:
name: Node ${{ matrix.node-version }} on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
node-version: ["18", "20"]
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable branch, 2026-03-27
- name: Cache cargo
uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
- name: Set up Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: ${{ matrix.node-version }}
- name: Install Node dependencies
working-directory: bindings/node
run: npm install
- name: Build native module
working-directory: bindings/node
# --platform puts the target triple into the filename so the loader's
# `wickra.<target>.node` lookup finds the freshly built binary instead
# of falling back to the per-platform npm subpackage (which doesn't
# exist yet for win32-x64-msvc).
run: npx napi build --platform --release
- name: Run Node tests
working-directory: bindings/node
run: node --test __tests__/
# The cross-library benchmark has moved to a dedicated scheduled workflow
# (.github/workflows/bench.yml) — see audit finding R10. It runs nightly
# at 03:00 UTC and on-demand via `workflow_dispatch`, and is no longer on
# the every-push / every-PR critical path.