Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

6. Compiler, tester et vérifier

Tu sais composer une flotte, l’épingler et livrer des changesets à travers elle. Maintenant, faisons en sorte qu’elle gagne son pain au quotidien. La promesse d’un outil multi-dépôts est simple : faire quelque chose sur chaque dépôt d’un coup, en parallèle, sans boucle for bricolée à la main — puis verrouiller toute la flotte pour que la CI reste au vert.

Dans ce chapitre, tu vas lancer des commandes arbitraires à travers la flotte, câbler build et test, rechercher dans chaque dépôt d’un seul coup, et utiliser verify comme le garde-fou anti-dérive qui relie le tout. Garde l’espace de travail my-first-stack ouvert.

Running commands across the whole fleet in parallel

Une commande en entrée, toute la flotte traitée en parallèle — sans boucle for bricolée à la main.

🎯 Dans ce chapitre, tu vas apprendre à…

  • Diffuser n’importe quelle commande sur tous les dépôts avec haw run.
  • Déclarer build = / test = par dépôt et piloter toute la flotte avec haw build / haw test — diffusé en direct, avec une couleur par dépôt.
  • Chercher dans tous les dépôts d’un coup avec haw grep.
  • Verrouiller la flotte contre le lock avec haw verify — la barrière anti-dérive de la CI.
  • Maîtriser le rayon d’action avec -j (parallélisme) et --group (portée).

haw run déploie une commande sur chaque dépôt en parallèle ; verify verrouille la flotte contre le lock.

⚙️ 1. Lance n’importe quelle commande sur chaque dépôt — haw run

Le cheval de trait. haw run prend une commande en positionnel et la lance dans chaque dépôt, en parallèle :

haw run 'git log -1 --oneline'
── hello-world ──
7fd1a60 Merge pull request #6 from Spaceghost/patch-1
── spoon-knife ──
d0dd1f6 Pointing to the guide for forking
ran in 2/2 repos

haw regroupe la sortie par dépôt pour que tu saches toujours quel dépôt a dit quoi. Tout ce que tu taperais dans un dépôt fonctionne : git fetch, git status -s, un linter, une commande shell en une ligne.

Astuce : Mets la commande entre guillemets. haw run 'git status -s' passe toute la chaîne comme une seule commande ; sans guillemets, ton shell essaierait d’interpréter les flags lui-même.

🔨 2. Déclare build et test — puis lance-les sur toute la flotte

haw reste agnostique vis-à-vis du système de build : chaque dépôt nomme la commande shell qui le compile ou le teste, et haw les déploie. Tu les déclares dans le manifeste avec build = et test =.

Dans le monde réel, chaque dépôt apporte sa propre chaîne d’outils. Voici la forme, tirée de l’exemple microservices livré :

[repo.proto]
build = "buf generate"
test  = "buf lint"

[repo.gateway]
build = "go build ./..."
test  = "go test ./..."

[repo.billing]
build = "cargo build --release"
test  = "cargo test"

[repo.accounts]
build = "npm ci && npm run build"
test  = "npm test"

Nos dépôts octocat n’ont rien de réel à compiler — et si tu lances haw build maintenant, il te le dit et sort avec un code non nul :

$ haw build
error: no cloned repo declares a `build` command in the manifest

Alors déclarons des commandes triviales pour voir le mécanisme. Ajoute une ligne build = et test = aux deux dépôts dans ton my-first-stack/haw.toml :

[repo.hello-world]
remote = "gh"
repo = "Hello-World.git"
rev = "master"
groups = ["core"]
build = "echo built"
test  = "echo tested"

[repo.spoon-knife]
remote = "gh"
repo = "Spoon-Knife.git"
rev = "main"
groups = ["web"]
build = "echo built"
test  = "echo tested"

Maintenant deux commandes pilotent toute la flotte :

haw build     # lance le `build =` de chaque dépôt, en parallèle
haw test      # lance le `test =` de chaque dépôt, en parallèle
$ haw build
── hello-world ──
built
── spoon-knife ──
built
build ran in 2/2 repos

La sortie est diffusée en direct au fur et à mesure que chaque dépôt s’exécute et regroupée sous un en-tête par dépôt, donc sur un terminal en couleur le flux de chaque dépôt porte sa propre couleur — tu peux lire un build sur toute la flotte sans perdre de vue quel dépôt a produit quelle ligne. Les dépôts qui ne déclarent pas la commande (ou qui ne sont pas clonés) sont simplement ignorés. Et voici le détail qui en fait une brique de CI :

Brique de CI : haw build et haw test sortent avec un code non nul si un dépôt échoue. C’est pourquoi la même commande que tu lances en local s’intègre directement dans un pipeline — le pipeline s’arrête dès que le build d’un dépôt casse.

🔎 3. Cherche dans toute la flotte — haw grep

Besoin de trouver chaque usage d’un symbole, d’un TODO, d’une API obsolète à travers tous les dépôts ? haw grep déploie git grep sur chaque dépôt cloné d’un seul coup :

