RUST Contents

CI Basics

Set up a minimal but production-ready CI pipeline for Rust: format checks, linting, tests, and build validation to ensure every change is safe to merge.

On this page

CI Is Your Automated Reviewer

Continuous Integration (CI) is not just about running tests. It is your automated reviewer that ensures every commit meets baseline quality before reaching production. A clean CI pipeline prevents broken builds, inconsistent formatting, lint regressions, and hidden test failures.

Production mindset:

  • CI must be deterministic
  • CI must be fast enough to run on every PR
  • CI failures must be actionable

Minimum Viable CI for Rust

A practical production baseline includes:

  • cargo build
  • cargo fmt check
  • cargo clippy (warnings as errors)
  • cargo test

Step 1: Build Validation

Always ensure the project compiles in CI.

cargo build --workspace --all-targets --locked

Use the --locked flag to guarantee Cargo.lock is respected and dependency versions are reproducible.

Step 2: Formatting Check

cargo fmt -- --check

This ensures contributors run rustfmt locally.

Step 3: Linting

cargo clippy --workspace --all-targets -- -D warnings

Treat warnings as errors to prevent slow accumulation of technical debt.

Step 4: Run Tests

cargo test --workspace --all-targets --locked

Production rule: CI must not rely on external services unless explicitly controlled (e.g., test containers).

Example GitHub Actions Workflow

Minimal workflow file:

# .github/workflows/ci.yml
name: CI

on:
  push:
    branches: [ main ]
  pull_request:

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - uses: dtolnay/rust-toolchain@stable

      - name: Cache cargo registry
        uses: actions/cache@v3
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
          key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}

      - name: Build
        run: cargo build --workspace --all-targets --locked

      - name: Format
        run: cargo fmt -- --check

      - name: Clippy
        run: cargo clippy --workspace --all-targets -- -D warnings

      - name: Test
        run: cargo test --workspace --all-targets --locked

This is intentionally minimal and production-safe.

Reproducibility and Toolchain Pinning

To avoid surprises when Rust updates, pin the toolchain.

# rust-toolchain.toml
[toolchain]
channel = "1.76.0"

Production rule: do not let CI randomly change compiler versions.

Fail Fast and Clear

Order CI steps from fastest to slowest:

  • Format
  • Clippy
  • Build
  • Tests

This reduces wasted compute time when formatting or linting already fails.

Parallel Jobs (Optional Later)

As your project grows, you may split jobs:

  • Lint job
  • Test job
  • Coverage job

But start simple. Complexity in CI is a production risk if not needed.

Common Production Pitfalls

  • Allowing CI to pass with warnings
  • Using nightly toolchain unintentionally
  • Running tests that depend on external APIs
  • Slow CI discouraging developers from running it locally
  • Ignoring failing CI temporarily and merging anyway

Production Checklist

  • cargo build with --locked
  • cargo fmt check
  • cargo clippy with -D warnings
  • cargo test for workspace
  • Pinned Rust toolchain
  • CI runs on every PR

A minimal, strict CI pipeline keeps your Rust project production-grade. It ensures that code style, correctness, and compilation are guaranteed before any change reaches main.