Skip to content

Bump actions/checkout from 4.2.2 to 6.0.3 (#69) #92

Bump actions/checkout from 4.2.2 to 6.0.3 (#69)

Bump actions/checkout from 4.2.2 to 6.0.3 (#69) #92

Workflow file for this run

name: Test
# Runs on pushes to the default branch AND on every pull request, so the
# matrix can be used as a required merge gate. (Baseline only ran on push.)
on:
push:
branches: [master]
pull_request:
workflow_dispatch:
# Cancel superseded runs for the same ref to save runner minutes.
concurrency:
group: test-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
# ---------------------------------------------------------------------------
# Lint. rustfmt is enforced (blocking) now that the source is rustfmt-clean.
# clippy and mypy stay advisory (continue-on-error) until their debt clears,
# and each runs regardless of the others:
# - clippy -> flip to blocking after the str->bytes fix (#19)
# - mypy -> flip to blocking after the .pyi stubs type-check clean (#42)
# ---------------------------------------------------------------------------
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: "3.10"
- uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9 # master
with:
toolchain: "1.83"
components: rustfmt, clippy
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
- name: cargo fmt --check
run: cargo fmt --all -- --check
# clippy::cast_possible_truncation pinpoints the str->bytes corruption bug.
- name: cargo clippy
if: always()
run: cargo clippy --all-targets -- -D warnings -W clippy::cast_possible_truncation
continue-on-error: true
- name: mypy (type stubs)
if: always()
run: |
python -m pip install --upgrade pip mypy
mypy fast_mail_parser/
continue-on-error: true
# ---------------------------------------------------------------------------
# Supply-chain audit. Blocking (no continue-on-error): the dependency stack is
# current (PyO3 0.29) and the Cargo.lock audits clean, so a new advisory
# against any dependency should fail the build and gate the PR rather than pass
# silently. (It was previously advisory only because the stack was stale and a
# fresh advisory against a pinned dep would have blocked unrelated PRs.)
# cargo-audit needs a newer rustc than the repo's pinned 1.83, so the job runs
# on stable via RUSTUP_TOOLCHAIN (overrides the rust-toolchain file).
#
# cargo-audit is `cargo install`ed from source (~3 min — previously the
# slowest job by far). The compiled binary is cached and keyed on the pinned
# CARGO_AUDIT_VERSION: a cache hit skips the build (restores in seconds); a
# miss builds it once and caches it.
#
# Cache invalidation: to upgrade cargo-audit, bump CARGO_AUDIT_VERSION below.
# That installs the new version AND invalidates the cache in one change — the
# version IS the cache key, so there is no separate suffix to remember. The
# key is intentionally NOT tied to the rustc/cargo version: the binary runs
# fine across toolchain updates, and keying on it would force a needless
# ~3-min rebuild on every stable bump. The RustSec advisory DB is fetched
# fresh on every run, so findings stay current regardless of the cached
# binary version.
# ---------------------------------------------------------------------------
security-audit:
name: cargo audit
runs-on: ubuntu-latest
env:
RUSTUP_TOOLCHAIN: stable
# Bump to upgrade cargo-audit; this also invalidates the binary cache.
CARGO_AUDIT_VERSION: "0.22.2"
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9 # master
with:
toolchain: stable
- name: Cache cargo-audit binary
id: cache-cargo-audit
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ~/.cargo/bin/cargo-audit
key: cargo-audit-${{ runner.os }}-${{ env.CARGO_AUDIT_VERSION }}
- name: Install cargo-audit
if: steps.cache-cargo-audit.outputs.cache-hit != 'true'
run: cargo install cargo-audit --version ${{ env.CARGO_AUDIT_VERSION }} --locked
- name: cargo audit
run: cargo audit
# ---------------------------------------------------------------------------
# Test matrix — the real merge gate. Builds & passes on CPython 3.9–3.13 with
# PyO3 0.29 (3.7/3.8 are EOL and unavailable on current ubuntu runners). 3.13
# is a required cell now that PyO3 0.29 supports it (was allowed-failure under
# the old 0.16 pin).
# ---------------------------------------------------------------------------
test:
name: Test (py${{ matrix.python-version }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: ${{ matrix.python-version }}
cache: pip
- name: Install the package
run: make install
- name: Install test dependencies
run: make install-test
- name: Test
run: make test
# ---------------------------------------------------------------------------
# Benchmark quality gate. The benchmark used to run inside every matrix cell
# (6x redundant, slow). It now runs once here and acts as a performance gate:
# fast_mail_parser must stay at least BENCH_MIN_SPEEDUP times faster than the
# pure-Python mail-parser baseline (README reports ~8x). The ratio is measured
# on the same runner in the same run, so it is hardware-independent and stable.
# Getting faster always passes; only regressions below the floor fail.
# ---------------------------------------------------------------------------
benchmark:
name: Benchmark quality gate
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: "3.10"
cache: pip
- name: Install the package + test dependencies
run: |
make install
make install-test
- name: Run benchmark
run: pytest -v tests/benchmark --benchmark-min-rounds=25 --benchmark-json=benchmark.json
- name: Enforce performance gate
env:
# Gate on min-time ratio. 8x matches the README headline figure and
# requires the str-input fast path; the optimized parser measures
# ~8.7x on CI. Headroom is tight, so a slow-relative runner can dip
# below 8x.
BENCH_MIN_SPEEDUP: "8.0"
run: python .github/scripts/check_benchmark.py benchmark.json
- name: Upload benchmark report
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: benchmark-json
path: benchmark.json