Rust GitHub Actions Workflow Template
Last updated
This is a working .github/workflows/ci.yml for a Cargo project. It installs the stable toolchain, caches dependencies and build artifacts with Swatinem/rust-cache, then checks formatting, runs clippy and executes the tests.
The workflow
name: CI
on:
push:
branches: [main]
pull_request:
permissions:
contents: read
concurrency:
group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
env:
CARGO_TERM_COLOR: always
CARGO_INCREMENTAL: "0"
RUSTFLAGS: "-D warnings"
jobs:
check:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- uses: Swatinem/rust-cache@v2
- run: cargo fmt --all -- --check
- run: cargo clippy --all-targets --all-features
- run: cargo test --all-features
What the non-obvious parts do
dtolnay/rust-toolchain@stableinstalls a toolchain by the ref you choose.@stabletracks the stable release; use@1.85.0style refs to pin an exact version.Swatinem/rust-cache@v2caches~/.cargoand thetargetdirectory, keyed onCargo.lock, the toolchain and manifest files. It also cleans out stale artifacts before saving so the cache does not grow forever. See Cargo caching in CI.CARGO_INCREMENTAL: "0"turns off incremental compilation. It helps local rebuilds but makes CI caches larger and slower to restore.RUSTFLAGS: "-D warnings"makes any compiler warning an error in CI. It also changes the compile flags, so cache entries from a build without it are not reused. Keep it set the same way everywhere.cargo fmt --all -- --checkfails if code is not formatted, without changing files.--all-targetsmakes clippy also lint tests, examples and benches.- 30 minute timeout. Cold Rust builds are slow, so the cap is higher than in other templates.
Variants
Build matrix
For libraries, add a job with matrix.toolchain: [stable, beta, "1.80.0"] to check the minimum supported Rust version. See matrix builds.
Workspaces
Add --workspace to the clippy and test commands to cover every member crate. Use rust-cache's workspaces: input when the workspace root is not the repository root.
Database tests
Add a services: block as shown in the Django template, and pass DATABASE_URL.
Release builds
Add a job that runs cargo build --release and upload the binary as an artifact. Cross-compiling is easier with cross or cargo-zigbuild.
macOS or Windows
Add them to the matrix if you ship binaries for them.
Run it on faster machines
Rust compile times scale with core count, so this is one of the stacks that gains most. Change one line:
runs-on: [self-hosted, Linux, compiler-ci]
The job runs on a fresh 8 vCPU machine from compiler.dev, with automatic fallback. In compiler.dev's benchmark a React and Rust (Axum) app went from 2m37s to 1m45s; see benchmarks. Tuning tips are in speed up Rust and Cargo on GitHub Actions, and prices are on pricing.
FAQ
Do I need sccache as well?
Not at first. rust-cache handles dependencies. sccache helps when many projects share compiled code.
Why does my cache keep growing?
rust-cache prunes old artifacts, but only for its own cache. Check cache limits if you hit the repository cap.
Should clippy fail the build?
Yes on main. On pull requests, it keeps style debt from piling up.
Can I cache across branches?
Branches can restore caches from the default branch. Make sure main runs the workflow so it saves one.
Related
- Speed Up Rust Cargo in GitHub ActionsSpeed up Rust Cargo builds in GitHub Actions with Swatinem/rust-cache, sccache, cargo-nextest, CARGO_INCREMENTAL=0 and a faster linker. YAML inside.
- .NET GitHub Actions Workflow TemplateCopy-paste GitHub Actions CI for .NET with NuGet caching, restore, build and test steps, a SQL Server service option, concurrency and permissions.
- Django GitHub Actions Workflow TemplateCopy-paste GitHub Actions CI for Django with a Postgres service container, pip caching, migrations check and tests, plus concurrency and permissions.
- Docker Build GitHub Actions Workflow TemplateCopy-paste GitHub Actions workflow to build Docker images with Buildx, GitHub cache layers and a push to GHCR on main, with minimal permissions.