Skip to content

onorepo orchestration for Rust workspaces. Graph-aware testing, dependency unification, crate extraction. 11 dependencies.

License

Notifications You must be signed in to change notification settings

loadingalias/cargo-rail

Repository files navigation

cargo-rail

Zero-waste orchestration for Rust monorepos.

Crates.io License Rust Version

Stop wasting CI time. Stop fighting workspace dependencies. Stop copy-pasting git history.

cargo install cargo-rail

What It Does

cargo-rail solves the three hardest problems in Rust monorepos:

Problem Solution Impact
🔥 Testing everything on every PR Graph-aware change detection 10x faster CI
💥 Dependency fragmentation Resolution-based unification Zero workspace-hack crates
🔨 Distributing crates History-preserving split/sync One command, full git history

Quick Start

1. Smart Testing (10x faster CI)

# Only test what changed
cargo rail test

# Explain why each crate is tested
cargo rail test --explain

Before:

- run: cargo test --workspace  # Tests everything (12 minutes)

After:

- run: cargo rail test --nextest  # Tests only affected crates (1 minute)

2. Dependency Unification (replaces cargo-hakari)

# Preview unification changes
cargo rail unify --dry-run

# Apply unification to workspace.dependencies
cargo rail unify

What it does:

  • Uses Cargo's actual dependency resolution, not just syntax
  • Merges feature sets intelligently from resolved features
  • No workspace-hack crate needed
  • Lossless TOML editing (preserves comments & formatting)

3. Crate Distribution (replaces Copybara)

# Split a crate to standalone repo with full git history
cargo rail split my-crate

# Bidirectional sync
cargo rail sync my-crate

What it does:

  • Preserves complete git history (commits, tags, blame)
  • Deterministic: same input = same commit SHAs
  • Uses git-notes for rebase-safe commit mapping
  • No libgit2/gitoxide dependency (pure system git)

Why cargo-rail?

Resolution-Based Unification

Unlike cargo-hakari's syntax-only approach, cargo-rail uses Cargo's actual resolver:

# crate-a
tokio = "1.0"

# crate-b
tokio = "^1.5"

# Both resolve to tokio 1.5.3 → compatible!
# cargo-rail merges them intelligently:
[workspace.dependencies]
tokio = { version = "1.5", features = ["rt", "net", "sync"] }

No workspace-hack crate. Just native workspace.dependencies.

Graph-Aware Change Detection

$ cargo rail affected --explain

Changed files:
  crates/core/src/lib.rs (source)
  docs/guide.md (docs)

Affected crates:
  ✓ core (direct change)
  ✓ api (depends on core)
  ✓ cli (depends on api)

Skipping:
  ✗ examples (no dependency path)
  ✗ docs (docs-only change)

Running: cargo nextest run -p core -p api -p cli

Real impact: 70-90% reduction in test time on large workspaces.

Deterministic Git Operations

Uses system git directly for maximum fidelity:

# Split preserves full history
git log --oneline
abc123 feat: add new feature
def456 fix: critical bug
...

# Same commits, same SHAs in split repo
cd ../my-crate-standalone
git log --oneline
abc123 feat: add new feature  # Same SHA!
def456 fix: critical bug      # Same SHA!

Architecture

Zero Abstraction

  • System git only – No libgit2/gitoxide dependency overhead
  • Direct graph constructioncargo_metadata + petgraph (no guppy)
  • 8 core dependencies – Minimal, auditable supply chain

Design Principles

  1. Single workspace load – Build context once, reuse everywhere
  2. Graph-first – All operations use the dependency graph
  3. Lossless editing – Preserve formatting, comments, structure
  4. Deterministic – Same input always produces same output

Configuration

Create .config/rail.toml:

# Toolchain management
[toolchain]
channel = "stable"
components = ["clippy", "rustfmt"]

# Dependency unification
[unify]
consolidate_transitive_features = false  # Consolidate transitive deps
transitive_feature_host = "auto"         # Smart auto-selection
validate_targets = []

# Split/sync (optional)
[[splits]]
name = "my-crate"
remote = "[email protected]:org/my-crate.git"
mode = "single"

See .config/rail.toml.example for all options.


Commands

Change Analysis

cargo rail affected                    # Show affected crates
cargo rail affected --since main       # Compare against branch
cargo rail test                        # Test affected crates
cargo rail test --nextest --watch      # Watch mode with nextest

Dependency Unification

cargo rail unify --dry-run             # Preview changes
cargo rail unify                       # Apply unification

Crate Distribution

cargo rail split my-crate              # Split to standalone repo
cargo rail sync my-crate               # Bidirectional sync
cargo rail status                      # Show sync status

Release Automation

cargo rail release plan --all          # Plan release
cargo rail release publish --execute   # Publish to crates.io

Comparison

Feature cargo-rail cargo-hakari Copybara
Dependency unification ✅ Resolution-based ✅ Syntax-only
Workspace-hack crate ❌ Not needed ✅ Required
Git history preservation ✅ Full ⚠️ Partial
Bidirectional sync
Deterministic ✅ Same SHAs N/A
Smart testing ✅ Graph-aware
Dependencies 8 core ~40+ (via guppy) Go ecosystem

Real-World Impact

Before

# CI takes 12 minutes testing entire workspace
# Maintain workspace-hack crate manually
# Use git-filter-repo scripts for splits

After

# CI takes 1-2 minutes testing only affected crates
# cargo rail unify (one command)
# cargo rail split my-crate (one command, full history)

Installation

# From crates.io
cargo install cargo-rail

# From source
git clone https://github.com/loadingalias/cargo-rail
cd cargo-rail
cargo install --path .

Development

# Build
cargo build --release

# Test
cargo test

# Quality checks
just check

Contributing

Contributions welcome! Please:

  1. Open an issue first for major changes
  2. Run just check before submitting
  3. Add tests for new features
  4. Update docs as needed

License

MIT License - see LICENSE for details.


Credits

Built with cargo_metadata, petgraph, toml_edit, and clap.

Inspired by cargo-hakari's unification approach and Copybara's monorepo concepts.


Ready to stop wasting time? cargo install cargo-rail