Comprendre la CI Dagger : Easy Mode vs Power Mode

Ce que vous allez comprendre

  • Analyser pourquoi Dagger a été choisi comme moteur CI plutôt qu'une CI YAML classique.
  • Comparer Easy Mode (.gitrust-ci.yml) et Power Mode (.dagger/) et évaluer quand basculer de l'un à l'autre.
  • Décrire les garanties d'isolation et de reproductibilité offertes par Dagger.

Le problème concret

Une CI traditionnelle (GitHub Actions, GitLab CI) exécute des étapes dans un environnement partagé. Deux problèmes fréquents :

  1. Manque de reproductibilité : « ça passe sur ma machine mais pas en CI » parce que les versions d'outils diffèrent.
  2. Couplage fort : un pipeline GitLab CI est indissociable de GitLab. Migrer vers une autre plateforme = réécrire tous les pipelines.

L'analogie

Dagger, c'est comme Docker pour les pipelines CI : chaque étape s'exécute dans un container isolé, avec des dépendances déclarées et des caches portables. Le pipeline peut tourner identiquement sur votre machine, sur le serveur gitrust, ou sur n'importe quel autre runner qui a Docker installé.

L'analogie avec Docker/Kubernetes est directe : - Docker résout « ça marche sur ma machine » pour les applications. - Dagger résout « ça marche sur ma machine » pour les pipelines.

Le modèle

Architecture gitrust CI

flowchart LR
    Push[git push] --> Hook[receive-pack\nhook]
    Hook --> Detect{Détection\nfichier CI}
    Detect -->|".gitrust-ci.yml"| Easy[Easy Mode\nDagger générique]
    Detect -->|".dagger/"| Power[Power Mode\nModule utilisateur]
    Detect -->|Aucun| None[Pas de CI]
    Easy --> Worker[CI Worker\nSémaphore N]
    Power --> Worker
    Worker --> Dagger[dagger call ...]
    Dagger --> Logs[Logs DB + SSE]
    Logs --> UI[Page pipeline\n/{owner}/{repo}/ci]

La détection est prioritaire : si .dagger/ et .gitrust-ci.yml coexistent, le Power Mode prend la priorité.

Easy Mode — .gitrust-ci.yml

Un fichier YAML simple décrit le pipeline. Le moteur Dagger générique de la plateforme l'interprète.

# .gitrust-ci.yml — exemple pour un projet Rust
build:
  command: cargo build --release
  cache:
    - path: ~/.cargo/registry
      key: cargo-registry

test:
  command: cargo test --workspace
  requires_build: true

checks:
  - name: fmt
    command: cargo fmt --all -- --check
  - name: clippy
    command: cargo clippy --workspace -- -D warnings

Avantages : - Accessible à tout utilisateur sans connaissance de Dagger. - Standardisé : tous les projets Easy Mode ont la même structure. - Zéro configuration côté plateforme.

Limites : - Pas de logique conditionnelle complexe. - Pas d'accès au Daggerverse (modules Dagger communautaires). - Pas de tests unitaires du pipeline lui-même. - Pas de composition (appeler un module depuis un autre).

Power Mode — .dagger/

Le dépôt contient un vrai module Dagger (Go, Python, ou TypeScript) :

.dagger/
├── dagger.json          # manifest du module
└── main.go              # fonctions Dagger
// .dagger/main.go — exemple Go
package main

import (
    "dagger/gitrust-ci/internal/dagger"
)

type GitrustCi struct{}

func (m *GitrustCi) Test(ctx context.Context, source *dagger.Directory) (string, error) {
    return dag.Container().
        From("rust:1.77-slim").
        WithMountedDirectory("/src", source).
        WithWorkdir("/src").
        WithExec([]string{"cargo", "test", "--workspace"}).
        Stdout(ctx)
}

Gitrust exécute : dagger call -m .dagger/ test --source=.

Avantages : - Logique conditionnelle arbitraire (Go/Python/TS complet). - Accès au Daggerverse : réutiliser des modules existants (Helm, SBOM, Trivy...). - Tests unitaires du pipeline possible (fonctions Dagger sont du vrai code). - Composition : un module peut appeler un autre module. - Isolation totale garantie par les containers Dagger. - Type-safety : le compilateur Go/TS vérifie les appels.

Limites : - Courbe d'apprentissage : il faut écrire du code Go/Python/TS. - Chaque équipe maintient son propre module.

Quand basculer de Easy Mode vers Power Mode ?

flowchart TD
    Q1{Pipeline simple ?\nbuild + test + lint}
    Q1 -->|Oui| Easy[Rester en Easy Mode]
    Q1 -->|Non| Q2{Logique conditionnelle ?\nex: déployer seulement sur main}
    Q2 -->|Oui| Power[Passer en Power Mode]
    Q2 -->|Non| Q3{Composition avec\nd'autres modules Dagger ?}
    Q3 -->|Oui| Power
    Q3 -->|Non| Q4{Tests du pipeline\nlui-même ?}
    Q4 -->|Oui| Power
    Q4 -->|Non| Easy

Règle pratique : si votre .gitrust-ci.yml commence à ressembler à un programme avec des if/else imbriqués, c'est le moment de passer en Power Mode.

Tableau comparatif

Critère Easy Mode (YAML) Power Mode (Dagger natif)
Accessibilité Excellent Courbe d'apprentissage
Puissance Limitée Illimitée
Testabilité du pipeline Nulle Totale
Composition (Daggerverse) Non Oui
Portabilité Via le moteur gitrust Native (tout runner Dagger)
Alignement philosophie Dagger Partiel (YAML = anti-pattern) Total
Maintenance plateforme Le moteur évolue Chaque repo est autonome

Position philosophique de Dagger

Dagger a été créé explicitement contre le modèle YAML des CI traditionnelles par l'équipe fondatrice de Docker. Le YAML Easy Mode de gitrust est un compromis assumé : on sacrifie la pureté philosophique pour l'accessibilité des 90 % de cas simples. Le YAML Easy Mode ne doit jamais essayer de tout couvrir — dès que la complexité augmente, le Power Mode est la bonne réponse.

Alternatives et compromis

Pourquoi pas GitHub Actions ou GitLab CI directement ? Ces systèmes sont couplés à leur plateforme. Un pipeline GitHub Actions ne tourne pas localement sans outil tiers (act). Dagger tourne identiquement en local, sur le runner gitrust, et sur GitHub Actions si nécessaire.

Pourquoi pas Jenkins/Tekton ? L'objectif de gitrust est l'auto-hébergement simple pour des équipes de 3-20 personnes. Ces outils ajoutent une complexité d'administration disproportionnée.

Vérifier votre compréhension

  1. Un développeur a un .gitrust-ci.yml avec 15 étapes et des skip_if conditionnels simulés via des scripts shell. Doit-il rester en Easy Mode ? Justifiez.

  2. Quelle propriété de Dagger garantit qu'un pipeline Power Mode qui passe en local passera aussi sur le runner gitrust ? Comment cette propriété est-elle implémentée techniquement ?

Pour aller plus loin