Comprendre la CI Dagger : Easy Mode et Power Mode

Ce que vous allez comprendre

  • Expliquer pourquoi gitrust utilise Dagger plutôt qu'un système CI YAML classique
  • Distinguer le « Easy Mode » (.gitrust-ci.yml) du « Power Mode » (module .dagger/)
  • Évaluer quand conseiller à vos utilisateurs de passer de l'un à l'autre

Le problème concret

Un utilisateur vous signale que sa CI « ne fait pas ce qu'il veut » avec .gitrust-ci.yml. Il a besoin de logique conditionnelle, de dépendances entre jobs, et de construire plusieurs images Docker en parallèle. Devez-vous modifier le moteur CI ou lui dire qu'il doit changer d'approche ?


L'analogie

Easy Mode, c'est la recette de cuisine imprimée sur la boîte de gâteau : elle marche pour 95 % des cas, est accessible aux débutants, mais on ne peut pas y ajouter de la fleur d'oranger sans sortir du cadre.

Power Mode, c'est le livre de pâtisserie professionnel : vous écrivez vos propres recettes en code (Go, Python, TypeScript), vous pouvez tout faire, mais il faut savoir pâtisser.

Dagger est l'atelier qui garantit que les deux approches s'exécutent dans exactement le même environnement, reproductible sur n'importe quelle machine.


Le modèle

Pourquoi Dagger ?

Les systèmes CI YAML classiques (GitHub Actions, GitLab CI) ont un problème fondamental : la logique de pipeline est encodée dans du YAML qui devient vite illisible, non-testable, et non-composable. Dagger a été créé par l'équipe fondatrice de Docker pour résoudre ce problème.

graph LR
    subgraph "CI YAML classique"
        Y[.github/workflows/ci.yml
GitLab CI / Jenkins] Y --> E[Exécuté sur runner
CI propriétaire] E --> R1[Résultat dépend
du runner] end subgraph "CI Dagger" D[Pipeline en code
Go / Python / TS] D --> DE[Dagger Engine
Docker containers] DE --> R2[Reproductible
local = CI = prod] end

Avantages de Dagger pour gitrust : - Reproductibilité : le même pipeline s'exécute identiquement en local et sur le serveur - Isolation : chaque job dans son propre conteneur Docker - Cache automatique : les layers Docker non modifiés ne sont pas reconstruits - Pas de dépendance à un service CI externe (GitHub Actions, etc.)

Easy Mode : .gitrust-ci.yml

Le fichier .gitrust-ci.yml est un profil YAML simplifié interprété par le moteur CI générique de gitrust (un module Dagger Python interne à la plateforme).

flowchart LR
    A[.gitrust-ci.yml
dans le dépôt] -->|lecture| B[Moteur CI gitrust
module Dagger Python] B -->|dagger call| C[Dagger Engine] C --> D[Container isolé
build + test] D --> E[Résultat → DB + UI]

Structure type :

# .gitrust-ci.yml
pipeline:
  name: CI principale
  image: rust:1.77-slim
  steps:
    - name: Vérifier le formatage
      run: cargo fmt --check
    - name: Linting
      run: cargo clippy -- -D warnings
    - name: Tests
      run: cargo test --workspace
  cache:
    - path: ~/.cargo/registry
    - path: target/

Ce que Easy Mode fait bien : - Build + test + lint pour des projets simples à intermédiaires - Configuration en quelques lignes - Accessible aux utilisateurs sans expertise CI/CD

Limites du Easy Mode : - Pas de logique conditionnelle complexe (si branche = main alors déployer) - Pas de fan-out/fan-in (jobs parallèles avec synchronisation) - Pas d'accès au Daggerverse (bibliothèque de modules Dagger communautaires) - La logique reste dans le YAML de la plateforme, pas dans le code du projet

Power Mode : module .dagger/

Quand un dépôt contient un dossier .dagger/, gitrust détecte sa présence et exécute directement le module Dagger natif. La plateforme ne l'interprète pas : elle lance dagger call sur le module du projet.

flowchart LR
    A[.dagger/
main.go ou main.py] -->|détecté| B[gitrust CI Worker] B -->|dagger call -m .dagger/ ci| C[Dagger Engine] C --> D[Pipeline défini
par l'utilisateur] D --> E[Résultat → DB + UI]

Ce que Power Mode apporte : - La logique pipeline est du code versionné avec le projet - Tests unitaires des pipelines possibles - Composition via le Daggerverse - Accès à toutes les fonctionnalités Dagger (secrets, services, multi-platform builds) - Aucune dépendance au moteur CI de gitrust pour la logique

Exemple minimal en Go :

// .dagger/main.go
package main

import (
    "context"
    "dagger.io/dagger"
)

func main() {
    ctx := context.Background()
    client, _ := dagger.Connect(ctx)
    defer client.Close()

    rust := client.Container().
        From("rust:1.77-slim").
        WithMountedCache("/usr/local/cargo/registry", client.CacheVolume("cargo-registry")).
        WithDirectory("/src", client.Host().Directory(".")).
        WithWorkdir("/src")

    rust.WithExec([]string{"cargo", "fmt", "--check"}).
        WithExec([]string{"cargo", "clippy", "--", "-D", "warnings"}).
        WithExec([]string{"cargo", "test", "--workspace"}).
        Sync(ctx)
}

Alternatives et compromis

Critère Easy Mode (.gitrust-ci.yml) Power Mode (.dagger/)
Accessibilité Excellent (quelques lignes YAML) Courbe d'apprentissage
Puissance Limitée aux cas simples Illimitée
Logique conditionnelle Non Oui
Parallélisme avancé Non Oui
Testabilité du pipeline Nulle Totale
Composition (Daggerverse) Non Oui
Maintenance Moteur géré par la plateforme Chaque dépôt est autonome
Alignement philosophie Dagger Partiel (YAML encode de la logique) Total

Recommandation pour vos utilisateurs : - Commencer en Easy Mode pour les projets simples - Migrer en Power Mode quand : besoin de logique conditionnelle, de fan-out/fan-in, d'intégration avec des services externes, ou quand le .gitrust-ci.yml dépasse 50 lignes


Implications pour l'administration

En tant qu'administrateur :

  • CI_ENABLED=false désactive toute exécution CI (Easy et Power Mode), utile lors d'une maintenance
  • CI_MAX_CONCURRENT s'applique aux deux modes
  • Le moteur Easy Mode (CI_ENGINE_PATH) doit être synchronisé lors des mises à jour de gitrust
  • Les modules Power Mode sont autonomes — leur mise à jour est la responsabilité de l'utilisateur

Vérifier votre compréhension

  1. Un utilisateur vous demande d'ajouter une étape « déploiement vers staging si la branche est main » dans son .gitrust-ci.yml. Quelle est la réponse correcte ? Quelle alternative proposez-vous ?

  2. En quoi le fait que Dagger garantisse la reproductibilité facilite-t-il le débogage d'un pipeline qui échoue uniquement sur le serveur et pas en local ?


Pour aller plus loin