name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
jobs:
fmt:
name: Formatting
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt
- run: cargo fmt --all --check
clippy:
name: Clippy (${{ matrix.os }})
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy
- uses: Swatinem/rust-cache@v2
- run: cargo clippy --all-targets --all-features -- -D warnings
test:
name: Tests (${{ matrix.os }})
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Cache fastembed ONNX models
uses: actions/cache@v4
with:
path: |
~/.cache/fastembed
~/Library/Caches/fastembed
~\AppData\Local\fastembed\Cache
key: fastembed-model-multilingual-e5-small-${{ runner.os }}
- name: Install cargo-nextest
run: cargo install cargo-nextest --locked
- name: Run tests with nextest (retry on network flake)
shell: bash
env:
RUST_TEST_THREADS: "2"
RUSTFLAGS: -D warnings
run: |
for attempt in 1 2 3; do
echo "=== Test attempt $attempt ==="
if cargo nextest run --profile ci --all-features; then
break
fi
if [ "$attempt" -eq 3 ]; then exit 1; fi
echo "Attempt $attempt failed, retrying in 30s..."
sleep 30
done
- name: Run doctests
env:
RUST_TEST_THREADS: "2"
RUSTFLAGS: -D warnings
run: cargo test --doc --all-features
doc:
name: Documentation
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo doc --no-deps --all-features
env:
RUSTDOCFLAGS: -D warnings
msrv:
name: MSRV (1.88)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@1.88
- uses: Swatinem/rust-cache@v2
- run: cargo check --all-features
audit:
name: Security Audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo install cargo-audit --locked
- run: cargo audit
deny:
name: Dependency Policy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo install cargo-deny --locked
- run: cargo deny check advisories licenses bans sources
coverage:
name: Coverage
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: llvm-tools-preview
- uses: Swatinem/rust-cache@v2
- name: Install cargo-nextest and llvm-cov
run: |
cargo install cargo-nextest --locked
cargo install cargo-llvm-cov --locked
- name: Coverage with nextest
env:
RUST_TEST_THREADS: "2"
run: cargo llvm-cov nextest --profile ci --all-features --lcov --output-path lcov.info
- uses: actions/upload-artifact@v4
with:
name: coverage-lcov
path: lcov.info
commit-check:
name: Block Agent Co-Authorship
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check commit messages for agent co-authors
run: |
range="${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}"
pattern='(?i)Co-authored-by:.*(Claude|Opus|Sonnet|Haiku|GPT-|Copilot|Cursor|Gemini|Anthropic|OpenAI|dependabot\[bot\]|renovate\[bot\])'
if git log --format='%B' "$range" | grep -Pq "$pattern"; then
echo "::error::Commit messages must not include Co-authored-by from AI agents or bots"
git log --format='%B' "$range" | grep -P "$pattern" || true
exit 1
fi
echo "No forbidden co-authors detected"
loom:
name: Loom Concurrency
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Run loom tests
env:
RUSTFLAGS: "--cfg loom"
LOOM_MAX_PREEMPTIONS: "2"
LOOM_MAX_BRANCHES: "500"
RUST_TEST_THREADS: "1"
run: timeout 600 cargo test --test loom_lock_slots --release -- --test-threads=1
bench-regression:
name: Benchmark Regression
runs-on: ubuntu-latest
continue-on-error: true
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Download baseline artifact
uses: actions/download-artifact@v4
with:
name: bench-baseline
path: target/criterion
continue-on-error: true
- name: Run benchmarks
env:
RUST_TEST_THREADS: "2"
run: timeout 300 cargo bench --bench regression_baseline -- --quick
- name: Upload benchmark results
uses: actions/upload-artifact@v4
with:
name: bench-baseline
path: target/criterion