Introduction : Pourquoi un CI/CD avancé est important pour les projets Rust
Un pipeline CI/CD de base pour Rust est une bonne chose, mais dans les projets réels, surtout avec plusieurs plateformes, des dépendances et un besoin de retour rapide, un simple cargo test ne suffit pas. Une configuration avancée de GitHub Actions permet de réduire le temps de build de 2 à 3 fois, de vérifier automatiquement le code sur différentes architectures, de publier des crates et d'effectuer du linting.
Dans cet article, nous aborderons les techniques avancées : mise en cache des dépendances, matrice de builds pour Windows/macOS/Linux, exécution parallèle des tests, publication sur crates.io et intégration avec Clippy.
1. Optimisation du temps de build : mise en cache et compilations incrémentales
L'opération la plus coûteuse dans le CI pour Rust est la compilation des dépendances. Sans mise en cache, chaque exécution télécharge et compile tous les crates à nouveau. La solution consiste à utiliser le cache intégré de GitHub Actions.
Mise en cache de base du répertoire 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 --releasePoint clé : la clé de cache inclut le hachage de Cargo.lock. Si les dépendances n'ont pas changé, le cache est restauré instantanément.
Séparation avancée du cache pour les tests et le build
Pour les grands projets, il est judicieux de séparer le cache pour cargo build et cargo test, afin de ne pas recompiler les binaires de test lors du build de release :
- 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. Matrice de builds : tests sur toutes les plateformes
Rust se compile pour de nombreuses plateformes. Pour garantir un fonctionnement correct sur Windows, macOS et Linux, nous utilisons une matrice de stratégies (matrix strategy).
Exemple de matrice pour trois OS
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 }}Cette approche crée automatiquement 6 jobs parallèles (3 OS × 2 toolchains). Vous pouvez ajouter une vérification sur nightly, les architectures arm64 ou la cross-compilation pour WASM.
Exclusion des combinaisons inutiles
strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] toolchain: [stable, nightly] exclude: - os: macos-latest toolchain: nightly # Ne pas tester nightly sur macOS3. Linting, formatage et sécurité
En plus des tests, un CI avancé inclut l'analyse statique. Ajoutons les vérifications clippy, rustfmt et cargo-audit pour les vulnérabilités.
Job séparé pour le 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