J'ai été confronté au problème de la mise à l'échelle de CI dans mon entreprise et en même temps à essayer de comprendre quelle approche adopter en matière de CI et de plusieurs succursales. Il y a une question similaire à stackoverflow, Branches à fonctionnalités multiples 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 adopter (ou peut-être quelques autres ???).
Il semble donc que si je veux fournir aux développeurs un CI pour leurs propres branches personnalisées, j'ai besoin d'outils spéciaux pour Jenkins (API ou scripts shell 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 prendriez-vous ou y a-t-il d'autres options?
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 de CI. Oui, vous utilisez un serveur CI, mais vous n'intégrez pas en continu le code de tous vos développeurs.
Réaliser un véritable CI signifie que tous vos développeurs s'engagent régulièrement sur la ligne principale. Facile à dire, mais le plus difficile est de le faire sans casser votre application. Je vous recommande vivement de consulter Livraison continue , en particulier la section Garder votre application disponible dans Chapitre 13: Gestion des composants et des dépendances . Les points principaux sont:
- Masquer les nouvelles fonctionnalités jusqu'à ce qu'elles soient terminées (A.K.A Feature Toggles ).
- Apportez toutes les modifications de manière incrémentielle sous la forme d'une série de petites modifications, chacune pouvant être libérée.
- Utilisez branche par abstraction pour apporter des modifications à grande échelle à la base de code.
- Utilisez des composants pour découpler des parties de votre application qui changent à des rythmes différents.
Ils sont assez explicites sauf branche par abstraction. Ce n'est qu'un terme de fantaisie pour:
- Créez une abstraction sur la partie du système que vous devez modifier.
- Refactorisez le reste du système pour utiliser la couche d'abstraction.
- 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.
- Mettez à jour votre couche d'abstraction pour déléguer à votre nouvelle implémentation.
- Supprimez l'ancienne implémentation.
- Retirez la couche d'abstraction si elle n'est plus appropriée.
Le paragraphe suivant de la section Branches, flux et intégration continue dans Chapitre 14: Contrôle de version avancé résume les impacts.
L'approche incrémentale nécessite certainement plus de discipline et de soins - et en fait plus de créativité - que de créer une succursale et de plonger Gung-ho dans la ré-architecture et le développement de nouvelles fonctionnalités. Mais cela réduit considérablement le risque que vos modifications cassent l'application et vous fera gagner beaucoup de temps à la fusion, à la correction des pannes et à la mise en application de votre application.
Il faut un changement de mental 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é de commettre du code sur la ligne principale et c'est une préoccupation raisonnable. Cela, à son tour, 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 éventuellement du manque de confiance avec vos tests automatisés. Le premier peut être résolu avec une formation et un soutien aux développeurs. Ce dernier est un problème beaucoup plus difficile à résoudre, mais la création de branches n'offre pas de sécurité supplémentaire réelle, elle ne fait que différer le problème jusqu'à ce que les développeurs se sentent suffisamment en confiance avec leur code.
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 ayant des exigences similaires et à les modifier selon les besoins. Je ne sais pas si vous voulez permettre à chaque développeur de configurer ses propres tâches pour ses propres branches, mais cela ne demande pas beaucoup de travail à une seule personne (c'est-à-dire un gestionnaire de build). Une fois les branches personnalisées fusionnées en branches stables, les tâches correspondantes peuvent être supprimées lorsqu'elles ne sont plus nécessaires.
Si vous êtes préoccupé par 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 juste m'assurer qu'il avait suffisamment de mémoire et de puissance de traitement pour traiter la file d'attente de génération.
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'effort manuel ou de duplication. Il n'y a rien de mal à utiliser d'autres outils ou scripts externes exécutés par votre serveur CI qui simplifient votre processus global de gestion de build.
Je choisirais dev + branches stables. Et si vous voulez toujours des branches personnalisées et craignez la charge, alors pourquoi ne pas déplacer ces branches personnalisées 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ù Kohsuke est maintenant. Il existe également un outil Eclipse, donc si vous êtes sur Eclipse, vous l'aurez étroitement intégré dans dev env.
En fait, ce qui est vraiment problématique, c'est de créer un isolement 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 maintenus par différentes équipes mais pour chaque distribution tous les projets doivent être validés. Une branche de fonctionnalités peut maintenant se chevaucher d'un projet à un autre et c'est lorsque l'isolement de la construction devient pénible. Nous avons essayé plusieurs solutions:
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 travail de départ créer les nouveaux emplois. Assurez-vous que le travail de départ 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 dit plus haut, 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