stochastic-rs 2.2.0

A Rust library for quant finance and simulating stochastic processes.
Documentation
name: Rust

on:
  push:
    branches: ["main"]
  pull_request:
    branches: ["main"]

env:
  CARGO_TERM_COLOR: always

jobs:
  # Quick check: every sub-crate compiles independently with default features.
  # This catches broken inter-crate boundaries before the heavier coverage job
  # exercises the full umbrella.
  check_subcrates:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        crate:
          - stochastic-rs-core
          - stochastic-rs-distributions
          - stochastic-rs-stochastic
          - stochastic-rs-copulas
          - stochastic-rs-stats
          - stochastic-rs-quant
          - stochastic-rs-ai
          - stochastic-rs-viz
    steps:
      - uses: actions/checkout@v3
      - uses: dtolnay/rust-toolchain@stable
      - name: Cargo check (${{ matrix.crate }})
        run: cargo check -p ${{ matrix.crate }} --no-default-features

  # Umbrella + features matrix. Covers feature combinations that exercise
  # cross-crate cfg-gated code (notably the python+gpu Array2 overlap caught
  # by the 2026-05-07 audit §4.1).
  check_umbrella:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        features:
          - "" # default
          - "ai"
          - "openblas"
          - "yahoo"
          - "python"
          - "gpu"
          - "python,gpu"
          - "openblas,ai,yahoo"
    steps:
      - uses: actions/checkout@v3
      - name: Install OpenBLAS (when needed)
        if: contains(matrix.features, 'openblas')
        run: sudo apt-get update && sudo apt-get install -y libopenblas-dev
      - uses: dtolnay/rust-toolchain@stable
      - name: Cargo check (features=${{ matrix.features }})
        run: |
          if [ -z "${{ matrix.features }}" ]; then
            cargo check -p stochastic-rs --all-targets
          else
            cargo check -p stochastic-rs --all-targets --features "${{ matrix.features }}"
          fi

  # Lint + format gates. Catches drift independently of the feature matrix.
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: dtolnay/rust-toolchain@stable
        with:
          components: clippy, rustfmt
      - name: cargo fmt --check
        run: cargo fmt --all -- --check
      - name: cargo clippy (workspace)
        run: cargo clippy --workspace --no-default-features --all-targets -- -D warnings

  # In-process Python smoke test (audit §7.9): builds the cdylib via
  # `maturin develop` and exercises the 5 main API surfaces (distributions,
  # stochastic, copulas, stats, quant) including seed-determinism for the
  # samplers that accept a `seed=` keyword.
  python_smoke:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: dtolnay/rust-toolchain@stable
      - uses: actions/setup-python@v5
        with:
          python-version: "3.x"
      - name: Install OpenBLAS
        run: sudo apt-get update && sudo apt-get install -y libopenblas-dev
      # `maturin develop` requires an active virtualenv on Linux; the
      # ubuntu-latest runner does not have one by default. Create one and
      # invoke maturin / python via the venv's binaries (no `source` so
      # each `run:` block — which is its own shell — still picks it up).
      - name: Set up venv + install build deps
        run: |
          python -m venv .venv
          .venv/bin/pip install --upgrade pip
          .venv/bin/pip install maturin numpy
      - name: maturin develop (openblas)
        run: .venv/bin/maturin develop --release --features openblas
      - name: Run python_smoke.py
        # `-u` flushes prints so the last `[OK]`/`[FAIL]` line before any
        # crash shows up in the log; `-X faulthandler` prints a C+Python
        # traceback on SIGSEGV, pinning the crashing native call.
        run: .venv/bin/python -X faulthandler -u stochastic-rs-py/python_smoke.py

  # Full test run with openblas + coverage.
  test_with_coverage:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3

      - name: Install system dependencies
        run: sudo apt-get update && sudo apt-get install -y libopenblas-dev

      - uses: dtolnay/rust-toolchain@nightly
        with:
          components: llvm-tools-preview

      - name: Add llvm-tools to PATH
        run: echo "${HOME}/.rustup/toolchains/$(rustup show active-toolchain | cut -d' ' -f1)/bin" >> $GITHUB_PATH

      - name: Install grcov
        run: cargo install grcov

      - name: Clean Build Artifacts
        run: cargo clean

      - name: Run tests with coverage
        env:
          CARGO_INCREMENTAL: "0"
          CARGO_PROFILE_RELEASE_LTO: "false"
          CARGO_PROFILE_RELEASE_CODEGEN_UNITS: "1"
          CARGO_PROFILE_RELEASE_DEBUG: "1"
          RUSTFLAGS: "-C instrument-coverage"
          LLVM_PROFILE_FILE: "coverage-%p-%m.profraw"
        run: |
          cargo test --release --workspace --exclude stochastic-rs-py --features openblas

      - name: Generate coverage report
        run: |
          grcov . \
            --binary-path ./target/release/ \
            -s . \
            -t lcov \
            --branch \
            --ignore-not-existing \
            --llvm \
            -o lcov.info

      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v4
        with:
          files: lcov.info
          fail_ci_if_error: true
          verbose: true
        env:
          CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}