Skip to content

Contributing

Thanks for helping with originet. Bugs and proposals go through issues; code through pull requests.

Setup

git clone git@github.com:estcarisimo/originet.git && cd originet
cargo build                       # the CLI: target/debug/originet
cargo test --workspace --all-features
cd python && uv sync --locked     # builds the extension in editable mode (needs Rust)
uv run pytest

Requirements: Rust 1.88 or newer (rust-version in Cargo.toml), and for the Python bindings uv and Python 3.10 or newer. Build the extension with uv sync (maturin), not with cargo build --workspace: a pyo3 extension-module cannot be linked by cargo alone (cargo clippy --workspace and cargo test --workspace are fine, they do not link it). On an Apple Silicon Mac the Rust toolchain must be the arm64 one (rustup); an x86_64 Homebrew toolchain cannot build the extension for an arm64 Python.

Checks that CI runs, in the same order:

cargo fmt --all --check
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo clippy -p originet --all-targets --no-default-features -- -D warnings
RUSTDOCFLAGS="-D warnings" cargo doc -p originet --no-deps --all-features
cargo deny check                  # cargo install cargo-deny
cargo test --workspace --all-features --locked
cargo test -p originet --no-default-features --locked
(cd python && uv run ruff check . && uv run ruff format --check . && uv run mypy && uv run pytest -q)
docker build -t originet .
uvx --with-requirements docs/requirements.txt mkdocs build --strict

Tests never touch the network: they use the fixtures in tests/fixtures/ and a seeded cache directory. Keep it that way; a test that needs CAIDA is an #[ignore] test.

Pull requests

  • Branch from main; never push to main directly (the protect-main ruleset enforces a pull request with green checks).
  • Every PR gets an independent review following .github/REVIEW.md and is merged only after VERDICT: APPROVE on its final commit with CI green.
  • Add a bullet under [Unreleased] in CHANGELOG.md for user-visible changes.
  • American English in identifiers, comments, docs and the changelog.
  • Every documented command is run before it is written down; example output is a real capture.
  • A change to the Python API updates python/originet/_native.pyi and python/tests/ too.
  • Dependencies: pinned to SHAs in workflows; new crates must pass cargo deny check (license allow-list in deny.toml).

Releases

  1. Move [Unreleased] in CHANGELOG.md to ## [X.Y.Z] - YYYY-MM-DD.
  2. Set version to X.Y.Z in Cargo.toml, python/Cargo.toml, python/pyproject.toml and CITATION.cff (with date-released); run cargo update --workspace and (cd python && uv lock) so the lockfiles follow.
  3. Merge that PR, then tag vX.Y.Z on main and push the tag.

The release workflow checks that the tag, the four versions and the changelog agree and that the tag is on main; then it creates the GitHub release with the changelog section, attaches binaries (Linux x86_64/aarch64 musl, macOS x86_64/arm64, Windows x86_64), builds the wheels and the sdist, and pushes ghcr.io/estcarisimo/originet.

Publishing to PyPI and crates.io is gated by the repository variables PYPI_PUBLISH and CRATES_IO_PUBLISH (true to publish) and uses OIDC Trusted Publishing, no stored tokens. One-time setup per registry:

  • PyPI: a pending publisher for originet (owner estcarisimo, repository originet, workflow release.yml, environment pypi) can be created before the first upload, so the workflow can publish the first version.
  • crates.io has no pending publisher: the first version is uploaded by hand (cargo login with a token scoped to publish-new for originet, then cargo publish -p originet --locked from main), the trusted publisher is added in the crate's settings (owner estcarisimo, repository originet, workflow release.yml, environment crates-io), and the token is revoked. The workflow skips a version that is already on the registry, so tagging that same version afterwards is safe.