Skip to content

feat(rust-sdk): ergonomic cargo options, nextest, ci(), cargo-hack (Py+TS parity)#143

Merged
markovejnovic merged 16 commits into
mainfrom
feat/better-rust-sdk
Jun 12, 2026
Merged

feat(rust-sdk): ergonomic cargo options, nextest, ci(), cargo-hack (Py+TS parity)#143
markovejnovic merged 16 commits into
mainfrom
feat/better-rust-sdk

Conversation

@markovejnovic

Copy link
Copy Markdown
Contributor

What

Overhauls the hm.rust pipeline-authoring helper in both DSLs so a Rust CI pipeline is one call:

proj = hm.rust.project()
hm.pipeline(list(proj.ci(nextest=True)))   # nextest + doctest + clippy + fmt

Every action method now takes research-backed cargo options

packages=, exclude=, features=, all_features=, no_default_features=, target=, release=/profile=, locked= (defaults True for reproducible CI), workspace=, plus a generic flags= escape hatch. The surface is symmetric across build/test/clippy/fmt/doc on both RustToolchain and RustProject.

New capabilities

  • test(nextest=True)cargo nextest run; companion doctest() step (nextest can't run doctests).
  • RustProject.build() and .doc() (previously missing).
  • RustProject.ci(nextest=, doc=) → the zero-config DAG (test + clippy + fmt, +doctest under nextest).
  • feature_powerset() → cargo-hack --feature-powerset --depth 2 --no-dev-deps (the tokio/reqwest/tracing idiom), with a path-independent, forever-cached install step.

Hardening

  • Shell-injection fix: every user-supplied value (packages, exclude, features, target, profile, cargo-hack skip/include) is shell-quoted (shlex.quote / shQuote). Raw flags= stay verbatim (escape hatch). Regression tests added.
  • Conflicting options raise precise errors per the repo's error-message doctrine: all_features + features/no_default_features; release + profile; exclude without workspace (cargo requires it); exclude with explicit packages.

Parity

Both DSLs route through a shared cargo-argument assembler (_cargo.py / cargo.ts) and shQuote replicates Python's shlex.quote byte-for-byte. Golden-string parity tests pin identical cargo commands across Python and TypeScript; the regenerated rust-release e2e fixtures are byte-identical across languages and pass the Rust IR-deserialization tests.

Why

Flag choices are evidence-based: surveyed CI of ~30 top Rust repos (tokio, ripgrep, rust-analyzer, ruff, axum, reqwest, rustls, sqlx, wgpu, …). --locked is the community standard for reproducible CI; nextest is dominant in large workspaces and always splits doctests into a separate step; cargo clippy --all-targets -- -D warnings and cargo fmt --all --check are the canonical lint/fmt invocations; cargo-hack --feature-powerset --depth 2 is the standard combinatorial-feature sweep.

Backwards compatibility

Additive except: RustToolchain.build/test now emit --locked by default (pass locked=False to opt out); RustProject.clippy uses --all-targets instead of --tests; fmt defaults to --all --check. Examples and e2e fixtures updated accordingly.

Tests

  • Python: 543 passed, ruff + mypy clean.
  • TypeScript: 405 passed, tsc + build clean.
  • Rust: 14 e2e fixture tests pass (deserialization + cross-language parity).
  • New: per-method unit tests on both classes/langs, shell-injection regression tests, and 6 cross-language golden-parity assertions.

Ports harmont-py/harmont/_cargo.py to TypeScript: CargoOpts interface,
shQuote (shlex.quote-identical), and cargoFlags assembler with full
validation (exclude/workspace pairing, allFeatures/features conflict,
release/profile conflict). 18 tests, all passing, tsc clean.
…extest

The example switched to rust.project().ci(), whose warmup runs
'cargo build --workspace --tests --locked' — which needs a committed
Cargo.lock. Add the (dependency-free) lockfile. Drop nextest=True from
the runnable example since the example-runner VM only rustup-installs
stable (no cargo-nextest); nextest stays documented as an opt-in.
# Conflicts:
#	examples/rust/.hm/pipeline.py
@markovejnovic markovejnovic merged commit 46d96be into main Jun 12, 2026
17 of 18 checks passed
@markovejnovic markovejnovic deleted the feat/better-rust-sdk branch June 12, 2026 00:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant