Введение: Почему продвинутый CI/CD важен для Rust проектов
Базовый CI/CD пайплайн для Rust — это хорошо, но в реальных проектах, особенно с несколькими платформами, зависимостями и необходимостью быстрой обратной связи, простого cargo test недостаточно. Продвинутая настройка GitHub Actions позволяет сократить время сборки в 2-3 раза, автоматически проверять код на разных архитектурах, публиковать крейты и выполнять линтинг.
В этой статье мы разберём продвинутые техники: кэширование зависимостей, матрицу сборок для Windows/macOS/Linux, параллельный запуск тестов, публикацию в crates.io и интеграцию с Clippy.
1. Оптимизация времени сборки: кэширование и инкрементальные компиляции
Самая затратная операция в CI для Rust — это компиляция зависимостей. Без кэширования каждый запуск будет скачивать и собирать все крейты заново. Решение — использовать встроенный кэш GitHub Actions.
Базовое кэширование target директории
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 --release
Ключевой момент: ключ кэша включает хеш Cargo.lock. Если зависимости не менялись, кэш восстанавливается мгновенно.
Продвинутое разделение кэша для тестов и сборки
Для больших проектов имеет смысл разделять кэш для cargo build и cargo test, чтобы не пересобирать тестовые бинарники при сборке релиза:
- 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. Матрица сборок: тестирование на всех платформах
Rust компилируется под множество платформ. Чтобы гарантировать корректную работу на Windows, macOS и Linux, используем матрицу стратегий (matrix strategy).
Пример матрицы для трёх ОС
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 }}
Такой подход автоматически создаёт 6 параллельных джоб (3 ОС × 2 тулчейна). Вы можете добавить проверку на nightly, архитектуры arm64 или кросс-компиляцию для WASM.
Исключение ненужных комбинаций
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
toolchain: [stable, nightly]
exclude:
- os: macos-latest
toolchain: nightly # Не тестируем nightly на macOS
3. Линтинг, форматирование и безопасность
Помимо тестов, продвинутый CI включает статический анализ. Добавим проверки clippy, rustfmt и cargo-audit для уязвимостей.
Отдельный job для линтинга
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
Проверка безопасности зависимостей
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install cargo-audit
run: cargo install cargo-audit
- name: Audit dependencies
run: cargo audit
Эти джобы выполняются параллельно с тестами, экономя время.
4. Автоматическая публикация в crates.io
Когда код прошёл все проверки, можно автоматически публиковать новый релиз. Для этого используем условный запуск по тегу (semver) или по пушу в main.
Публикация по созданию тега
publish:
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
needs: [test, lint, security]
steps:
- uses: actions/checkout@v4
- uses: actions-rust-lang/setup-rust-toolchain@v1
- name: Login to crates.io
run: cargo login ${{ secrets.CARGO_REGISTRY_TOKEN }}
- name: Publish crate
run: cargo publish
Не забудьте добавить секрет CARGO_REGISTRY_TOKEN в настройках репозитория (Settings → Secrets and variables).
Создание GitHub Release
- name: Create Release
uses: softprops/action-gh-release@v1
with:
files: target/release/my-rust-binary
body_path: CHANGELOG.md
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
5. Параллельные тесты и Code Coverage
Для ускорения тестов можно разделить их на несколько джобов, используя cargo test --test для каждого файла тестов. Но более практичный вариант — собирать coverage с помощью tarpaulin или cargo-llvm-cov.
Пример с cargo-llvm-cov
coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions-rust-lang/setup-rust-toolchain@v1
with:
components: llvm-tools-preview
- name: Install cargo-llvm-cov