Deux développeurs attendent la fusion de leurs changements. Les tests sont verts dans les deux merge requests, les revues sont terminées et Git ne signale aucun conflit. Pourtant, quelques minutes après la seconde fusion, le formulaire d’import accepte un lot que le traitement serveur refuse. Aucun des deux développeurs n’avait testé cette combinaison de limites.
La vraie question est la composition exacte du code testé. Un résultat vert décrit une exécution sur un état donné ; il ne garantit pas qu’un autre changement, fusionné entre-temps, reste compatible. Le risque concerne les applications métier maintenues par plusieurs personnes, même lorsque les modifications portent sur des fichiers différents et passent chacune les mêmes contrôles.
Nous allons distinguer les pipelines de merge request, les résultats fusionnés et les merge trains GitLab, puis reproduire une fusion propre dont le contrat métier échoue. L’exercice repose sur deux plafonds d’import et une capacité agrégée. Il utilise un dépôt Git temporaire ; il ne lance aucun pipeline distant et ne mesure pas la charge d’un serveur réel.
Le développement d’applications web métier doit relier revue, tests et réception de la version réellement livrée. Un audit technique de votre application peut partir d’un incident de fusion pour retrouver ce qui a été testé, ce qui a changé ensuite et le contrôle manquant avant l’ouverture aux utilisateurs.
Pour qui : des équipes qui intègrent plusieurs changements à la fois
Le problème apparaît quand plusieurs changements convergent vers une même branche cible. Une merge request prépare un nouveau format de document ; une autre modifie un plafond, un droit ou une valeur par défaut. Les revues peuvent être correctes à leur échelle, tandis que la version réunie présente un comportement inédit. Le nombre de développeurs compte moins que le chevauchement des décisions.
Reconnaître les indices d’une composition jamais reçue
Un premier signal faible est la phrase « cela passe sur ma branche » après un échec reproductible sur la cible. Un deuxième se trouve dans les rapports attachés aux demandes : chaque preuve est récente, mais aucune ne contient l’autre changement. La proximité des horaires donne une impression de synchronisation que les références Git ne confirment pas.
Commencez par un incident où la panne est apparue après plusieurs fusions rapprochées. Relevez la cible avant ces fusions, les branches sources et le premier état qui échoue. Évitez de conclure trop vite à un test instable ou à un cache : ces pistes doivent être examinées, mais elles n’expliquent pas automatiquement une incompatibilité entre deux évolutions.
Distinguer ce risque des autres faux résultats rassurants
Un test peut aussi réussir parce qu’il vérifie la mauvaise règle ou parce que le job utile n’a jamais été exécuté. Le problème traité ici suppose un contrôle pertinent, présent et capable de détecter le défaut lorsqu’il voit le code combiné. Ajouter cent assertions à une branche isolée ne résout pas l’absence de cette composition dans le parcours de validation.
Le dossier code et tests confrontés à une règle métier indépendante couvre la qualité du résultat attendu. Le présent diagnostic ajoute une autre exigence : conserver ce contrôle et l’appliquer à l’ensemble susceptible d’être intégré. Les deux vérifications se complètent sans répondre à la même question.
Identifier ce que chaque type de pipeline teste réellement
La documentation des merge request pipelines précise que leur forme classique teste le contenu de la branche source, sans intégrer celui de la cible. Elle est disponible dans les offres Free, Premium et Ultimate. Le libellé « merge request » ne suffit donc pas à prouver que le résultat d’une fusion a été exécuté.
Les merged results pipelines, documentés pour Premium et Ultimate, testent un commit temporaire réunissant source et cible. Ce commit n’appartient pas à l’une de ces branches. En présence d’un conflit empêchant cette préparation, GitLab peut exécuter un pipeline de merge request standard à la place : inspectez le type effectivement obtenu.
| Contrôle | Composition examinée | Question encore ouverte |
|---|---|---|
| MR classique | Branche source de la demande. | Fonctionne-t-elle avec la cible actuelle ? |
| Résultat fusionné | Source réunie à une version de la cible. | Une autre demande va-t-elle entrer avant celle-ci ? |
| Merge train | Demande, cible et demandes précédentes dans la file. | Le comportement métier est-il testé ? |
Ce tableau décrit la portée des preuves, pas un classement universel des outils. Une application peu modifiée peut être reçue avec une intégration séquentielle explicite. Un produit où plusieurs équipes livrent chaque jour exige davantage de coordination. Dans les deux cas, le bon arbitrage dépend des changements simultanés et du coût d’un défaut sur la branche partagée.
Exemple concret : deux plafonds corrects produisent un lot impossible
Le scénario fictif concerne un portail qui reçoit des pièces jointes par lot. Son contrat impose que le lot maximal annoncé à l’utilisateur reste inférieur ou égal à une capacité agrégée de 20 MiB. Initialement, le portail accepte cinq fichiers de 2 MiB chacun, soit un maximum de 10 MiB. Un MiB représente ici 1 048 576 octets ; ces seuils ne sont pas des recommandations d’hébergement.
Deux demandes indépendantes devant la même capacité
La demande A augmente le nombre de fichiers à huit, en conservant 2 MiB par fichier. Son maximum atteint 16 MiB et respecte le contrat. La demande B augmente la taille unitaire à 3 MiB, en conservant cinq fichiers. Son maximum atteint 15 MiB et respecte également le contrat. Les deux résultats sont réellement corrects pour les états qu’ils examinent.
Les paramètres sont volontairement placés dans deux fichiers distincts : count.json pour le nombre et size.json pour la taille. La capacité de 20 MiB reste dans un troisième fichier. Le test d’intégration lit ces trois entrées puis compare le produit du nombre par la taille à la capacité, sans modifier son attente entre A et B.
Une fusion propre qui dépasse le contrat de quatre MiB
Après réunion, le portail annonce huit fichiers de 3 MiB, soit 24 MiB. La capacité n’a pas changé : le dépassement atteint 4 MiB, ou 20 % de la limite retenue. Git peut fusionner les fichiers sans conflit textuel, tandis que le même test d’intégration refuse le résultat. Le vert de chaque branche ne constitue pas une preuve sur ces 24 MiB.
La documentation de git merge décrit la réunion d’historiques et la résolution des conflits de contenu. Elle ne fournit pas une validation des contraintes métier de votre logiciel. Dans l’exercice, l’absence d’entrée non fusionnée dans l’index Git et l’échec du contrat sont donc deux observations compatibles.
Reproduire la fusion et lire les limites de la démonstration
Le script Python de fusion compatible crée un dépôt temporaire sans dépôt distant, construit la base et les deux branches, puis effectue une véritable fusion Git. Il conserve les identifiants des commits dans son résultat avant de retirer uniquement son répertoire temporaire. Le dépôt depuis lequel vous lancez le programme n’est pas modifié.
Exécutez le fichier avec Python 3 sur une machine où Git est disponible. Le résultat doit montrer 10 MiB pour la base, 16 pour A, 15 pour B et 24 pour leur réunion. La fusion possède deux parents et aucun conflit textuel restant. Seul l’état combiné dépasse la capacité dans cette première série de configurations.
Le programme vérifie aussi qu’un lot de huit fichiers de 3 MiB satisfait les limites unitaires tout en dépassant le plafond agrégé. Il ne crée pas ces fichiers en mémoire, n’envoie aucune requête HTTP et ne teste ni Nginx, ni PHP, ni antivirus. Le contrat de 20 MiB porte sur les contenus du modèle ; l’enveloppe multipart et les autres coûts doivent être qualifiés séparément dans une application réelle.
Trois raccourcis sont ensuite confrontés au résultat attendu : considérer les deux succès isolés comme suffisants, ne regarder que la plus grande pièce et ignorer le changement de cible dans une preuve. Ces témoins rendent le défaut vérifiable. Ils ne constituent ni une certification de GitLab ni une mesure du nombre de régressions qu’un train éviterait dans votre organisation.
Pourquoi tester la cible une fois ne règle pas toutes les fusions concurrentes
Supposons que les résultats fusionnés d’A et B soient préparés à partir de la même cible initiale. Le premier vérifie 16 MiB, le second 15 MiB. Si A entre ensuite dans la cible, la situation pertinente pour B devient huit fichiers et non cinq. Le résultat déjà calculé pour B ne prouve pas ce nouvel assemblage, même si personne n’a modifié sa branche source.
Retrouver le changement qui rend la preuve insuffisante
Dans l’incident, ne classez pas l’ancien résultat comme mensonger : il décrit correctement un autre état. Ajoutez la référence de cible utilisée au rapport pour rendre cette limite visible. Une heure de fin, un nom de branche ou une capture de voyant vert ne remplace pas cette identification. Une branche peut avancer sans changer de nom.
Paradoxalement, plus les contrôles isolés s’exécutent vite et en parallèle, plus les deux changements peuvent arriver presque ensemble à la fusion. La vitesse reste utile, mais elle ne remplace pas une règle d’intégration. Refaire exactement le même pipeline sur le même assemblage ne permet pas de recevoir une composition qui n’y figure toujours pas.
Garder la concurrence visible dans la décision de fusion
Le responsable de livraison doit savoir si d’autres demandes sont susceptibles d’entrer avant la sienne. Sur un flux séquentiel, cela impose de réexaminer la preuve après chaque changement de cible. Sur un flux organisé en train, il faut suivre la position et la composition associées au contrôle. Le choix ne doit pas rester une convention orale entre deux développeurs disponibles ce jour-là.
Le coût caché apparaît lorsque l’intégration est reprise après réception métier : il faut retrouver les données utilisées, refaire les scénarios et expliquer pourquoi un accord récent ne couvre plus la version. Un historique technique précis réduit cette enquête. Il ne supprime pas la nécessité de faire réexaminer une fonctionnalité dont le comportement a changé après la recette.
Ce qu’un merge train apporte et ce qu’il ne décide pas
La documentation des merge trains GitLab décrit une file où chaque demande est testée avec la cible et les demandes qui la précèdent. Les pipelines peuvent s’exécuter en parallèle, mais une demande attend la réussite de son contrôle et la fusion de celles placées avant elle. Cette fonctionnalité relève des offres Premium et Ultimate.
Dans notre scénario, placer B derrière A doit conduire le contrôle concerné à examiner les 24 MiB. Le défaut devient alors visible avant l’intégration de cette combinaison. C’est une application de la portée documentée du train à notre modèle ; l’exercice local ne prétend pas avoir exécuté ce parcours sur une instance GitLab.
La documentation précise aussi qu’une demande en échec sort du train et que les pipelines des demandes suivantes sont recréés pour leur nouvelle composition. Un pipeline annulé dans ce contexte n’indique donc pas forcément un runner défaillant. Il faut d’abord vérifier si la file a changé, puis rechercher le résultat qui correspond à sa composition actuelle.
Un train ne rend pas un mauvais test pertinent et ne reçoit pas l’exploitation à votre place. Si aucun contrôle ne confronte le lot maximal à sa capacité, les 24 MiB peuvent rester verts. La conception des scénarios, les données de recette, les accès et les intégrations externes gardent leurs propres critères ; le train apporte la bonne réunion de changements à ces vérifications.
Conserver une preuve qui nomme le code, la cible et les contrôles
La référence des variables GitLab expose notamment CI_MERGE_REQUEST_EVENT_TYPE, avec les valeurs detached, merged_result et merge_train. Elle distingue aussi les références source et cible disponibles selon le contexte. Ne remplissez pas une référence absente avec le nom de branche en prétendant conserver la même preuve.
Décrire les entrées et la sortie du contrôle de compatibilité
Le contrat proposé associe l’identifiant du pipeline, le commit effectivement testé, la source, la cible connue et le type d’exécution. Il conserve les entrées de configuration nécessaires à la reproduction, la version du test et son résultat. La sortie contient le verdict de compatibilité et le rapport de l’exercice, sans lui attribuer une autorisation générale de déploiement.
La journalisation doit distinguer un job prévu, un job exécuté et un job dont le résultat conditionne réellement la fusion. Faites vérifier cette distinction par la personne responsable de la CI. Un nom de stage rassurant ne suffit pas si la règle d’inclusion exclut le témoin de capacité dans le contexte où les changements sont réunis.
Retrouver le contrôle courant sans remplacer l’historique
Gardez les résultats anciens comme preuves historiques, mais marquez leur périmètre. La référence API des merge trains fournit un point d’entrée pour examiner les trains et les éléments associés. Un suivi d’exploitation peut utiliser la CLI ou l’API pour relier demande, pipeline et état courant sans dépendre d’une capture manuelle du navigateur.
L’exercice utilise un contrat local volontairement strict : source, cible et commit testé doivent correspondre à la demande de preuve. Ce n’est pas un algorithme universel d’autorisation GitLab. Les méthodes de fusion peuvent produire des identifiants différents ; une équivalence éventuelle doit être établie explicitement, jamais déduite d’un message de commit ressemblant ou d’un ancien statut réussi.
Corriger l’incompatibilité sans déplacer silencieusement la limite
Quand A et B échouent ensemble, ne haussez pas automatiquement la capacité à 24 MiB pour rendre le test vert. La limite initiale peut protéger une dépendance, un délai ou une ressource qui n’a pas été redimensionnée. Le contrôle vient précisément de révéler que la promesse utilisateur et le traitement prévu ne correspondent plus.
Arbitrer la promesse avec le responsable métier
Une correction possible dans le scénario conserve 3 MiB par fichier mais ramène le lot à six fichiers, soit 18 MiB. Le script vérifie cette variante. Elle est compatible avec le contrat fictif, mais elle change la proposition d’A : l’équipe métier doit accepter six fichiers au lieu de huit. Un test réussi ne vaut pas cet accord.
Une autre décision pourrait garder huit fichiers en réduisant la limite unitaire, ou conserver les deux hausses après une étude réelle de capacité. Le choix doit examiner les usages : import administratif ponctuel, traitement documentaire en masse ou parcours mobile n’ont pas forcément les mêmes contraintes. Les chiffres de l’exercice servent à rendre l’arbitrage lisible, pas à prescrire votre infrastructure.
Recevoir le nouveau comportement jusqu’au message utilisateur
La correction doit aligner le formulaire, la validation serveur et les messages d’erreur. Un écran qui promet toujours huit fichiers alors que le serveur n’en accepte plus que six laisse le problème au support. La recette inclut le lot maximal accepté, le premier dépassement refusé et la conservation des documents lorsque l’utilisateur doit corriger sa demande.
Après modification, une nouvelle preuve doit porter sur la composition corrigée. Le dossier recevoir une version entre sandbox, recette et production décrit le lien entre accord métier et version. Il aide à ne pas réutiliser l’accord sur l’ancienne promesse comme une validation automatique du nouvel import.
Encadrer l’urgence et la sortie de file sans perdre la preuve
Une correction urgente peut modifier l’ordre d’intégration prévu. Le point à traiter est l’effet sur les compositions déjà testées : une demande passée devant les autres change ce qu’elles devront rencontrer. Définissez qui peut décider cette exception, quelle preuve doit être reconstruite et comment les équipes identifient les rapports devenus insuffisants.
GitLab documente des possibilités de contournement du train et leur encadrement. La documentation courante indique une disponibilité générale de l’application obligatoire des trains depuis GitLab 19.3, avec plusieurs niveaux d’exception. Vérifiez la version, l’offre et la configuration de votre instance avant de considérer la file comme obligatoire ; l’activation d’un train ne suffit pas à démontrer cette politique.
Dans le runbook proposé, une sortie de file ouvre une revue de composition plutôt qu’une simple relance automatique. Les responsables retrouvent la correction entrée, les demandes affectées et les contrôles à réexécuter. Le monitoring distingue attente normale, reconstruction de preuve et échec métier. Une seule alerte « pipeline lent » masquerait ces situations derrière le même symptôme.
Le retour arrière doit aussi conserver la question des données et des effets déjà produits. Retirer un changement de code ne reconstitue pas automatiquement des documents supprimés ou un import partiellement traité. La compatibilité de fusion couvre le code assemblé ; l’exploitation garde une procédure séparée pour retrouver les opérations engagées et reprendre les dossiers concernés.
Erreurs fréquentes : croire que le nom du pipeline suffit
Relancer une preuve sur la même cible devenue ancienne
Un nouveau résultat horodaté peut porter sur un assemblage inchangé et rester inutile pour la décision actuelle. Avant de relancer, identifiez la composition requise. La reprise doit démontrer que les changements déjà entrés sont pris en compte ; elle ne doit pas seulement remplacer un voyant par un autre après quelques minutes de calcul.
Le témoin local qui ignore la cible illustre ce défaut : il accepte le succès de B sur la base initiale alors que l’on demande une preuve après A. Le nom de B et son code source sont identiques, mais le contexte pertinent a changé. Ce contrôle évite de confondre stabilité de la demande et stabilité de son environnement d’intégration.
Choisir entre vitesse et contrôle sans mesurer le travail repris
Supprimer la vérification d’intégration pour raccourcir le pipeline peut déplacer le coût vers la recette ou l’exploitation. Inversement, exécuter toutes les campagnes longues sur chaque détail peut saturer les runners. Mesurez le délai jusqu’à une décision utile, les reconstructions dues à la file et le temps humain passé à diagnostiquer des combinaisons jamais examinées.
Le dossier distinguer une CI utile d’un pipeline décoratif aide à choisir les contrôles qui décident réellement. Pour ce risque précis, protégez le test commun de capacité dans les contextes combinés avant d’optimiser les tâches périphériques. Sa durée doit être observée dans votre projet, sans promesse de gain universelle.
Plan d’action : recevoir une combinaison avant d’étendre la règle de fusion
Reconstituer une paire de changements réellement interdépendants
Choisissez deux évolutions qui touchent une même contrainte par des chemins différents : droits et écran, format émis et importeur, nombre de pièces et taille maximale. Décrivez une règle attendue indépendante de chaque branche. Rejouez la base, chaque modification isolée et leur réunion ; vous devez pouvoir expliquer les quatre résultats avant de modifier la configuration CI.
Conservez les identifiants Git, les valeurs de configuration et la sortie du contrôle dans le dossier de recette. S’il n’existe aucun test capable de distinguer la combinaison incorrecte, commencez par le construire. L’adoption d’un mécanisme de file ne compense pas l’absence de cette règle. Le propriétaire métier doit pouvoir comprendre ce qui est refusé sans lire tout le pipeline.
Qualifier l’instance et observer le parcours obtenu
Relevez l’offre GitLab, la version et les réglages du projet. Comparez les jobs présents dans les pipelines de source, de résultat fusionné et de train lorsque ces fonctions sont disponibles. Testez une demande en échec puis son retrait de la file, et retrouvez le contrôle reconstruit pour la suivante. Une option enregistrée dans les paramètres ne constitue pas cette preuve d’exécution.
Si les fonctions de train ne sont pas disponibles, organisez une intégration séquentielle contrôlée avec une nouvelle validation de la composition après changement de cible. Cette procédure doit avoir un responsable et des critères de reprise explicites. Elle ne devient pas équivalente à un train natif par simple convention de nommage ; mesurez les oublis et les délais qu’elle laisse encore possibles.
Décider sur les preuves plutôt que sur le volume de jobs
Le pilote doit relier chaque fusion à la composition reçue et conserver les écarts constatés. Suivez les défauts détectés avant intégration, les rapports périmés présentés à tort et les reprises après urgence. Comparez des périodes de charge comparables ; un mois sans incident avec très peu de changements ne prouve pas que la nouvelle organisation absorbera une livraison simultanée de plusieurs équipes.
- Ouvrir la règle de fusion lorsque le témoin incompatible échoue au bon endroit et que le témoin corrigé passe avec une preuve retrouvable.
- Conserver le pilote lorsque les contrôles sont corrects mais que les retraits de file ou les exceptions restent mal suivis.
- Refuser l’extension lorsque la composition testée est inconnue ou qu’un job indispensable disparaît du contexte combiné.
La responsabilité finale se partage entre règles métier, configuration CI et réception de livraison. Attribuez ces décisions à des personnes identifiées et gardez les conditions de retour au traitement séquentiel. Une liste de pipelines verts constitue une trace technique ; une chaîne de preuves expliquée permet à l’équipe de décider quelle version elle peut effectivement intégrer.
Contenus liés pour relier tests, réception et application en service
La qualité de la règle testée et la composition du code sont deux dimensions différentes. Le dossier sur les tests confrontés à un résultat métier indépendant aide à éviter un contrôle qui reproduit l’erreur du développement. La méthode de réception entre environnements relie ensuite cet accord aux données, accès et effets externes.
Après intégration, il reste à vérifier que les processus exécutent réellement la version attendue. Le diagnostic Symfony Messenger : l’ancien worker survit au déploiement traite ce décalage côté exploitation. Un code correctement fusionné et une application effectivement mise à jour demandent des preuves complémentaires, particulièrement lorsque des traitements asynchrones poursuivent leur travail.
Conclusion : valider le code réuni, pas seulement ses changements séparés
Les deux demandes de l’exemple ne mentent pas : 16 MiB et 15 MiB respectent chacune la capacité de 20 MiB. C’est leur réunion à 24 MiB qui change la décision. La fusion textuelle réussie confirme que Git a assemblé les fichiers ; le test métier montre que cette promesse d’import ne tient plus dans le contrat retenu.
Une équipe peut donc conserver ses tests utiles tout en améliorant l’endroit où ils s’exécutent. Source, cible, demandes précédentes et commit testé doivent rester identifiables. La file d’intégration organise cette rencontre ; les scénarios, les responsables et les preuves de réception lui donnent un sens pour le produit.
Un audit technique des tests et du parcours de livraison peut partir d’une seule incompatibilité reproduite. Il permet de décider s’il manque une règle métier, une composition de test, une coordination de fusion ou une preuve sur la version ouverte aux utilisateurs.
Dawap accompagne le développement et l’évolution de logiciels web sur mesure en reliant ces étapes aux usages réels. Nous pouvons cadrer un pilote avec votre équipe, éprouver les changements concurrents et structurer une réception qui reste compréhensible lorsque plusieurs livraisons avancent en même temps.