docs(readme): drop Rust-implementation framing — describe the library… #71
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| pull_request: | |
| branches: [main] | |
| push: | |
| branches: [main] | |
| workflow_dispatch: | |
| concurrency: | |
| group: ci-${{ github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| jobs: | |
| yaml-lint: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 | |
| with: | |
| python-version: '3.x' | |
| - name: Install yamllint | |
| # Major-bound pin (like the uvx tools) so a yamllint 2.x can't add rules | |
| # that red this gate without a deliberate bump. | |
| run: pip install 'yamllint>=1,<2' | |
| - name: Lint YAML | |
| run: yamllint . | |
| lint: | |
| name: ruff | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| # Rust toolchain: needed so `uv sync` can build the PyO3 extension via maturin. | |
| - uses: dtolnay/rust-toolchain@67ef31d5b988238dd797d409d6f9574278e20537 # stable | |
| with: | |
| toolchain: stable | |
| - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 | |
| with: | |
| enable-cache: true | |
| - run: uv run ruff format --check . | |
| - run: uv run ruff check . | |
| typecheck: | |
| name: mypy + stubtest | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - uses: dtolnay/rust-toolchain@67ef31d5b988238dd797d409d6f9574278e20537 # stable | |
| with: | |
| toolchain: stable | |
| - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 | |
| with: | |
| enable-cache: true | |
| - run: uv run mypy | |
| # stubtest checks the .pyi against the compiled module at runtime — it catches | |
| # signature drift (params/types/defaults) the AST-based drift guard in | |
| # tests/test_api_surface.py cannot see. The allowlist suppresses only | |
| # irreducible PyO3 / stub-only conventions (see stubtest-allowlist.txt). | |
| # --ignore-disjoint-bases keeps the gate stable across mypy upgrades: the | |
| # dual-base exceptions (e.g. Timeout(ProcessError, TimeoutError)) are PEP 800 | |
| # disjoint-base candidates a future mypy could start flagging. | |
| - run: uv run python -m mypy.stubtest processkit --ignore-disjoint-bases --allowlist stubtest-allowlist.txt | |
| rust-lint: | |
| name: rust-lint | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| # PyO3's build script needs a Python interpreter to resolve its config (even | |
| # for a check-only clippy build, which never links libpython). Pin one | |
| # explicitly rather than relying on the runner image's preinstalled python. | |
| - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 | |
| with: | |
| python-version: '3.x' | |
| - uses: dtolnay/rust-toolchain@67ef31d5b988238dd797d409d6f9574278e20537 # stable | |
| with: | |
| toolchain: stable | |
| components: clippy, rustfmt | |
| - run: cargo fmt --all --check | |
| - run: cargo clippy --all-targets -- -D warnings | |
| test: | |
| # One matrix over (OS × interpreter): the empty `python` entry runs the abi3 | |
| # (GIL) build via the project's pinned interpreter; `3.14t` provisions the | |
| # free-threaded CPython (PEP 703) and builds the version-specific (non-abi3) | |
| # extension, exercising the suite with the GIL disabled. | |
| name: test (${{ matrix.os }}, ${{ matrix.python || 'abi3' }}) | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, ubuntu-24.04-arm, windows-latest, macos-latest] | |
| python: ['', '3.14t'] | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - uses: dtolnay/rust-toolchain@67ef31d5b988238dd797d409d6f9574278e20537 # stable | |
| with: | |
| toolchain: stable | |
| - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 | |
| with: | |
| enable-cache: true | |
| # `uv run` provisions the interpreter, syncs the env (building the Rust | |
| # extension via `maturin develop`), then runs pytest. The `--python` flag is | |
| # added only for the free-threaded entry. | |
| - run: uv run ${{ matrix.python && format('--python {0} ', matrix.python) }}pytest | |
| build: | |
| name: build (${{ matrix.os }}) | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, ubuntu-24.04-arm, windows-latest, macos-latest] | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - uses: dtolnay/rust-toolchain@67ef31d5b988238dd797d409d6f9574278e20537 # stable | |
| with: | |
| toolchain: stable | |
| - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 | |
| with: | |
| enable-cache: true | |
| # Verify the abi3 wheel (cp310+) builds on every target OS, not just Linux — | |
| # a one-OS build would not catch a Windows/macOS packaging break. A debug | |
| # build (no --release) exercises the same abi3 tag / cdylib link / packaging | |
| # path much faster. The optimized (LTO) wheels are built + smoke-tested by | |
| # cibuildwheel: musl x86_64 here (build-musllinux), and the FULL matrix | |
| # (every OS/arch, incl. Windows/macOS) pre-pivot in the release flow — so a | |
| # release-profile-only break can't reach PyPI, it just surfaces at release. | |
| - run: uv run maturin build --out dist | |
| # The sdist is platform-independent; build it once. | |
| - if: matrix.os == 'ubuntu-latest' | |
| run: uv run maturin sdist --out dist | |
| # Assert the release cibuildwheel selector resolves to exactly the intended | |
| # wheel families per libc — the abi3 GIL wheel (cp310) and the free-threaded | |
| # cp314t wheel, for both manylinux (glibc) and musllinux (musl) — so a | |
| # renamed/dropped/re-skipped identifier surfaces here, not at release. (The | |
| # musllinux wheels are actually built + smoke-tested in the build-musllinux | |
| # job below; this only checks the selector resolves.) | |
| - if: matrix.os == 'ubuntu-latest' | |
| name: Verify cibuildwheel build selector | |
| run: | | |
| ids=$(uvx 'cibuildwheel>=4,<5' --print-build-identifiers --platform linux) | |
| echo "$ids" | |
| for fam in cp310-manylinux cp310-musllinux cp314t-manylinux cp314t-musllinux; do | |
| echo "$ids" | grep -q "^$fam" || { echo "::error::$fam wheel not in cibuildwheel selector"; exit 1; } | |
| done | |
| build-musllinux: | |
| # Actually build + smoke-test the musllinux (Alpine/musl) wheels. This is the | |
| # only thing on a push that exercises the musl Rust toolchain path — | |
| # cibuildwheel otherwise runs only in the dispatch-only release flows, so a | |
| # musl-specific break (the before-all hook, maturin's cdylib crt-static | |
| # handling) would otherwise surface only at release. Builds both wheel families | |
| # for x86_64 in the Alpine container (Rust is installed inside it by the | |
| # before-all hook in pyproject.toml — no host toolchain needed); aarch64 musl | |
| # builds natively at release on the ubuntu-24.04-arm runner. | |
| name: build (musllinux x86_64) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 | |
| with: | |
| enable-cache: true | |
| - name: Build + smoke-test musllinux wheels | |
| # Pin the exact two families (abi3 GIL + free-threaded). CIBW_BUILD | |
| # OVERRIDES pyproject's build selector, so a wildcard like *-musllinux_x86_64 | |
| # would also pull cp311–cp314 (redundant abi3-reuse smoke runs). | |
| env: | |
| CIBW_BUILD: "cp310-musllinux_x86_64 cp314t-musllinux_x86_64" | |
| run: uvx 'cibuildwheel>=4,<5' --platform linux --output-dir wheelhouse | |
| audit: | |
| name: pip-audit | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 | |
| with: | |
| enable-cache: true | |
| # Audit the locked dependency tree. Exporting the lockfile (--no-emit-project | |
| # drops the editable binding itself) lets pip-audit scan the deps without | |
| # building the Rust extension — so no rust-toolchain / compile step is needed. | |
| # The project has no runtime deps, so the dev groups ARE the audit surface: | |
| # --all-groups makes that explicit (not reliant on uv's default-includes-dev), | |
| # and --locked pins the scan to the committed uv.lock (failing loudly if stale). | |
| - run: >- | |
| uv export --no-emit-project --all-groups --locked | |
| --format requirements-txt --output-file requirements-audit.txt | |
| - run: uvx 'pip-audit>=2,<3' -r requirements-audit.txt |