cursus.

Cours 1 · Culture et fondationsLeçon 2 sur 2

Rappels indispensables

4 h de lecture10 sections Version PDF

À la fin de cette leçon, vous saurez

Linux en ligne de commande, processus et permissions ; ports, DNS et HTTP ; Git avancé — branches, fusion, rebase, GitFlow contre trunk-based — et revue de code.

Trois choses bloquent un TP de DevOps dès la première séance, et aucune n'est du DevOps.

Le serveur n'a pas d'interface graphique : tout se fait en ligne de commande, et un étudiant qui hésite sur chmod ou sur un pipe perd son temps sur autre chose que le sujet. L'application ne répond pas, et il faut savoir où regarder : le processus écoute-t-il ? le port est-il ouvert ? le nom se résout-il ? Et le dépôt Git compte huit branches divergentes, parce que personne n'a décidé d'une stratégie.

Ce chapitre remet ces trois outils à niveau. Il ne remplace pas les cours de systèmes et de réseaux — il en extrait ce dont on se sert tous les jours, et il ajoute la partie de Git que l'usage individuel ne demande jamais.

Linux, ce qui sert vraiment

Le cours de systèmes a tout posé ; voici ce qu'on emploie sans y penser.

CommandeUsage quotidien en exploitation
ps aux, top, htopqu'est-ce qui tourne, et qui consomme
kill -TERM, kill -9arrêter proprement, puis brutalement
df -h, du -sh *le disque est plein — où ?
tail -f fichier.logsuivre un journal en direct
grep, awk, sort | uniq -cfouiller ces journaux
chmod, chowndroits et propriétaire
systemctl status, journalctl -ul'état d'un service et ses journaux
ssh, scpatteindre la machine, y déposer un fichier

Deux rappels du cours de systèmes qui reviendront constamment.

Les droits. rwx pour le propriétaire, le groupe et les autres, notés en octal — 755, 644. Un conteneur qui refuse de démarrer parce qu'un script n'est pas exécutable est le grand classique du chapitre 3.

Les processus et les signaux. SIGTERM demande de s'arrêter proprement, SIGKILL tue sans préavis. Cette distinction n'est pas théorique : Docker et Kubernetes envoient un SIGTERM, attendent quelques secondes, puis un SIGKILL. Une application qui n'écoute pas SIGTERM perd ses requêtes en cours à chaque déploiement — et personne ne comprend pourquoi.

Réseau, le minimum pour diagnostiquer

Quand « ça ne répond pas », la question se décompose en quatre, et il faut les poser dans cet ordre.

Le nom se résout-il ? dig monsite.fr ou nslookup. Un DNS mal propagé se manifeste comme une panne d'application.

Le port est-il ouvert et écouté ? ss -tlnp liste ce qui écoute localement ; curl -v ou nc -zv hôte port teste depuis l'extérieur. La distinction compte : un service qui écoute sur 127.0.0.1 fonctionne en local et est injoignable de partout ailleurs — c'est l'erreur la plus fréquente du chapitre 3, où un conteneur doit écouter sur 0.0.0.0 pour être atteignable.

La requête arrive-t-elle ? Les journaux du serveur le disent. Si rien n'apparaît, le problème est en amont : pare-feu, routage, groupe de sécurité.

Que répond-elle ? Les codes HTTP suffisent à orienter : 2xx succès, 3xx redirection, 4xx la faute vient du client — 404 introuvable, 401 non authentifié, 403 interdit — et 5xx la faute vient du serveur, 500 erreur interne, 502 la passerelle n'a pas obtenu de réponse, 503 service indisponible.

Cette dernière ligne est celle qu'on emploie le plus : un 502 accuse le service en amont, un 500 accuse l'application. Savoir lequel des deux on regarde fait gagner une heure.

Git au-delà de l'usage individuel

Un étudiant arrive avec commit, push, pull. Le travail en équipe demande trois choses de plus.

Les branches. Une branche est un simple pointeur mobile sur un commit. La créer ne copie rien — c'est ce qui rend l'opération instantanée, et ce qui explique qu'on en crée sans compter.

La fusion contre le rebasage. Les deux intègrent le travail d'une branche dans une autre, et produisent des historiques de formes différentes.

merge                              rebase                                   A───B───C───────M                  A───B───C───D'──E'     \         /                         D───────E                    les commits sont REJOUÉS                                   au-dessus de C

merge préserve l'histoire telle qu'elle s'est produite, au prix d'un graphe qui se ramifie. rebase réécrit les commits pour donner une ligne droite, plus lisible — mais il crée de nouveaux commits, ce qui donne la seule règle absolue du chapitre : on ne rebase jamais une branche déjà partagée avec d'autres. Les commits d'origine disparaissent, et les collègues qui les avaient récupérés se retrouvent avec un historique incompatible.

