Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 34 additions & 4 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
# Test + clippy on every push/PR; on a version tag (`vX.Y.Z`) build wheels + sdist and attach them
# to a GitHub Release. crates.io is published manually (`cargo publish`). No PyPI — install the
# Python package from a release wheel or `pip install git+https://github.com/prostomarkeloff/directiva`.
# to a GitHub Release. crates.io is published manually (`cargo publish`).
#
# No secrets needed — the GitHub Release uses the built-in GITHUB_TOKEN.
# PyPI is published manually too, from the all-platform wheels this matrix produces (a local
# `uv build` only covers the current platform, so publish from the CI set):
# gh release download vX.Y.Z -D dist # every wheel + the sdist the release job attached
# uv publish dist/* # needs a PyPI token (UV_PUBLISH_TOKEN / --token)
# `make dist-fetch TAG=vX.Y.Z` + `make publish` wrap exactly those two steps.
#
# No secrets needed in CI — the GitHub Release uses the built-in GITHUB_TOKEN; the PyPI token lives
# only on the maintainer's machine for `uv publish`.
#
# abi3 (pyo3 abi3-py39) → one wheel per platform/arch works on CPython 3.9+, so no per-Python matrix.
name: CI
Expand Down Expand Up @@ -65,6 +71,30 @@ jobs:
name: wheels-linux-${{ matrix.target }}
path: dist

# musl wheels (Alpine and the many slim Docker bases that ship musl libc, not glibc). Without
# these, `pip install directiva` on Alpine falls back to the sdist and needs a Rust toolchain.
musllinux:
runs-on: ubuntu-latest
strategy:
matrix:
target: [x86_64, aarch64]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Build wheels
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.target }}
args: --release --out dist
sccache: "true"
manylinux: musllinux_1_2
- uses: actions/upload-artifact@v4
with:
name: wheels-musllinux-${{ matrix.target }}
path: dist

macos:
runs-on: macos-latest
strategy:
Expand Down Expand Up @@ -122,7 +152,7 @@ jobs:
name: GitHub release (wheels + sdist)
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/')
needs: [test, linux, macos, windows, sdist]
needs: [test, linux, musllinux, macos, windows, sdist]
permissions:
contents: write
steps:
Expand Down
34 changes: 33 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@

.DEFAULT_GOAL := help

.PHONY: help check test clippy fmt fmt-check lint build py-dev py-test fuzz-parse fuzz-glob clean
.PHONY: help check test clippy fmt fmt-check lint build py-dev py-test fuzz-parse fuzz-glob \
dist dist-fetch publish clean

help:
@echo "directiva targets:"
Expand All @@ -21,6 +22,9 @@ help:
@echo " make py-test py-dev + a Python import/parse/match/lint smoke test"
@echo " make fuzz-parse cargo-fuzz the parser (needs nightly + cargo-fuzz)"
@echo " make fuzz-glob cargo-fuzz the glob engine (needs nightly + cargo-fuzz)"
@echo " make dist uv build → sdist + a wheel for THIS platform only (local smoke check)"
@echo " make dist-fetch TAG=vX.Y.Z download every CI-built wheel + sdist from the GH release"
@echo " make publish uv publish dist/* (run after dist-fetch; needs a PyPI token)"
@echo " make clean cargo clean + remove .venv and built artefacts"

check: fmt-check clippy test
Expand Down Expand Up @@ -68,6 +72,34 @@ fuzz-parse:
fuzz-glob:
cargo +nightly fuzz run glob -- -max_total_time=$(FUZZ_TIME)

# ── publishing ──────────────────────────────────────────────────────────────────
# PyPI gets PREBUILT wheels for every platform so `pip install directiva` never needs a compiler.
# Those wheels come from the CI matrix (linux x86_64/aarch64, macOS x86_64/arm64, windows x64) +
# the sdist — NOT from a local build. Release flow:
# 1. bump `version` in Cargo.toml, commit
# 2. git tag vX.Y.Z && git push --tags → CI builds the matrix, attaches it to the GH release
# 3. make dist-fetch TAG=vX.Y.Z → pull that whole set into ./dist
# 4. make publish → uv publish dist/* (PyPI token via UV_PUBLISH_TOKEN)

# Local build — ONE wheel (this platform) + the sdist. A smoke check / for inspecting the artifact;
# never the thing you publish (it would leave every other platform falling back to a source build).
dist:
rm -rf dist
uv build

# Pull the all-platform wheels + sdist the CI `release` job attached to TAG, into ./dist. This is
# the set to publish. Needs the `gh` CLI authenticated to the repo.
dist-fetch:
@test -n "$(TAG)" || { echo "usage: make dist-fetch TAG=vX.Y.Z"; exit 2; }
rm -rf dist && mkdir -p dist
gh release download "$(TAG)" -D dist
@echo "fetched into ./dist:" && ls dist

# Upload everything in ./dist to PyPI. Run after `make dist-fetch TAG=…`. Reads the token from
# UV_PUBLISH_TOKEN (or pass `uv publish --token …` yourself).
publish:
uv publish dist/*

clean:
cargo clean
rm -rf .venv dist fuzz/target fuzz/corpus fuzz/artifacts
19 changes: 7 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -280,22 +280,17 @@ The package is **typed** (`py.typed` + stubs; `Severity` is a `Literal`), and ga
`python` cargo feature so the pure-Rust crate keeps **zero** Python dependency by default. Built with
[maturin](https://github.com/PyO3/maturin) (abi3 — one wheel per platform works on **CPython ≥ 3.9**).

**No PyPI.** Two ways to install:

**1. Prebuilt wheel — no Rust toolchain.** Grab the wheel for your platform from the
[Releases page](https://github.com/prostomarkeloff/directiva/releases/latest) and install it by URL:

```bash
pip install https://github.com/prostomarkeloff/directiva/releases/download/v0.2.0/directiva-0.2.0-cp39-abi3-macosx_11_0_arm64.whl
```

**2. From source — needs a Rust toolchain** (pip drives maturin automatically):
**Install — prebuilt, no Rust toolchain:**

```bash
pip install git+https://github.com/prostomarkeloff/directiva
pip install directiva # or: uv add directiva
```

Build locally into a venv with `maturin develop --features python`.
Prebuilt abi3 wheels are on PyPI for Linux (x86_64, aarch64), macOS (x86_64, arm64) and Windows
(x64) — pip picks the one for your platform, no compiler involved. On a platform with no matching
wheel, pip falls back to the sdist, which **does** need a Rust toolchain (it drives maturin
automatically). For local development, build the extension into a venv with `make py-dev`
(`maturin develop --features python`).

---

Expand Down
Loading