name: Quality
on:
push:
branches: [main, "feat/**"]
pull_request:
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
env:
CARGO_TERM_COLOR: always
jobs:
coverage-gate:
name: coverage (98% lines)
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@7e38f4b43b4db5c8dd498af069a4f6196df1d067 with:
toolchain: nightly
components: llvm-tools-preview
- uses: Swatinem/rust-cache@f0d9c3887740aee45f6153b24b3a6b815192ec16 - uses: taiki-e/install-action@83ac0ad63c0167e6f06796fab0fce28db1bf3db0 with:
tool: cargo-llvm-cov
- run: cargo llvm-cov --all-features --locked --fail-under-lines 98
miri:
name: miri
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@7e38f4b43b4db5c8dd498af069a4f6196df1d067 with:
toolchain: nightly
components: miri
- uses: Swatinem/rust-cache@f0d9c3887740aee45f6153b24b3a6b815192ec16 - run: cargo +nightly miri test --lib
fuzz-replay:
name: fuzz build + corpus replay
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@7e38f4b43b4db5c8dd498af069a4f6196df1d067 with:
toolchain: nightly
- uses: Swatinem/rust-cache@f0d9c3887740aee45f6153b24b3a6b815192ec16 with:
workspaces: fuzz
- run: cargo install --locked cargo-fuzz
- name: Build every target and replay the corpus
working-directory: fuzz
run: |
set -euo pipefail
cargo +nightly fuzz build
for target in $(cargo +nightly fuzz list); do
echo "== $target"
dirs=("corpus/$target")
[ -d "regressions/$target" ] && dirs+=("regressions/$target")
cargo +nightly fuzz run "$target" -- -runs=0 "${dirs[@]}"
done
proptest:
name: proptest property verification
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@7e38f4b43b4db5c8dd498af069a4f6196df1d067 with:
toolchain: stable
- uses: Swatinem/rust-cache@f0d9c3887740aee45f6153b24b3a6b815192ec16 - run: cargo test --test test_proptest -- --nocapture
loom:
name: loom concurrency check
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@7e38f4b43b4db5c8dd498af069a4f6196df1d067 with:
toolchain: stable
- uses: Swatinem/rust-cache@f0d9c3887740aee45f6153b24b3a6b815192ec16 - run: RUSTFLAGS="--cfg loom" cargo test --test loom_smoke --release
docs-lint:
name: docs lint (markdownlint, codespell, REUSE)
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with:
persist-credentials: false
- uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 - run: npx --yes markdownlint-cli2 "**/*.md" "!target/**" "!fuzz/target/**"
- run: uvx codespell
- run: uvx --with chardet reuse lint
cargo-vet:
name: cargo-vet
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@7e38f4b43b4db5c8dd498af069a4f6196df1d067 with:
toolchain: stable
- uses: Swatinem/rust-cache@f0d9c3887740aee45f6153b24b3a6b815192ec16 - uses: taiki-e/install-action@83ac0ad63c0167e6f06796fab0fce28db1bf3db0 with:
tool: cargo-vet@0.10.2
- run: cargo vet --locked
- name: Exemption ratchet
run: |
set -euo pipefail
baseline="$(tr -d '[:space:]' < supply-chain/exemptions-baseline.txt)"
current="$(cargo vet --locked 2>&1 | grep -oE '[0-9]+ exempted' | grep -oE '[0-9]+')"
echo "exempted: $current (baseline $baseline)"
if [ "$current" -gt "$baseline" ]; then
echo "::error::exemptions grew from $baseline to $current"
exit 1
fi
release-hygiene:
name: versions, examples, benches
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@7e38f4b43b4db5c8dd498af069a4f6196df1d067 with:
toolchain: stable
- uses: Swatinem/rust-cache@f0d9c3887740aee45f6153b24b3a6b815192ec16 - run: ./scripts/verify-release-versions.sh
- run: make examples
- run: cargo bench --all-features -- --test
- name: rustdoc with warnings denied
env:
RUSTDOCFLAGS: -D warnings
run: cargo doc --no-deps --all-features --locked
msrv:
name: MSRV (1.88.0)
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@7e38f4b43b4db5c8dd498af069a4f6196df1d067 with:
toolchain: 1.88.0
- uses: Swatinem/rust-cache@f0d9c3887740aee45f6153b24b3a6b815192ec16 - run: cargo check --all-features --all-targets --locked
semver-checks:
name: API breakage (cargo-semver-checks)
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@7e38f4b43b4db5c8dd498af069a4f6196df1d067 with:
toolchain: stable
- uses: Swatinem/rust-cache@f0d9c3887740aee45f6153b24b3a6b815192ec16 - uses: taiki-e/install-action@83ac0ad63c0167e6f06796fab0fce28db1bf3db0 with:
tool: cargo-semver-checks
- run: cargo semver-checks check-release --all-features
feature-powerset:
name: feature powerset (cargo-hack)
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@7e38f4b43b4db5c8dd498af069a4f6196df1d067 with:
toolchain: stable
- uses: Swatinem/rust-cache@f0d9c3887740aee45f6153b24b3a6b815192ec16 - uses: taiki-e/install-action@83ac0ad63c0167e6f06796fab0fce28db1bf3db0 with:
tool: cargo-hack
- run: cargo hack check --feature-powerset --all-targets --locked
no-std:
name: no_std + alloc (thumbv7em-none-eabihf)
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@7e38f4b43b4db5c8dd498af069a4f6196df1d067 with:
toolchain: stable
targets: thumbv7em-none-eabihf
- uses: Swatinem/rust-cache@f0d9c3887740aee45f6153b24b3a6b815192ec16 - run: cargo build --lib --locked --no-default-features --features yaml,toml,json --target thumbv7em-none-eabihf
- run: cargo test --lib --locked --no-default-features --features yaml
complexity:
name: complexity (per-function ceilings)
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@7e38f4b43b4db5c8dd498af069a4f6196df1d067 with:
toolchain: stable
- uses: taiki-e/cache-cargo-install-action@9ee83daaa7b96a6fab930949ecf1122bba04a389 with:
tool: rust-code-analysis-cli@0.0.25
- run: python3 -I scripts/complexity_check.py
links:
name: links (lychee)
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with:
persist-credentials: false
- uses: lycheeverse/lychee-action@e7477775783ea5526144ba13e8db5eec57747ce8 with:
args: --config lychee.toml './**/*.md'
fail: true
token: ${{ secrets.GITHUB_TOKEN }}