L'usage courant : rebaser sa branche locale sur la principale avant de proposer sa contribution, puis fusionner. On obtient un historique lisible sans réécrire ce que d'autres ont déjà.

Les conflits. Ils surviennent quand deux branches modifient les mêmes lignes. Git ne peut pas trancher et vous laisse le fichier avec les deux versions marquées. Le point important est statistique : la probabilité de conflit croît avec la durée de vie de la branche. Une branche fusionnée le jour même entre rarement en conflit ; une branche de trois semaines touche des fichiers qui ont bougé entre-temps.

Deux stratégies de branchement

C'est le lien direct avec le chapitre 1, et le choix a des conséquences mesurables.

GitFlow organise le travail autour de branches durables : main, develop, une branche par fonctionnalité, des branches de version et de correctif. C'est structuré, adapté à des versions livrées — un logiciel installé chez des clients, avec plusieurs versions maintenues en parallèle.

Trunk-based ne garde qu'une branche principale, dans laquelle chacun intègre au moins une fois par jour, à l'aide de branches de très courte durée. Les fonctionnalités inachevées sont masquées par des drapeaux de fonctionnalité plutôt que par des branches.

GitFlowTrunk-based
Durée de vie d'une branchesemainesheures à un jour
Taille des lotsgrossepetite
Conflitsfréquents et largesrares et étroits
Compatible livraison continuedifficilementoui
Adapté àversions installées chez des clientsservice en ligne

Le rapprochement avec le chapitre 1 est immédiat : une branche de trois semaines est un lot de trois semaines. Toute la logique DORA — petits lots, rétroaction courte, retour arrière facile — pousse vers le trunk-based dès qu'on livre en continu. Ce n'est pas une question de mode mais de cohérence : un pipeline qui déploie plusieurs fois par jour ne peut pas cohabiter avec des branches qui vivent un mois.

La revue de code

Une demande de fusion (pull request) n'est pas une formalité administrative : c'est le point où trois choses se produisent — un second regard sur la correction, une diffusion de la connaissance dans l'équipe, et le déclenchement automatique du pipeline du chapitre 5.

Trois règles d'usage, et la première explique les deux autres.

Petit. Une demande de deux cents lignes est relue sérieusement ; une de deux mille est approuvée sans être lue. Le taux de détection s'effondre au-delà de quelques centaines de lignes, et c'est encore un argument pour les petits lots.

Rapide. Une demande qui attend deux jours bloque son auteur et se désynchronise de la branche principale — donc conflits.

Sur le code, pas sur la personne. « Cette boucle relit la base à chaque tour » plutôt que « tu n'as pas réfléchi ». C'est le post-mortem sans blâme du chapitre 1, appliqué à la relecture.

Quiz · vérifiez votre compréhension Sans réponse

Pourquoi ne rebase-t-on jamais une branche déjà poussée et partagée ?

Quiz · vérifiez votre compréhension Sans réponse

Une équipe qui déploie plusieurs fois par jour maintient des branches de fonctionnalité vivant trois semaines. Où est l'incohérence ?

À vous

L'exercice simule un dépôt et rend visible ce que la ligne de commande cache.

D'abord la forme de l'historique : les mêmes contributions intégrées par fusion puis par rebasage, avec le graphe affiché dans les deux cas. Vous constaterez que le contenu final est identique et que les identifiants de commits, eux, ont changé — d'où la règle.

Ensuite un simulateur de stratégie de branchement : vous faites varier la durée de vie des branches et le nombre de contributeurs, et le programme compte les conflits, la taille des lots intégrés et le délai moyen d'intégration. Les chiffres de GitFlow et du trunk-based se séparent nettement, et ils se relient directement aux indicateurs DORA du chapitre 1.

Exercice · JavaScript · à vous de jouer

Comparez fusion et rebasage sur le même historique, puis chiffrez l'effet de la durée de vie des branches.

En attente
// ── 1. Fusion contre rebasage ─────────────────────────────────────────────
// Un commit : identifiant, message, parents.
let compteur = 0;
const commit = (msg, parents) => ({ id: "c" + (++compteur), msg, parents });

function creerDepot() {
  const a = commit("A : socle", []);
  const b = commit("B : lecture config", [a]);
  const c = commit("C : correctif principal", [b]);      // sur main
  const d = commit("D : début fonctionnalité", [b]);     // sur la branche
  const e = commit("E : fin fonctionnalité", [d]);
  return { a, b, c, d, e };
}

function fusionner(depot) {
  // La fusion CONSERVE d et e tels quels, et crée un commit à deux parents.
  const m = commit("M : fusion de la branche", [depot.c, depot.e]);
  return [depot.a, depot.b, depot.c, depot.d, depot.e, m];
}

function rebaser(depot) {
  // ← à écrire : rejouer d et e AU-DESSUS de c. Ce sont de NOUVEAUX commits.
  return [];
}

