Introduction: Why Advanced CI/CD is Important for Rust Projects
A basic CI/CD pipeline for Rust is good, but in real projects, especially those with multiple platforms, dependencies, and the need for fast feedback, a simple cargo test is not enough. Advanced GitHub Actions configuration allows you to reduce build time by 2-3 times, automatically check code on different architectures, publish crates, and perform linting.
In this article, we will cover advanced techniques: dependency caching, build matrices for Windows/macOS/Linux, parallel test execution, publishing to crates.io, and integration with Clippy.
1. Build Time Optimization: Caching and Incremental Compilation
The most expensive operation in CI for Rust is compiling dependencies. Without caching, each run will download and build all crates from scratch. The solution is to use the built-in GitHub Actions cache.
Basic target Directory Caching
jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions-rust-lang/setup-rust-toolchain@v1 - name: Cache Rust dependencies uses: actions/cache@v3 with: path: | ~/.cargo/registry ~/.cargo/git target key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - run: cargo build --releaseKey point: the cache key includes the Cargo.lock hash. If dependencies haven't changed, the cache is restored instantly.
Advanced Cache Separation for Tests and Builds
For large projects, it makes sense to separate the cache for cargo build and cargo test to avoid rebuilding test binaries during a release build:
- name: Cache cargo build uses: actions/cache@v3 with: path: | ~/.cargo/registry ~/.cargo/git target/debug/.fingerprint target/debug/build key: ${{ runner.os }}-build-${{ hashFiles('**/Cargo.lock') }}2. Build Matrix: Testing on All Platforms
Rust compiles for many platforms. To ensure correct operation on Windows, macOS, and Linux, we use a matrix strategy.
Example Matrix for Three OSes
jobs: test: strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] toolchain: [stable, beta] features: - default - all runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - uses: actions-rust-lang/setup-rust-toolchain@v1 with: toolchain: ${{ matrix.toolchain }} - name: Run tests run: cargo test --features ${{ matrix.features }}This approach automatically creates 6 parallel jobs (3 OSes × 2 toolchains). You can add checks for nightly, arm64 architectures, or cross-compilation for WASM.
Excluding Unnecessary Combinations
strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] toolchain: [stable, nightly] exclude: - os: macos-latest toolchain: nightly # Don't test nightly on macOS3. Linting, Formatting, and Security
In addition to tests, advanced CI includes static analysis. Let's add checks for clippy, rustfmt, and cargo-audit for vulnerabilities.
Separate Job for Linting
lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions-rust-lang/setup-rust-toolchain@v1 with: components: clippy, rustfmt - name: Check formatting run: cargo fmt --check - name: Clippy with warnings as errors run: cargo clippy -- -D warnings