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.
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 avechaw 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… | Utilise | Pourquoi |
|---|---|---|
| lancer une commande ad hoc partout | haw run '<cmd>' | ponctuel, ne fait pas partie du manifeste |
| compiler tout le produit | haw build | lance le build = déclaré de chaque dépôt, code de sortie prêt pour la CI |
| tester tout le produit | haw test | lance le test = déclaré de chaque dépôt, échoue à la moindre défaillance |
| prouver que l’arbre correspond au lock | haw verify | garde-fou anti-dérive, sort avec le code 3 en cas de dérive |
| trouver du texte à travers tous les dépôts | haw grep <pat> | git grep sur toute la flotte, sortie regroupée |
| se limiter à une partie de la flotte | ajouter --group <g> | agir sur une tranche étiquetée |
| dompter une exécution lourde ou de CI | ajouter -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 lancehaw buildethaw test— regarde la sortie diffusée par dépôt et le résumé2/2 repos. - Lance
haw grep guidesur toute la flotte (un vrai résultat dansspoon-knife). Puis restreins :haw run –group core ‘git log -1 –oneline’— seul le dépôtcoredevrait répondre. - Lance
haw verify; echo $?et confirme exit0sur un arbre propre. Force-le entièrement en série avechaw 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 testles 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 ungit grepsur toute la flotte.haw verifyverrouille l’arbre contrehaw.lock(sort avec le code 3 en cas de dérive) — le premier geste de chaque pipeline.-j Nplafonne 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.