Gestion de plusieurs succursales en intégration continue

85

J'ai été confronté au problème de la mise à l'échelle de l'IC dans mon entreprise et en même temps, j'ai essayé de déterminer quelle approche adopter en ce qui concerne l'IC et les branches multiples. Il y a une question similaire à stackoverflow, plusieurs branches de fonctionnalités et intégration continue . J'en ai commencé un nouveau parce que j'aimerais avoir plus de discussion et fournir une analyse dans la question.

Jusqu'à présent, j'ai trouvé qu'il y a 2 approches principales que je peux prendre (ou peut-être quelques autres ???).

Donc, il semble que si je veux fournir aux développeurs des CI pour leurs propres branches personnalisées, j'ai besoin d'outils spéciaux pour Jenkins (API ou shellscripts ou quelque chose?) Et gérer la mise à l'échelle. Ou je peux leur dire de fusionner plus souvent avec DEV et de vivre sans CI sur des branches personnalisées. Laquelle choisiriez-vous ou y a-t-il d'autres options?

toomasr
la source

Réponses:

69

Lorsque vous parlez de mise à l'échelle de CI, vous parlez vraiment de mise à l'échelle de l'utilisation de votre serveur CI pour gérer toutes vos branches de fonctionnalités avec votre ligne principale. Au départ, cela semble être une bonne approche, car les développeurs d'une branche bénéficient de tous les avantages des tests automatisés inclus dans les travaux CI. Cependant, vous rencontrez des problèmes de gestion des travaux du serveur CI (comme vous l'avez découvert) et, plus important encore, vous ne faites pas vraiment CI. Oui, vous utilisez un serveur CI, mais vous n'intégrez pas en permanence le code de tous vos développeurs.

L'exécution d'un véritable CI signifie que tous vos développeurs s'engagent régulièrement sur la ligne principale. Facile à dire, mais le plus dur est de le faire sans casser votre application. Je vous recommande vivement de consulter la livraison continue , en particulier la section Garder votre application libérable dans le Chapitre 13: Gestion des composants et des dépendances . Les principaux points sont:

  • Masquez la nouvelle fonctionnalité jusqu'à ce qu'elle soit terminée ( bascule de fonctionnalité AKA ).
  • Effectuez toutes les modifications de manière incrémentielle sous la forme d'une série de petits changements, dont chacun est libérable.
  • Utilisez la branche par abstraction pour apporter des modifications à grande échelle à la base de code.
  • Utilisez des composants pour découpler les parties de votre application qui changent à des rythmes différents.

Ils sont assez explicites, sauf branche par abstraction. Ceci est juste un terme sophistiqué pour:

  1. Créez une abstraction sur la partie du système que vous devez modifier.
  2. Refactorisez le reste du système pour utiliser la couche d'abstraction.
  3. Créez une nouvelle implémentation, qui ne fait pas partie du chemin du code de production tant qu'elle n'est pas terminée.
  4. Mettez à jour votre couche d'abstraction pour déléguer à votre nouvelle implémentation.
  5. Supprimez l'ancienne implémentation.
  6. Supprimez la couche d'abstraction si elle n'est plus appropriée.

Le paragraphe suivant de la section Branches, flux et intégration continue du chapitre 14: Contrôle de version avancé résume les impacts.

L'approche incrémentale nécessite certainement plus de discipline et de soin - et en fait plus de créativité - que de créer une branche et de plonger dans la refonte de l'architecture et le développement de nouvelles fonctionnalités. Mais cela réduit considérablement le risque que vos modifications interrompent l'application et vous fera gagner, à vous et à votre équipe, beaucoup de temps pour fusionner, corriger les ruptures et mettre votre application dans un état déployable.

Il faut un certain changement d'esprit pour abandonner les branches de fonctionnalités et vous obtiendrez toujours une résistance. D'après mon expérience, cette résistance est basée sur le fait que les développeurs ne se sentent pas en sécurité lors de la validation du code sur la ligne principale et c'est une préoccupation raisonnable. Cela découle généralement d'un manque de connaissances, de confiance ou d'expérience avec les techniques énumérées ci-dessus et peut-être du manque de confiance avec vos tests automatisés. Le premier peut être résolu grâce à la formation et au support des développeurs. Ce dernier est un problème beaucoup plus difficile à traiter, mais le branchement ne fournit aucune sécurité supplémentaire, il reporte simplement le problème jusqu'à ce que les développeurs se sentent suffisamment en confiance avec leur code.

Tom Howard
la source
4
Tom, cela ne fonctionne bien que si 1) la version et la mise à jour sont relativement faciles 2) la plupart de vos modifications sont bien isolées. Cela est vrai pour les développeurs Web, mais si vous faites des versions de produits en boîte, les versions stables doivent rester stables à tout prix, car les correctifs sont vraiment coûteux, voire impossibles dans un grand environnement d'entreprise.
Jevgeni Kabanov
13
véritable CI n'est pas seulement une question d'intégration, c'est aussi une question de rétroaction
Anton Arhipov
3
J'ai choisi cela comme réponse (au moins donné la prime, s'il vous plaît laissez-moi savoir si je dois encore le marquer comme correct) mais je pense que ce n'est pas une solution à mon problème. J'ai écrit un suivi sur zeroturnaround.com/blog/…
toomasr
1
@Jevgeni Kabanov et @toomasr Vous semblez tous les deux supposer que faire un véritable CI signifie renoncer à la qualité et cela ne fonctionne que pour les développeurs Web, car il est si facile de proposer des correctifs. Je suppose que ce qui vous inquiète, c'est un commit douteux juste avant une sortie. Oui, cela peut entraîner une mauvaise version qui peut être coûteuse à réparer. Cependant, un commit douteux sur une branche de fonctionnalité juste avant sa sortie est tout aussi mauvais. Si vous sentez qu'il y a une différence, veuillez partager votre raisonnement. Une façon de lutter contre cela (si la validation concernait la ligne principale ou une branche de fonctionnalité) consiste à utiliser l'approche de livraison continue.
Tom Howard
1
Oh, et BTW, depuis un peu plus de 4 ans, ma principale expérience de développement a été dans les institutions financières. L'impératif d'avoir des versions stables et le coût de l'erreur (sans parler du processus de contrôle des modifications que vous devez suivre pour sortir un correctif) ne sont pas beaucoup plus élevés que cela. Un produit en boîte serait un changement relaxant pour moi.
Tom Howard
4

