Releasing robin-sparkless¶
This document describes how to cut a release and publish:
The repository is a Cargo workspace with members: robin-sparkless (root, main facade), crates/robin-sparkless-core, crates/robin-sparkless-polars, crates/spark-sql-parser, and the Python extension crate under python/. The primary Rust dependency for users is robin-sparkless; the subcrates may be published for advanced or minimal-use cases. make check and CI build the whole workspace (cargo build --workspace --all-features, cargo test --workspace --all-features).
Version pinning (CI and local)¶
So that local development and CI use the same toolchains and tools:
- Rust: rust-toolchain.toml pins the Rust version (e.g. 1.93.1). CI uses the same
toolchainvalue in .github/workflows/ci.yml and .github/workflows/release.yml. - cargo-nextest: CI installs a fixed version (e.g. 0.9.92) in the workflow. Use the same version locally if you use nextest.
Pre-release checklist (e.g. X.Y.Z)¶
- [ ] Versions — Root, robin-sparkless-core, and robin-sparkless-polars
Cargo.tomlhave the sameversion(e.g.4.x.y). RootCargo.tomlpath deps use matchingversion = "4"(or"4.x"). Pythonpython/pyproject.tomlandpython/Cargo.tomlversion match if releasing Python. - [ ] CHANGELOG — Add
[X.Y.Z] - YYYY-MM-DDsection with Added/Changed/Fixed; move Unreleased items or leave Unreleased for next. - [ ] README — Rust install examples use the major version or the new release version (e.g.
robin-sparkless = "4"orrobin-sparkless = "4.x.y"). - [ ] CI —
make check-fullpasses (format, clippy, audit, deny, Rust tests, Python lint). Push to a branch and confirm CI green. - [ ] Secrets — GitHub repo has
CARGO_REGISTRY_TOKEN(crates.io) andPYPI_API_TOKEN(PyPI) if publishing Python. - [ ] Tag — After merge to
main,git tag vX.Y.Zandgit push origin vX.Y.Z; release workflow runs automatically.
Prerequisites¶
- The repository must have a GitHub Actions secret named
CARGO_REGISTRY_TOKENset to a crates.io API token. - The repository must have a GitHub Actions secret named
PYPI_API_TOKENset to a PyPI API token for thesparklessproject. - Create a token at crates.io/settings/tokens (requires a crates.io account). Store it as a repo secret in GitHub under Settings → Secrets and variables → Actions.
- Create a PyPI token at pypi.org/manage/account/token and store it as
PYPI_API_TOKENunder the same GitHub settings.
Release steps¶
- Bump the version in all Rust and Python manifests so they stay in sync:
- Cargo.toml (root,
robin-sparkless) - crates/robin-sparkless-core/Cargo.toml
- crates/robin-sparkless-polars/Cargo.toml
- crates/spark-sql-parser/Cargo.toml
- python/pyproject.toml (Python package metadata)
- python/Cargo.toml (native extension crate)
Use the same version for the three robin-sparkless crates and the Python package (e.g. 4.x.y). spark-sql-parser can use the same version or its own (e.g. 0.x.y). Update the version in root and the crates; if you publish the subcrates, also update the dependency version in root (e.g. robin-sparkless-core = { version = "4", path = "..." }, robin-sparkless-polars = { version = "4", path = "..." }). Commit and push to main.
- Create and push a tag matching the version with a
vprefix:
-
Release workflow runs automatically on the tag push (see .github/workflows/release.yml):
-
Rust checks:
- Format check, Clippy (workspace),
cargo audit,cargo deny - Build and tests for the whole workspace
cargo doc --workspace
- Format check, Clippy (workspace),
- Crates.io publish (Rust) in dependency order:
spark-sql-parserrobin-sparkless-corerobin-sparkless-polarsrobin-sparkless
- Python checks:
- Mypy over the Python sources
- Build per-OS wheels for the native extension (Ubuntu, macOS, Windows)
- Python smoke tests + fast pytest subset against the built wheel across a Python version/OS matrix
-
PyPI publish (Python):
sparklesswheels and sdist are published to PyPI for:- manylinux x86_64 + sdist
- manylinux aarch64
- musllinux x86_64
- musllinux aarch64
- macOS (x86_64-apple-darwin, aarch64-apple-darwin)
- Windows (x86_64, aarch64)
-
Verify:
- Rust:
- crates.io/crates/robin-sparkless
- robin-sparkless-core
- robin-sparkless-polars
- spark-sql-parser
- Their docs on docs.rs after the workflow completes.
- Python:
- pypi.org/project/sparkless
pip install sparkless==X.Y.Zin a clean virtualenv and a quickfrom sparkless.sql import SparkSessionsmoke test.
Version policy¶
- Tags must match the version in the root
Cargo.toml(e.g. tagvX.Y.Zonly when root and both crates haveversion = "X.Y.Z"). - Do not re-tag or overwrite tags; crates.io does not allow republishing the same version.
- The three robin-sparkless crates are published with the same version number so that the main crate can depend on
robin-sparkless-core = "4"androbin-sparkless-polars = "4"and resolve to the matching v4 release.spark-sql-parsermay use a separate version (e.g.0.x.y).
Manual publish (optional)¶
If you need to publish from the repo without using the tag workflow (e.g. a one-off fix for one crate), use the same order so dependencies exist on crates.io:
cargo publish -p spark-sql-parser --token <CRATES_IO_TOKEN>
cargo publish -p robin-sparkless-core --token <CRATES_IO_TOKEN>
cargo publish -p robin-sparkless-polars --token <CRATES_IO_TOKEN>
cargo publish -p robin-sparkless --token <CRATES_IO_TOKEN>
Ensure the version in each crate’s Cargo.toml is bumped and that dependency version fields in root match the versions you are publishing.
Notes on the Python package¶
- The Python package
sparkless(v4+) is published from this repository’spython/directory. - Wheels are built using maturin with a
pyo3-based native extension crate (sparkless-native) that links againstrobin-sparkless. - The package exposes
from sparkless.sql import SparkSessionand uses a privatesparkless._nativemodule for the Rust bindings. The legacysparkless_robinmodule name is no longer used.