-
Notifications
You must be signed in to change notification settings - Fork 7
218 lines (200 loc) · 8.29 KB
/
Copy pathrust.yml
File metadata and controls
218 lines (200 loc) · 8.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
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 pytest scipy
- 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
- name: Run pytest suite
# The pytest suite (stochastic-rs-py/tests/) covers all five API
# surfaces beyond the smoke script; conftest.py skips with a clear
# message if the extension is somehow not importable.
run: .venv/bin/python -m pytest stochastic-rs-py/tests/ -v
# Fast correctness gate: the whole workspace test-suite via cargo-nextest
# (no coverage instrumentation), so a failing/flaky test surfaces in minutes
# instead of only inside the multi-hour coverage job. The `ci` nextest
# profile prints one line per finished test with a running `(N/total)`
# counter, so the log shows which test is executing and how far along the
# run is.
test:
runs-on: ubuntu-latest
timeout-minutes: 90
steps:
- uses: actions/checkout@v3
- name: Install OpenBLAS
run: sudo apt-get update && sudo apt-get install -y libopenblas-dev
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Install nextest
uses: taiki-e/install-action@v2
with:
tool: nextest
# `--release` because the heavy Monte-Carlo tests (Malliavin, rBergomi,
# Fourier-Malliavin) are unusably slow unoptimised; `--exclude
# stochastic-rs-py` because the cdylib is exercised by pytest in the
# python_smoke job. Mirrors the coverage job's feature set for parity.
- name: cargo nextest run (workspace)
run: cargo nextest run --workspace --exclude stochastic-rs-py --features openblas --profile ci
# nextest does not run doctests; this gates the crates' doc examples
# (e.g. the README quickstart rendered on docs.rs) that plain `cargo
# test` used to cover. `--release` reuses the artifacts built above.
- name: cargo test --doc (workspace)
run: cargo test --release --workspace --exclude stochastic-rs-py --features openblas --doc
# Full test run with openblas + coverage. Heavyweight + instrumented, so it
# only runs on pushes to main; the fast `test` job gates pull requests.
test_with_coverage:
runs-on: ubuntu-latest
if: github.event_name == 'push'
timeout-minutes: 240
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: Install nextest
uses: taiki-e/install-action@v2
with:
tool: nextest
- 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"
# nextest runs each test in its own process (one profraw per test, kept
# unique by the %p pid above) and the `ci-coverage` profile prints the
# running (N/total) counter; grcov then merges every profraw as before.
run: |
cargo nextest run --release --workspace --exclude stochastic-rs-py --features openblas --profile ci-coverage
- name: Generate coverage report
run: |
grcov . \
--binary-path ./target/release/ \
-s . \
-t lcov \
--branch \
--ignore-not-existing \
--llvm \
-o lcov.info
# nextest writes one profraw per test (~1300 files, >1 GB total).
# grcov has merged them into lcov.info above, so delete them — else
# the Codecov upload sweeps up a gigabyte of raw profiling data
# instead of the single lcov report, which Codecov cannot parse.
find . -name '*.profraw' -delete
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
files: lcov.info
# Upload only lcov.info; do not let the CLI discover/attach anything
# else in the tree (belt-and-braces with the profraw cleanup above).
disable_search: true
fail_ci_if_error: true
verbose: true
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}