web-dev-qa-db-fra.com

Annulation automatique des validations qui échouent à la génération

Un de mes collègues m'a dit qu'il envisageait de faire en sorte que notre serveur CI annule les validations qui ont échoué à la génération, donc le HEAD dans master est toujours stable (comme en passant la génération au moins) .

Est-ce une meilleure pratique ou cela peut être plus problématique que de laisser master cassé jusqu'à ce que le développeur le corrige?

Ma pensée est que l'annulation de la validation rendra plus complexe la tâche de relecture de la validation et du correctif (le développeur devra annuler la restauration puis valider le correctif, ce qui encombrera également le git log) et nous devons simplement laisser la validation, puis valider le correctif. Bien que je vois certains avantages à avoir master stable, ce retour des validations échouées ne me convainc pas.

edit: Peu importe s'il s'agit de master ou de toute autre branche de développement, mais la question reste la même: le système CI doit-il annuler une validation qui a échoué à la génération?

une autre modification (longue): Ok, nous utilisons git d'une manière étrange. Nous pensons que le concept de branches va à l'encontre du véritable CI, car s'engager dans une branche vous isole des autres développeurs et de leurs changements, et ajoute du temps lorsque vous devez réintégrer votre branche et faire face à d'éventuels conflits. Si tout le monde s'engage sur master, ces conflits sont réduits au minimum et chaque validation passe tous les tests.

Bien sûr, cela vous oblige à pousser uniquement stable (ou vous cassez la version) et à programmer plus soigneusement pour ne pas casser la compatibilité descendante ou faire basculer les fonctionnalités lors de l'introduction de nouvelles fonctionnalités.

Il y a des compromis à faire CI tel ou tel chemin, mais cela est hors de portée de la question (voir question connexe pour cela). Si vous préférez, je peux reformuler la question: une petite équipe de développeurs travaille ensemble dans une branche de fonctionnalités. Si un développeur valide quelque chose qui rompt la construction de cette branche, le système CI doit-il annuler la validation ou non?

44
Carlos Campderrós