Je mettrais en place des emplois distincts pour chaque branche. Je l'ai déjà fait et ce n'est pas difficile à gérer et à configurer si vous avez correctement configuré Hudson / Jenkins. Un moyen rapide de créer plusieurs travaux consiste à copier à partir d'un travail existant qui a des exigences similaires et à les modifier si nécessaire. Je ne sais pas si vous voulez permettre à chaque développeur de configurer ses propres travaux pour ses propres branches, mais ce n'est pas beaucoup de travail pour une seule personne (c'est-à-dire un gestionnaire de build) à gérer. Une fois que les branches personnalisées ont été fusionnées en branches stables, les travaux correspondants peuvent être supprimés lorsqu'ils ne sont plus nécessaires.

Si vous vous inquiétez de la charge sur le serveur CI, vous pouvez configurer des instances distinctes du CI ou même des esclaves séparés pour aider à équilibrer la charge sur plusieurs serveurs. Assurez-vous que le serveur sur lequel vous exécutez Hudson / Jenkins est adéquat. J'ai utilisé Apache Tomcat et je devais simplement m'assurer qu'il disposait de suffisamment de mémoire et de puissance de traitement pour traiter la file d'attente de construction.

Il est important d'être clair sur ce que vous voulez réaliser en utilisant CI, puis de trouver un moyen de l'implémenter sans trop d'efforts manuels ni de duplication. Il n'y a rien de mal à utiliser d'autres outils ou scripts externes exécutés par votre serveur CI qui aident à simplifier votre processus global de gestion de build.

Bernard
la source
Je pense que ce manque d'outils signifie qu'il y a de la place pour certains plugins / produits dans ce département. Je ne voudrais pas écrire le mien.
toomasr
1
Il existe un utilitaire pour Jenkins qui crée automatiquement la configuration de construction pour chaque branche: entagen.github.com/jenkins-build-per-branch
kolen
3

Je choisirais dev + branches stables. Et si vous voulez toujours des branches personnalisées et que vous avez peur de la charge, alors pourquoi ne pas les déplacer vers le cloud et laisser les développeurs les gérer eux-mêmes, par exemple http://cloudbees.com/dev.cb C'est la société où se trouve actuellement Kohsuke . Il existe également un outil Eclipse, donc si vous êtes sur Eclipse, vous l'aurez étroitement intégré directement dans l'environnement de développement.

Anton Safonov
la source
Vais-je échanger le manque d'outils de gestion de plusieurs succursales contre le même problème mais sur le cloud? Je veux dire que je pourrai gérer la charge maintenant mais toujours pas les branches?
toomasr
Je voulais dire oublier les outils et répartir la gestion entre les développeurs - "si vous voulez une version personnelle personnalisée, voici votre compte CB". Sans affecter les performances de construction du serveur principal. Bien que leur API soit assez simple, la création d'utils de gestion serait probablement une question d'une à deux semaines, puis vous y faites ce que vous voulez. Comme d'habitude dans la vie, si vous voulez quelque chose de spécial, vous feriez mieux de le faire vous-même. En même temps, ils se développent rapidement et écoutent la communauté, alors remplissez une demande de fonctionnalité et peut-être qu'elle apparaîtra bientôt.
Anton Safonov le
Oh, compris. Dites au propriétaire de la succursale le choix des emplois qui l'intéressent et configurez-les comme il le souhaite pour sa succursale personnalisée. J'aime cette idée.
toomasr
1

En fait, ce qui est vraiment problématique, c'est de créer une isolation avec des branches de fonctionnalités. Dans notre entreprise, nous avons un ensemble de projets Maven séparés qui font tous partie d'une plus grande distribution. Ces projets sont gérés par différentes équipes, mais pour chaque distribution, tous les projets doivent être publiés. Un featurebranch peut maintenant se chevaucher d'un projet à un autre et c'est à ce moment que l'isolement de la construction devient douloureux. Nous avons essayé plusieurs solutions:

  • créer des référentiels d'instantanés distincts dans nexus pour chaque branche de fonctionnalité
  • partager des référentiels locaux sur des esclaves dédiés
  • utiliser le plugin repository-server-plugin avec les référentiels en amont
  • tout construire dans un seul travail avec un référentiel privé

En fait, la dernière solution est la plus prometteuse. Toutes les autres solutions manquent d'une manière ou d'une autre. Avec le plugin job-dsl, il est facile de configurer une nouvelle branche de fonctionnalités. Copiez et collez simplement le script groovy, adaptez les branches et laissez le job d'amorçage créer les nouveaux jobs. Assurez-vous que le travail d'amorçage supprime les travaux non gérés. Ensuite, vous pouvez facilement évoluer avec des branches de fonctionnalités sur différents projets maven.

Mais comme Tom l'a bien dit ci-dessus, il serait plus agréable de surmonter la nécessité des branches de fonctionnalités et d'apprendre aux développeurs à s'intégrer proprement, mais c'est un processus plus long et le résultat n'est pas clair avec de nombreuses parties du système héritées que vous ne toucherez plus.

mes 2 cents

prosaileur
la source