haw grep guide
spoon-knife (1 hit(s))
  README.md:9:For some more information on how to fork a repository, [check out our guide, "Forking Projects""](http://guides.github.com/overviews/forking/). Thanks! :sparkling_heart:
1 hit(s) in 2 repo(s) for `guide`

Chaque dépôt avec une correspondance obtient un en-tête et ses résultats en dessous, et une ligne finale totalise les résultats et les dépôts fouillés — un dépôt sans correspondance n’apparaît tout simplement pas. Il recherche dans les fichiers suivis via Git, donc c’est rapide et ça ignore gratuitement tes artefacts de build. Limite-le à une seule stack avec --stack <name> quand la flotte est grande.

🛡️ 4. Verify — le garde-fou de la CI

Compiler et tester au vert n’est que la moitié de l’histoire. Avant tout ça, la CI doit prouver que l’arbre est celui que tu as épinglé — aucune dérive par rapport à haw.lock. C’est haw verify, que tu as rencontré au chapitre 3 :

haw verify; echo "code de sortie : $?"
verified: tree matches haw.lock (2 repos)
exit code: 0

verify affirme que l’arbre sur disque correspond au lock et sort avec le code 3 en cas de dérive — un garde-fou propre et scriptable. C’est la première vraie étape de chaque pipeline : synchroniser sur le lock, verify que tu es bien dessus, puis compiler et tester. Le chapitre 7 câble le job complet sync → verify → build → test.

Astuce : verify lit uniquement l’arbre et le lock — aucun réseau, aucun build. C’est assez peu coûteux pour tourner comme un hook git pre-commit (haw hooks install) afin que la dérive n’atteigne même jamais la CI.

🎚️ 5. Maîtrise le rayon d’action : parallélisme et groupes

Deux leviers gardent les commandes sur toute la flotte sous contrôle.

Parallélisme — -j. Par défaut, haw lance jusqu’à min(cores, 8) dépôts à la fois. Plafonne-le quand une tâche est lourde (ou qu’un runner de CI est petit) :

haw test -j 4     # au plus 4 dépôts qui compilent/testent à la fois
haw run -j 1 'git fetch'   # entièrement en série

Groupes — --group. Tu te souviens des labels groups = [...] de ton manifeste ? Ils existent précisément pour que tu puisses agir sur une tranche de la flotte. Dans my-first-stack, hello-world est dans le groupe core et spoon-knife est dans web :

haw status --group core
REPO         BRANCH                   HEAD       DIRTY  DRIFT
hello-world  master                    7fd1a60b   -      -

Seulement le dépôt core. Le même filtre --group fonctionne sur sync, status et run (ainsi que build/test), et il est répétable — passe-le deux fois pour sélectionner deux groupes. Un filtre vide signifie tout ; un filtre exclut les dépôts sans groupe.

haw run --group core 'git log -1 --oneline'   # seulement les dépôts core

🗺️ 6. Quand utiliser chacune

Une carte rapide pour choisir le bon verbe sans réfléchir :

Tu veux…UtilisePourquoi
lancer une commande ad hoc partouthaw run '<cmd>'ponctuel, ne fait pas partie du manifeste
compiler tout le produithaw buildlance le build = déclaré de chaque dépôt, code de sortie prêt pour la CI
tester tout le produithaw testlance le test = déclaré de chaque dépôt, échoue à la moindre défaillance
prouver que l’arbre correspond au lockhaw verifygarde-fou anti-dérive, sort avec le code 3 en cas de dérive
trouver du texte à travers tous les dépôtshaw grep <pat>git grep sur toute la flotte, sortie regroupée
se limiter à une partie de la flotteajouter --group <g>agir sur une tranche étiquetée
dompter une exécution lourde ou de CIajouter -j <n>plafonner les dépôts concurrents

La règle générale : run pour les commandes ponctuelles, build/test pour les commandes que tes dépôts déclarent, verify pour verrouiller. Les commandes déclarées sont celles que tu voudras identiques en local et en CI.

🙌 À toi de jouer

Mets la flotte à l’épreuve dans my-first-stack :

  • Ajoute les lignes triviales build = / test = ci-dessus, puis lance haw build et haw test — regarde la sortie diffusée par dépôt et le résumé 2/2 repos.
  • Lance haw grep guide sur toute la flotte (un vrai résultat dans spoon-knife). Puis restreins : haw run –group core ‘git log -1 –oneline’ — seul le dépôt core devrait répondre.
  • Lance haw verify; echo $? et confirme exit 0 sur un arbre propre. Force-le entièrement en série avec haw run -j 1 ‘git status -s’ et regarde les dépôts se traiter un par un.

✅ Récapitulatif

  • haw run '<cmd>' lance n’importe quelle commande dans chaque dépôt en parallèle, sortie regroupée par dépôt.
  • Déclare build = / test = par dépôt ; haw build / haw test les déploient, diffusent en direct la sortie par dépôt, et sortent avec un code non nul à la moindre défaillance — ils font ainsi aussi office d’étapes de CI.
  • haw grep <pattern> est un git grep sur toute la flotte.
  • haw verify verrouille l’arbre contre haw.lock (sort avec le code 3 en cas de dérive) — le premier geste de chaque pipeline.
  • -j N plafonne le parallélisme ; --group G (répétable) restreint les commandes aux dépôts étiquetés.

👉 La suite

Tu sais compiler, tester et verrouiller la flotte en local. Maintenant, faisons monter tout ça en qualité production — confiance, CI, signature et audit → 7. Passer en production.