function afficher(nom, commits) {
  console.log("   " + nom);
  for (const c of commits) {
    const p = c.parents.map((x) => x.id).join(", ") || "—";
    console.log("      " + c.id.padEnd(4) + c.msg.padEnd(28) + "parents : " + p);
  }
}

// ── 2. Effet de la durée de vie des branches ──────────────────────────────
// Modèle simple : chaque jour, chaque contributeur produit une modification.
// Une branche accumule ses modifications jusqu'à son intégration. Le risque
// de conflit croît avec le nombre de modifications faites AILLEURS pendant
// qu'elle vivait.
function simuler({ contributeurs, jours, dureeBranche }) {
  const modifsParJour = contributeurs;
  const integrations = Math.floor(jours / dureeBranche) * contributeurs;
  const tailleLot = dureeBranche;                    // modifications par lot
  const modifsAilleurs = 0;                          // ← à écrire
  const probaConflit = 0;                            // ← à écrire
  return { integrations, tailleLot, modifsAilleurs, probaConflit,
           delaiIntegration: dureeBranche / 2 };
}

// ── À VOUS ────────────────────────────────────────────────────────────────
// 1. Écrivez rebaser(). Comparez les identifiants : que constate-t-on, et
//    pourquoi ne rebase-t-on pas une branche partagée ?
// 2. Complétez simuler() : pendant qu'une branche vit d jours, les autres
//    contributeurs produisent (contributeurs − 1) × d modifications.
//    La probabilité de conflit croît avec ce nombre.
// 3. Comparez GitFlow (branches de 15 jours) et trunk-based (0,5 jour) sur
//    six contributeurs et trois mois. Reliez aux indicateurs DORA.

const d = creerDepot();
afficher("après fusion", fusionner(d));

Console de sortie
Le résultat s'affiche dans la console

En travaux pratiques

Travaux pratiques 2 · sur machine

Mise en place du dépôt et diagnostic réseau

Lancer l'application du fil rouge à la main, diagnostiquer une erreur de réseau, puis installer la stratégie de branchement qui servira tout le semestre.

2 h
Avant de commencer
  • Une machine Linux ou un WSL, avec Git, Node et curl
  • L'archive de l'application tickets fournie par l'enseignant
  1. 1. Lancer l'application, et échouer

    Démarrez l'application fournie, puis tentez de l'atteindre depuis un autre terminal avec curl. Elle ne répond pas. Ne modifiez rien tant que vous n'avez pas suivi les quatre questions du diagnostic.

  2. 2. Identifier l'interface d'écoute

    Listez ce qui écoute sur la machine et comparez l'adresse d'écoute à celle que vous interrogez. Corrigez la configuration, sans toucher au code métier.

  3. 3. Vérifier les droits

    Le script de démarrage fourni n'est pas exécutable. Rendez-le exécutable pour son seul propriétaire, sans donner de droit d'écriture au groupe ni aux autres. Écrivez la valeur octale que vous employez et justifiez-la.

  4. 4. Créer le dépôt et sa stratégie

    Initialisez un dépôt, poussez-le, protégez la branche principale, et écrivez un fichier CONTRIBUTING.md qui fixe la stratégie de branchement : durée de vie maximale d'une branche, taille maximale d'une demande de fusion, et délai maximal de relecture.

  5. 5. Fusion contre rebasage, sur un vrai conflit

    À deux, modifiez la même ligne du même fichier sur deux branches. Intégrez la première par fusion, la seconde par rebasage. Comparez les deux historiques obtenus, puis dites laquelle des deux opérations vous vous interdiriez si la branche avait déjà été poussée.

C'est réussi quand
  • curl obtient une réponse depuis un autre terminal, et vous savez dire quelle question du diagnostic a révélé la cause
  • Le script démarre et ses droits sont justifiés
  • La branche principale refuse un push direct
  • Vous savez énoncer la règle sur le rebasage d'une branche partagée

Ce que la suite en fait

Le bloc II attaque le premier vrai sujet : empaqueter l'application avec tout ce dont elle a besoin, pour que « ça marche sur ma machine » cesse d'être une excuse. Les droits Unix et les signaux de ce chapitre y reviennent dès le premier Dockerfile, et la question du port écouté y devient le premier bogue de tout le monde.

Et la revue de code retrouvera son sens au chapitre 5 : une demande de fusion est ce qui déclenche le pipeline, et le pipeline est ce qui rend la revue supportable — le relecteur n'a plus à vérifier que le code compile et que les tests passent.

À retenir

Flashcards · 1 / 5Toucher pour retourner
Fin de la leçon

Vous avez parcouru les 10 sections.

Marquez-la terminée pour faire avancer votre parcours, ou revenez sur un point avant de passer à la suite.