Je serais contre le faire pour les raisons suivantes:

  • Chaque fois que vous configurez un outil automatisé pour changer le code en votre nom, il y a le risque qu'il se trompe ou qu'une situation se produise où vous en avez besoin pour arrêter de faire ce changement (par exemple , la dernière version de Google Mock contenait un bogue, donc ce n'est pas votre code qui échoue) et vous devez perdre du temps à le reconfigurer. De plus, il y a toujours un léger risque que la construction échoue à cause d'un bogue dans le système de construction, plutôt que d'un bogue dans votre code. Pour moi, CI consiste à gagner la confiance que mon code est correct; cela ne ferait que le transformer en une autre source de problèmes potentiels dont je devrais m'inquiéter.

  • Les types de bugs qui cassent "la construction" devraient être des erreurs stupides qui prennent très peu de temps à corriger (comme vous l'avez indiqué dans un commentaire, cela est vrai pour vous). Si des bogues plus subtils et compliqués arrivent régulièrement sur master, alors la bonne solution n'est pas de "le réparer plus vite", c'est d'être plus prudent lors de l'examen des branches de fonctionnalités avant qu'elles ne soient fusionnées.

  • Laisser le maître non constructible pendant quelques minutes pendant que le bug est corrigé correctement ne fait de mal à personne. Ce n'est pas comme si le PDG vérifie personnellement le master et publie le code directement aux clients à tout moment aléatoire (du moins, espérons-le, sans votre implication). Dans le cas très improbable où vous devez publier quelque chose avant de pouvoir corriger le bogue, alors vous pouvez facilement prendre la décision de revenir manuellement avant de publier.

56
Ixrec

Entendons-nous d'abord sur les conditions.

J'utilise personnellement les termes Construction continue et Intégration continue pour distinguer deux scénarios différents:

  • Build continu: un outil qui vérifie périodiquement si le référentiel a changé depuis la dernière build, et construit/test si c'est le cas.
  • Intégration continue: un outil qui prend les requêtes Pull et les valide par rapport à la dernière tête prior pour les rendre visibles.

Ce dernier, l'intégration continue, signifie que le référentiel qu'il protège est toujours vert1: c'est strictement mieux.

Votre question n'a de sens que pour la construction continue, donc je répondrai en supposant que c'est votre configuration.

1: Les causes environnementales peuvent également gâcher une construction, par exemple un test avec une année codée en dur (2015) peut commencer à échouer en janvier 2016, un disque peut être plein, ... Et bien sûr, il y a le fléau des tests instables . J'ignore hautainement ces problèmes ici; sinon nous n'irons jamais nulle part.


Si vous avez une configuration de construction continue, vous pouvez en effet automatiser l'inversion des validations qui peuvent avoir interrompu la génération, mais il existe plusieurs subtilités.

  • Vous ne pouvez pas réellement supprimer les commits: d'autres collègues les ont peut-être déjà vérifiés et les repousseront la prochaine fois qu'ils tenteront de valider. Au lieu de cela, une inversion devrait commettre un reverse diff. Oh, et les collègues vous détesteront pour avoir retourné leur travail quand il était correct, car ils devront trouver un moyen de le repousser à nouveau ...
  • Vous ne pouvez pas seulement supprimer le dernier commit (c'est une fusion), mais vous devez supprimer tous les commits ... jusqu'à un certain point. Par exemple, le dernier bon commit connu (attention au boot-strapping du système).
  • Vous devez penser aux causes externes (problèmes environnementaux) et éviter une configuration qui rétablit tout au jour 0. Heureusement, le retour au dernier bon commit connu contourne ce problème.
  • Vous devez penser que la dernière bonne construction connue peut ne plus se construire (problèmes d'environnement), auquel cas il est probable que toutes les autres validations seront annulées. Idéalement, en cas d'échec, et avant de revenir en arrière, vous devriez vérifier la dernière bonne version connue et la tester à nouveau. S'il passe, revenez, sinon, lancez une alerte.

Notez qu'avec ce système, en cas de test instable ou si un collègue commet souvent de la merde, de nombreux bons commits seront annulés. Vos collègues vous détesteront alors.


J'espère que mon histoire d'horreur a révélé les problèmes d'autoriser un référentiel cassé et vous allez maintenant implémenter un pipeline d'intégration continue approprié où les RP ne sont jamais directement poussés vers le référentiel mais mis en file d'attente pour la fusion dans une file d'attente de travail, et intégrés un à la fois ( ou par roll-up):

  • récupérer la tête du référentiel localement
  • appliquer des demandes de tirage
  • construire et tester
  • en cas de succès, pousser vers le référentiel, sinon marquer comme échec
  • passer aux demandes suivantes

Après avoir essayé les deux, c'est strictement mieux.

26
Matthieu M.

Est-ce une meilleure pratique ou cela peut être plus problématique que de simplement laisser master cassé jusqu'à ce que le développeur le corrige?

C'est problématique. Une personne décidant que "le maître HEAD est cassé; je reviendrai sur le changement supérieur" est complètement différente du système CI qui fait de même.

Voici quelques inconvénients:

  • Des erreurs dans le processus d'inversion automatisé visseront le référentiel;

  • cela suppose un seul ensemble de modifications (le plus haut) vissé la construction (ce qui est irréaliste)

  • Les responsables auront plus de travail à faire pour résoudre le problème, que simplement enquêter et valider (ils devront également regarder l'historique inversé)

Nous pensons que le concept de branches va à l'encontre du véritable CI, car s'engager dans une branche vous isole des autres développeurs et de leurs changements, et ajoute du temps lorsque vous devez réintégrer votre branche et faire face à d'éventuels conflits.

Cette croyance (branches vs CI) est incorrecte. Pensez à conserver n branche stable, où vous ne validez que testé unitaire ensembles de modifications. Le reste (succursales de fonctionnalités et succursales locales) devrait être de la responsabilité de chaque développeur et ne devrait en aucun cas faire partie de votre politique CI.

Dans les branches de fonctionnalités, vous voulez être isolé des autres développeurs. Cela vous permet de:

  • effectuer un codage exploratoire

  • expérimenter avec la base de code

  • effectuer des validations partielles (valider efficacement le code non fonctionnel) pour configurer des points de sauvegarde (au cas où vous bousilleriez), pour créer un historique des modifications plus significatif (via des messages de validation), et pour sauvegarder votre travail et passer complètement à autre chose (dans le temps qu'il vous faut pour écrire "git commit && git checkout")

  • effectuer des tâches de faible priorité qui prennent beaucoup de temps (par exemple, vous voulez effectuer un refactoring qui modifie les 80 classes de la couche de données: vous en changez deux par jour, jusqu'à ce que vous les changiez toutes et que le code compile (mais vous pouvez le faire sans affecter personne jusqu'à ce que vous puissiez faire un seul commit).

Si un développeur valide quelque chose qui rompt la construction de cette branche, le système CI doit-il annuler la validation ou non?

Ça ne devrait pas. La validation du code stable sur votre branche CI est la responsabilité du committer, pas un système automatisé.

5
utnapistim

Je suggère d'utiliser un environnement Gerrit + Jenkins pour garder votre branche principale toujours en bon état. Les gens poussent leur nouveau code vers Gerrit qui déclenche un travail Jenkins pour extraire ce correctif, les builds, les tests, etc. Si d'autres développeurs comme votre correctif et Jenkins terminent son travail avec succès, alors Gerrit fusionnera ce morceau de code dans votre branche principale.

C'est un environnement similaire décrit par @ brian-vandenberg

En plus de maintenir votre branche en bon état, vous ajoutez également une étape de révision du code qui améliore la qualité du code et le partage des connaissances sur votre logiciel.

[1] Jenkins https://jenkins-ci.org/

[2] Gerrit https://www.gerritcodereview.com/

2
Gustavo Coelho

Le CI ne doit jamais modifier l'historique de validation du dépôt.

La solution correcte ici est qu'aucun ajout ne soit ajouté à la branche principale s'ils n'ont pas été testés et vérifiés.

Travaillez-vous sur des branches de fonctionnalités, faites exécuter automatiquement le CI sur celles-ci, et si les builds échouent, ne les fusionnez pas dans master.

Vous pouvez avoir une version supplémentaire qui teste les fusions si celles-ci sont un problème, en s'exécutant sur la branche de fonctionnalité, et pendant la génération fusionnant maître/intégration/quoi que ce soit dans la branche locale, puis en exécutant des tests.

1
Daenyth

Nous utilisons Jenkins pour notre serveur de génération et utilisons le modèle de contrôleur d'accès pour pousser les validations - où une combinaison de Jenkins et de déclencheurs de validation (qui garantissent que les pairs examinateurs ont fait leur travail) est le contrôleur d'accès.

Les validations sont envoyées indirectement via un curl à Jenkins, où il clone le référentiel maître, puis récupère les validations à fusionner et effectue toutes les générations requises (pour Linux/solaris). Si toutes les générations sont terminées, la validation est poussée.

Cela évite de nombreux sinon tous les problèmes discutés jusqu'à présent:

  • modification de l'histoire
  • obtenir l'historique correct si vous êtes le développeur qui doit réparer la rupture
  • l'instabilité (sous forme de versions cassées) n'est jamais introduite

Cela nous permet également d'appliquer directement d'autres exigences, telles que la réussite des tests unitaires.

1
Brian Vandenberg

La question posée est défectueuse. Je respecte cependant cette déclaration

"Nous pensons que le concept de branches va à l'encontre du vrai CI, car s'engager dans une branche vous isole des autres développeurs et de leurs changements"

Ce que vous devez faire, c'est ces étapes

  • travaillez hors master si vous le souhaitez (c'est bien et continuez à tirer les changements de tout le monde) MAIS ne vous engagez pas à masteriser localement
  • JUSTE AVANT de valider vos modifications sur master, créez une branche avec submit_XXXXXX
  • demandez à votre génération automatisée de récupérer toutes les branches de submit_XXX
  • Option 1: construire des pauses ou fusionner des pauses ... le changement est rejeté et il n'atterrit jamais sur le maître
  • Option 2: Build Works, Jenkins pousse le maître et le met à jour

ALORS, ce que nous faisons est de mettre un crochet de validation git pour empêcher TOUT LE MONDE de réellement s'engager à maîtriser. Cela fonctionne très bien .... AUCUN build cassé jamais et AUCUN rétablissement ne revient du maître non plus.

plus tard, Dean

0
Dean Hiller

Combien de fois avez-vous reçu cet e-mail automatisé disant que votre dernier commit a interrompu la construction? Combien de fois est-ce mal? Mais maintenant, vous devez vérifier pour voir si c'était bien vous ou quelqu'un d'autre qui a fait un autre commit à peu près au même moment. Ou peut-être que c'était quelque chose d'environnement.

Si le système n'est pas sûr, je ne veux certainement pas l'automatiser.

0
Mohair