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

5. Les changesets à travers les dépôts

C’est la fonctionnalité emblématique de hawser — celle qui justifie à elle seule tout l’outil. Dans ce chapitre, tu vas prendre une seule fonctionnalité qui touche plusieurs dépôts et la piloter comme un tout : une branche commune à tous, des pull requests reliées entre elles, et une fusion qui atterrit dans le bon ordre.

Reviewing cross-repo pull requests as one changeset

Une fonctionnalité, un seul flux de revue — même quand le code est réparti sur plusieurs dépôts et plusieurs forges.

🎯 Dans ce chapitre, tu vas apprendre à…

  • Comprendre ce qu’est un changeset : une fonctionnalité = une branche sur N dépôts.
  • Démarrer un changeset avec haw change start — la même branche dans chaque dépôt, en un seul geste.
  • Suivre toute la fonctionnalité sur un seul écran avec haw change status.
  • Ouvrir des PR/MR liées entre elles avec haw change request — sur GitHub, GitLab et Bitbucket.
  • Fusionner dans l’ordre des dépendances avec haw change land, pour que main ne casse jamais.

Une fonctionnalité, plusieurs dépôts : change start crée la branche partout, status agrège, request ouvre les PR reliées.

😤 1. La douleur que ça supprime

Repense à la dernière fois qu’une fonctionnalité s’étalait sur plusieurs dépôts. Tu as fait cette danse :

  1. git checkout -b feature dans le dépôt A. Puis le dépôt B. Puis le dépôt C.
  2. Pousser chacun. Ouvrir une PR dans A. Puis B. Puis C.
  3. Courir après les revues sur trois pages de PR distinctes.
  4. Les fusionner — et ne pas oublier que la bibliothèque partagée doit fusionner avant les services qui en dépendent, sinon main casse.

Rien ne reliait ces trois PR entre elles. Il n’existait aucun artefact unique qui disait “ce sont une seule fonctionnalité.” Un changeset est exactement cet artefact : une fonctionnalité = une branche à travers N dépôts, avec des PR/MR reliées et un atterrissage ordonné.

Les changesets ont besoin d’une vraie forge (GitHub, GitLab ou Bitbucket) et d’un token pour ouvrir les PR. Les étapes start et status sont locales et sans danger à essayer partout ; request et land dialoguent avec la forge. On te signalera laquelle est laquelle.

🌱 2. Démarre le changeset

Tu donnes un nom à la fonctionnalité et (optionnellement) les dépôts qu’elle touche :

haw change start FEAT-42 --repos api,billing,proto
changeset `FEAT-42` started across 3 repo(s):
  proto    -> change/FEAT-42
  billing  -> change/FEAT-42
  api      -> change/FEAT-42

En un seul geste, haw a créé la même branchechange/FEAT-42 par défaut — dans chacun des trois dépôts. Maintenant tu fais tes modifications et tu committes dans chaque dépôt comme du Git normal. Le nom de la branche les relie entre eux.

Quelques options utiles au démarrage :

  • --repos a,b,c — se limiter aux dépôts que la fonctionnalité touche (par défaut : tous les dépôts).
  • --branch <name> — utiliser un nom de branche personnalisé au lieu de change/<id>.
  • --skip-branch — adopter la branche sur laquelle chaque dépôt se trouve déjà, au lieu d’en créer une.
  • --label <l> — attacher un label (répétable) qui sera transmis aux PR/MR plus tard.

📊 3. Regarde-la prendre forme — change status

À tout moment, retrouve toute la fonctionnalité sur un seul écran :

haw change status FEAT-42

Ceci agrège, par dépôt : la branche, si chaque dépôt est dessus, s’il est sale, son HEAD — et une fois les PR existantes, l’état de revue et le statut CI de chaque PR/MR. Avant l’ouverture de toute PR, ça ressemble à ceci (lancé sur le changeset DEMO-1 de l’« À toi de jouer » ci-dessous, donc les dépôts sont les deux clones octocat) :

changeset `DEMO-1`
REPO         BRANCH                   ON IT     DIRTY  HEAD       PR
hello-world  change/DEMO-1             yes       -      7fd1a60b   —
spoon-knife  change/DEMO-1             yes       -      d0dd1f61   —
(no PR/MRs yet — open them with `haw change request DEMO-1`)

Au lieu de trois onglets de navigateur, un seul tableau de bord. C’est l’équivalent, pour un changeset, de haw status.

Astuce : Ajoute --format json à change status (il émet un document stable haw.change-status/1) quand tu veux rediriger l’état vers un autre outil ou un script :

$ haw change status DEMO-1 --format json
{
  "id": "DEMO-1",
  "repos": [
    {
      "branch": "change/DEMO-1",
      "dirty": false,
      "head": "7fd1a60b01f91b314f59955a4e4d4e80d8edf11d",
      "missing": false,
      "name": "hello-world",
      "on_branch": true,
      "pr": null
    }
  ],
  "schema": "haw.change-status/1"
}

🔀 4. Ouvre les pull requests — change request

Quand tes branches sont poussées et prêtes, une seule commande ouvre des PR/MR reliées entre elles — une par dépôt — sur la forge où réside chaque dépôt :

haw change request FEAT-42

