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
name: CI
on:
push:
branches:
pull_request:
branches:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
CARGO_TERM_COLOR: always
jobs:
# Fast lint checks - single job to reduce setup overhead
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- uses: Swatinem/rust-cache@v2
- name: Format
run: cargo fmt --all -- --check
- name: Clippy
run: cargo clippy --all-features -- -D warnings
# Main test job
test:
name: Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Run tests
run: cargo test --all-features
# Examples - only when source or examples change
examples:
name: Examples
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Build and run examples
run: |
cargo build --examples --all-features
# Run each example in the foreground so `set -e` fails the step on any
# runtime panic. A bare `wait` on backgrounded jobs always returns 0
# and would silently swallow a panicking example.
cargo run --example quick_taste
cargo run --example first_patch
cargo run --example tutorial_subtractive
cargo run --example tutorial_envelope
cargo run --example tutorial_filter_mod
# Documentation - check rustdoc warnings
doc:
name: Docs
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Build docs
run: cargo doc --no-deps --all-features
env:
RUSTDOCFLAGS: -D warnings
# no_std / alloc-tier check (Q137): actually exercise the feature tiers that
# src/lib.rs documents ("Without any features, the library operates in
# no_std mode with alloc, providing core DSP modules for embedded systems
# and WebAssembly targets") on a genuine no_std target, instead of only ever
# building with --all-features like every other job here. Cheap and PR-gated
# since it's just two `cargo rustc --emit=metadata` invocations.
#
# `--crate-type rlib` overrides the crate's declared `cdylib` (Cargo.toml,
# required by wasm-pack, see the [lib] comment there / Q140): checking the
# unmodified cdylib+rlib crate-type on a no_std build fails with spurious
# "no global memory allocator" / "panic_handler function required" errors
# that have nothing to do with this crate's actual no_std code, because
# rustc requires an allocator/panic-handler for any cdylib artifact.
#
# thumbv7em-none-eabihf (Cortex-M4/M7) has no native 64-bit atomic load/store
# (`core`'s max_atomic_width is 32 there), so `core::sync::atomic::AtomicU64`
# does not exist on this target. The crate handles this by depending on
# `portable-atomic` (Cargo.toml) and using `portable_atomic::AtomicU64` in
# src/polyphony.rs, src/io.rs, and src/rng.rs instead of the `core` type.
# Both commands below therefore compile cleanly on this target; this job is a
# real (non-`continue-on-error`) gate that keeps the no_std build honest in CI.
no_std:
name: no_std / alloc
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
targets: thumbv7em-none-eabihf
- uses: Swatinem/rust-cache@v2
- name: Check no_std (bare, no default features)
run: cargo rustc --lib --crate-type rlib --no-default-features --target thumbv7em-none-eabihf -- --emit=metadata
- name: Check no_std + alloc
run: cargo rustc --lib --crate-type rlib --no-default-features --features alloc --target thumbv7em-none-eabihf -- --emit=metadata
# Browser tests - WASM integration tests with Playwright
browser-tests:
name: Browser Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
targets: wasm32-unknown-unknown
- uses: Swatinem/rust-cache@v2
- name: Install wasm-pack
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: demos/browser/tests/package-lock.json
- name: Install Playwright
run: |
cd demos/browser/tests
npm ci
npx playwright install --with-deps chromium
- name: Run browser tests
run: make test-browser
# ============================================================================
# Main branch only - expensive or comparative checks
# ============================================================================
# MSRV check - only on main (PRs should just work if main works)
msrv:
name: MSRV (1.78)
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master'
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@1.78.0
- uses: Swatinem/rust-cache@v2
- name: Check MSRV
run: cargo check --all-features
# Benchmarks - only meaningful on main for comparisons
bench:
name: Benchmarks
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master'
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
# Compile the benches both ways so the scalar and SIMD (wide-backed) code
# paths are guaranteed to build.
- name: Compile benchmarks (scalar + SIMD)
run: |
cargo bench --no-run
cargo bench --no-run --features simd
# Actually gate the real-time deadline (Q114). Must run in release: the
# test's wall-clock assertion is only active in optimized builds.
- name: Real-time compliance gate (release)
run: cargo test --release --test realtime_compliance -- --nocapture
# Produce criterion measurement data with short warm-up/measurement times
# so the run stays bounded, then persist it as a downloadable baseline.
- name: Run benchmarks (generate criterion baselines)
run: cargo bench -- --warm-up-time 1 --measurement-time 3
- name: Upload criterion baselines
uses: actions/upload-artifact@v4
with:
name: criterion-baselines
path: target/criterion
if-no-files-found: warn
# Coverage - expensive, main only
coverage:
name: Coverage
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master'
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: llvm-tools-preview
- uses: Swatinem/rust-cache@v2
- name: Install cargo-llvm-cov
uses: taiki-e/install-action@cargo-llvm-cov
- name: Run coverage
run: |
cargo llvm-cov --all-features \
--ignore-filename-regex 'src/wasm/.*' \
--fail-under-lines 80