ModernCIPush. Green. Merged.

CI for Rust

ModernCI runs your cargo commands unchanged and adds Rust-aware handling around them. It narrows test runs to the crates a change touches (Cargo's affected set), reads per-test results from cargo-nextest and libtest, fails a test check that ran zero tests, resolves Cargo.lock and Cargo.toml merge conflicts by itself, and reuses a green result only for identical inputs. ModernCI is itself a Rust workspace tested this way. Speed against other Rust CI setups: measurement in progress.

Marks: live is in release 0.4.28 on main; preview is built in an open pull request, not released; planned is decided, not built.

A branch file for a Rust workspace

yaml
# .ci/default.yaml: what a branch must pass to merge into main
to: main
on_green: merge
deadline: 45m
env: { CARGO_INCREMENTAL: "0" }
checks:
  fmt:    { run: cargo fmt --all -- --check }
  clippy: { run: cargo clippy --workspace --all-targets -- -D warnings, needs: [fmt] }
  test:   { run: cargo nextest run --workspace, needs: [fmt], scope: affected }

The file is read from the target branch, never from the pull request. live

What is Rust-specific

CapabilityMarkDetail
Affected crates onlylivescope: affected narrows a check to the crates a change touches, from the Cargo workspace.
Per-test resultslivecargo-nextest and libtest output is parsed per test. A test check that ran zero tests fails.
Failures already on the targetliveA test that also fails on the target branch is listed apart and isn't charged to the pull request.
Flaky testslive (nextest)A suspect is re-run alone once, then quarantined: still run and reported, never blocking. Plain cargo test re-runs are planned.
Lockfile conflictsliveConflicts only in Cargo.lock, Cargo.toml (and package*.json, go.mod, go.sum, changelogs) are resolved in one labelled merge commit, then tested in full.
Result reuseliveA green result is reused only for the same input key: the whole tree plus declared inputs.
Reuse keyed by build environmentpreviewKeys include the backend's toolchain environment (on dev, #56).
Pinned toolsliveTools a check needs are fetched per pin and verified by sha256 per architecture.
Cargo accelerationpreviewA target directory per build environment, with dependency layers restored into fresh work directories (PR #54).
Compiler-cache supervisionpreviewA declared shared service (such as an sccache server) gets a canary every 5 minutes and is restarted when it hangs (PR #83).
Affected-set parse in pure RustplannedToday the affected set uses Cargo's own metadata.

Where Rust builds run

On your own machine (each check as an unprivileged user), over ssh, or on Latchkey elastic runners: a fresh runner per job, billed per minute. The commit under test is packed by the daemon as a git bundle, so no Git provider token reaches the runner. Each pull request goes on the cheapest backend that meets its deadline. live

Evidence

  • ModernCI's own workspace (fmt, clippy -D warnings, tests, a load-test gate) is tested by ModernCI on every change.
  • Clean and incremental build times compared with GitHub Actions, Blacksmith and Namespace: measurement in progress. The method, runner specs and commands are on benchmarks.
  • Measured baseline (busbar, a Rust workspace, 2026-10-12 to 13, one 8-vCPU host): the test check took 243 s at p50 and 961 s at p95, and the median push to green result was 43 min, 37 min of it queued behind checks run one after another.

Limitations

  • In 0.4.28 one pull request's checks run one after another. Parallel checks are planned (PR #93 is a first cut).
  • A fresh elastic runner starts cold unless a cache is restored. Cargo acceleration is in preview, not released.
  • A shared sccache server on our own install has hung several times. Supervising it is in preview (PR #83), and ModernCI's own build cache (PR #54) replaces it.
  • Affected-test selection exists only for Cargo.

See also: AI coding agents, benchmarks, facts.