Voici la partie discrètement puissante : tes dépôts n’ont pas tous à être sur la même forge. haw parle GitHub, GitLab et Bitbucket, donc une fonctionnalité qui couvre un service GitHub et une bibliothèque GitLab obtient une PR sur GitHub et une MR sur GitLab, reliées entre elles, depuis cette unique commande. Tous les labels que tu as passés à start sont transmis ici. Cible une branche de base précise avec --base <branch>.

Cette étape a besoin d’un token de forge dans ton environnement — par ex. export GITHUB_TOKEN=$(gh auth token). haw lit les tokens uniquement depuis les variables d’environnement, ne les stocke jamais. Les étapes en lecture seule (start, status) n’ont besoin d’aucun token.

🛬 5. Atterris dans l’ordre des dépendances — change land

Les revues sont faites, les checks sont au vert. Maintenant fusionne — mais dans le bon ordre. Rappelle-toi que proto est une bibliothèque partagée dont api et billing dépendent. Fusionner un service avant que sa bibliothèque n’atterrisse, c’est comme ça qu’on casse main.

haw connaît l’ordre parce que ton manifeste le déclare. Souviens-toi de la clé deps de l’exemple microservices :

[repo.gateway]
deps = ["proto"]     # proto doit atterrir avant gateway

Donc land fusionne les PR/MR dans un ordre topologique stable — les dépendances d’abord — et s’arrête à la première défaillance plutôt que de laisser un fouillis à moitié fusionné :

haw change land FEAT-42
landing changeset `FEAT-42` in dependency order:
  proto    ✓ merged
  billing  ✓ merged
  api      ✓ merged
changeset `FEAT-42` landed.

Étape de forge — nécessite un token. Comme request, land dialogue avec la forge et requiert un token (par ex. export GITHUB_TOKEN=$(gh auth token)) ainsi que des droits de fusion sur chaque dépôt. La sortie ci-dessus est illustrative : contre les dépôts publics en lecture seule octocat qu’utilise ce cours, request/land ne peuvent ni pousser ni fusionner, donc ne t’attends pas à ces lignes sans tes propres dépôts accessibles en écriture et un token.

proto a fusionné en premier parce que tout en dépend ; les services ont suivi. Une seule commande, le bon ordre, pas de main cassé.

Jubilant celebration reaction

Une commande. Cinq dépôts fusionnés dans le bon ordre. On l’a fait.

change land fusionne les PR/MR reliées dans l’ordre topologique — les dépendances d’abord — et s’arrête à la première défaillance.

🖼️ 6. La valeur, en une seule image

        one feature (FEAT-42)
                │
   ┌────────────┼────────────┐
 proto        billing        api          ← change start:  one branch across N repos
   │            │             │
 MR/PR        PR             PR            ← change request: cross-linked, any forge
   │            │             │
   └──── land in deps order ──┘            ← change land:  proto → billing → api

Tu n’as jamais perdu de vue quelles PR étaient « la fonctionnalité », tu n’as jamais fusionné dans le mauvais ordre, et tu as tout piloté depuis quatre commandes. C’est tout l’intérêt d’un changeset : une fonctionnalité multi-dépôts qui se comporte comme un changement unique et cohérent.

Astuce : Tu travailles sur plusieurs dépôts et tu veux sauter dans l’un d’eux ? haw change goto FEAT-42 <repo> affiche son chemin pour que tu puisses faire cd "$(haw change goto FEAT-42 api)". Et haw change snapshot save <name> enregistre la branche + le HEAD de chaque dépôt pour que tu puisses restaurer plus tard l’état multi-dépôts exact.

🙌 À toi de jouer

La moitié locale du flux ne nécessite aucun jeton de forge, alors essaie-la dans un espace de travail dès maintenant :

  • Lance haw change start DEMO-1 –repos hello-world,spoon-knife et confirme que la même branche change/DEMO-1 apparaît dans les deux dépôts (jette un œil avec haw run ‘git branch –show-current’).
  • Lance haw change status DEMO-1 et lis l’agrégat branche/dirty/HEAD — un seul tableau de bord au lieu de deux onglets.
  • Maintenant esquisse-le sur papier : pour une vraie fonctionnalité couvrant une lib partagée et deux services, dans quel ordre doivent-ils land ? (La lib d’abord — c’est la clé deps qui fait son travail.)

✅ Récapitulatif

  • Un changeset est une fonctionnalité à travers N dépôts : une branche partagée, des PR/MR reliées, une fusion ordonnée.
  • haw change start <id> --repos a,b,c crée la même branche dans chaque dépôt.
  • haw change status <id> agrège branche + revue + CI sur toute la fonctionnalité.
  • haw change request <id> ouvre des PR/MR reliées entre elles sur GitHub, GitLab et Bitbucket.
  • haw change land <id> fusionne dans l’ordre des dépendances (d’après le deps de chaque dépôt), en s’arrêtant à la première défaillance.
  • start/status sont locales ; request/land ont besoin d’un token de forge dans l’environnement.

👉 La suite

Tu sais livrer une fonctionnalité à travers la flotte. Maintenant, compilons, testons et vérifions le tout — le workflow quotidien qui le garde au vert → 6. Compiler, tester et vérifier.