name: CI
permissions:
contents: read
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
CARGO_TERM_COLOR: always
jobs:
test:
name: test (${{ matrix.os }}, ${{ matrix.rust }})
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
rust: [stable, 1.85.0]
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.rust }}
components: clippy
- uses: Swatinem/rust-cache@v2
- run: cargo test --all-features --locked
- run: cargo clippy --all-targets --all-features --locked -- -D warnings
- run: cargo doc --no-deps --all-features --locked
env:
RUSTDOCFLAGS: -D warnings
typos:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: crate-ci/typos@v1
deny:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: EmbarkStudios/cargo-deny-action@v2.0.20
with:
command: check advisories licenses bans sources
dependency-review:
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/dependency-review-action@v5
with:
fail-on-severity: low
comment-summary-in-pr: on-failure
allow-licenses: MIT, Apache-2.0, BSD-3-Clause, Unicode-DFS-2016, Unicode-3.0
coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: taiki-e/install-action@cargo-tarpaulin
- uses: Swatinem/rust-cache@v2
- run: cargo tarpaulin --all-features --out xml --timeout 120 --fail-under 90
- uses: codecov/codecov-action@v7
with:
files: ./cobertura.xml
fail_ci_if_error: false
semver:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- uses: obi1kenobi/cargo-semver-checks-action@v2
hack:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: taiki-e/install-action@cargo-hack
- uses: Swatinem/rust-cache@v2
- run: cargo hack check --feature-powerset --locked
fuzz:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
- run: cargo install cargo-fuzz
- uses: Swatinem/rust-cache@v2
- run: cargo fuzz build
bench:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Save baseline from main
if: github.event_name == 'pull_request'
run: |
git stash --include-untracked || true
git checkout ${{ github.base_ref }}
cargo bench --all-features -- --save-baseline main
git checkout ${{ github.head_ref }}
git stash pop || true
- name: Run benchmarks with regression check
id: benchmark
run: cargo bench --all-features -- --baseline main 2>&1 | tee benchmark.log
- name: Check for performance regressions (>5%)
if: github.event_name == 'pull_request'
run: |
python3 << 'PYEOF'
import re
import sys
with open("benchmark.log") as f:
content = f.read()
# Match criterion change lines followed by "Performance has regressed."
# change: [+5.123% +7.234% +9.345%] (p = 0.00 < 0.05)
# Performance has regressed.
pattern = r'change:\s+\[([+\-][\d.]+)%\s+([+\-][\d.]+)%\s+([+\-][\d.]+)%\][^\n]*\n\s+Performance has regressed\.'
matches = re.findall(pattern, content)
failed = False
for lower, typical, upper in matches:
lower_val = float(lower)
# The lower bound of the confidence interval gives the most
# conservative estimate of the regression.
if lower_val > 5.0:
print(
f"FAIL: significant regression detected: {lower}% to {upper}% "
f"(typical: {typical}%)"
)
failed = True
else:
print(
f"WARNING: minor regression detected: {lower}% to {upper}% "
f"(typical: {typical}%) — below 5% threshold"
)
if failed:
print("\nFailing because at least one benchmark regressed > 5%.")
sys.exit(1)
print("No significant performance regressions (>5%) detected.")
PYEOF
- name: Upload benchmark results
uses: actions/upload-artifact@v7
with:
name: criterion-report-${{ github.event_name }}-${{ github.sha }}
path: target/criterion/
retention-days: 30
publish-dry-run:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo publish --dry-run --all-features --locked