Workflows de livraison continue et modèle de branche par ticket

Faut-il associer création de branches prolifique et livraison continue ? Sur votre SaaS, bien sûr que oui.

Sarah Goff-Dupont Sarah Goff-Dupont

Comme je l'ai expliqué en détail dans « Livraison continue boostée grâce à Git », l'utilisation de branches prolifiques dans votre workflow de livraison continue est une bonne chose. Elle aide à conserver vos branches les plus importantes dans un état propre et livrable, permet aux développeurs d'essayer de nouvelles choses sans empiéter sur les plates-bandes de leurs coéquipiers, et, si elle est bien faite, facilite le suivi des projets.

Depuis plusieurs années, nous utilisons un workflow de branche par ticket, comme beaucoup de nos clients. Et nous avons intégré sa prise en charge dans Jira Software et les outils de développement d'Atlassian pour que ce ne soit pas seulement une bonne pratique, mais aussi une pratique facile. Nous allons donc analyser en détail le modèle de branche par ticket et la manière dont il s'adapte aux trois workflows de livraison continue les plus courants : les produits SaaS, les produits installés ou mobiles, et Gitflow (qui peut fonctionner pour les deux types de produits).

Le workflow de branche par ticket de base

Son nom parle de lui-même : créez une branche de développement pour chaque ticket sur lequel vous travaillez (ou pour chaque changement de code que vous effectuez, qui devrait de toute façon être suivi dans Jira Software). Effectuez ensuite tout le travail d'implémentation et de test sur cette branche. Lorsque vous avez terminé, soumettez une pull request, mergez en amont et livrez chaque fois que vous êtes prêt.

Capture d'écran d'un workflow de base | CI/CD Atlassian

Voici comment le décomposer étape par étape à l'aide des outils d'Atlassian.

Étape 0 : Configurez l'intégration de vos outils

Travaillez avec votre sympathique voisin administrateur Atlassian pour intégrer Jira Software, Bitbucket et Bamboo. Notez que vous pouvez combiner les options Cloud et Server. Par exemple, plusieurs équipes Atlassian utilisent Jira Software Server, Bamboo Server et Bitbucket Cloud. Je recommande aussi vivement Sourcetree à ceux qui préfèrent travailler avec Git via une interface graphique plutôt qu'une ligne de commande. C'est gratuit, donc je ne vois pas de raison de ne pas l'essayer. Une fois que vous l'avez installé, connectez Sourcetree à vos dépôts.

Vous devrez aussi faire d'autres choses évidentes comme créer des tickets pour suivre votre travail, configurer un ou deux dépôts, ainsi que vos builds et vos tâches de déploiement.

Étape 1 : Créez votre branche

Ouvrez le ticket dans Jira Software, assignez-vous ce ticket et définissez-le comme étant en cours pour que votre équipe sache ce qu'il en est. Sur le côté droit se trouve le panneau Development (Développement). Cliquez sur le lien Create branch (Créer une branche) qui s'y trouve. Si plusieurs gestionnaires de dépôts sont connectés, vous verrez un écran vous permettant de choisir celui qui gérera votre branche. Dans le cas contraire, vous passerez directement à l'écran suivant dans lequel vous pourrez configurer la branche.

Capture d'écran d'un workflow de création de branches | CI/CD Atlassian

Notez comment Bitbucket a récupéré la clé du ticket (MKT-15886 dans ce cas) et l'a utilisée dans le nom de la branche. Cela permet de faire toutes sortes de choses magiques, comme envoyer des informations sur le commit, le build, la pull request et le déploiement au panneau Development (Développement). Les clés de ticket déclenchent toutes sortes de liens et d'automatisations astucieuses tout au long de votre workflow de livraison continue. Veillez donc à les inclure dans le nom de vos branches, que vous travailliez par le biais d'une interface utilisateur ou d'une ligne de commande.

Notez également les menus déroulants qui vous permettent de sélectionner un préfixe pour la branche en fonction de son type (correctif, fonctionnalité, version, etc.), et la branche parent ou le tag à partir desquels créer votre nouvelle branche. En supposant que la branche que vous sélectionnez est développée et testée par Bamboo, un indicateur apparaîtra pour signaler si la branche est saine à ce stade. Vous devez absolument surveiller cela ! La dernière chose dont vous avez besoin, c'est d'une nouvelle branche présentant déjà un problème, quel qu'il soit.

Une fois que tout est paramétré comme vous le souhaitez, cliquez sur Create branch (Créer une branche), et Bitbucket se chargera du reste.

Étape 2 : Programmez, testez, répétez

Cette partie vous est probablement familière : vous devez cloner le dépôt localement si ce n'est pas déjà fait, faire un check-out de votre nouvelle branche et commencer à programmer. Le temps que vous fassiez votre premier push vers la nouvelle branche, Bamboo l'a déjà détectée dans votre dépôt et a configuré son intégration continue à l'aide de la fonctionnalité de planification des branches (en supposant que la gestion automatique des branches soit activée). Pour faire simple, Bamboo détecte les nouvelles branches de votre dépôt et leur applique les builds que vous avez configurés pour la branche principale.

Je recommande également d'activer le merge automatique via Bamboo. Au début de chaque build, Bamboo peut faire un check-out de deux branches, les merger, puis exécuter le build sur le code mergé. Ainsi, pour cette étape du workflow de livraison continue, vous mergez les changements provenant de la branche principale vers votre branche de fonctionnalité. De cette façon, votre branche ne s'éloignera pas trop de la principale et vous obtiendrez un feedback rapide pour savoir si vos changements sont compatibles avec ceux effectuées sur la principale.

Capture d'écran d'une mise à jour de branche | CI/CD Atlassian

Si vous n'êtes pas fan du merge automatique, mergez la branche principale dans la vôtre (ou rebasez-la) et lancez un build pour vous assurer qu'il n'y a pas de mauvaises surprises (ou corrigez-les le cas échéant). Une fois l'implémentation terminée et tous vos tests réussis, vous êtes prêt pour l'étape suivante.

Étape 3 : Mergez en amont

En tant que membres responsables de nos équipes, nous ne nous précipitons pas et ne réalisons jamais de merge sur la branche principale (ou toute autre branche stratégique) sans faire de pull request, la seule forme de revue de code qui soit recevable dans tout l'univers.

Vous pouvez créer des pull requests à partir de la ligne de commande ou en utilisant Sourcetree, mais il y a certains avantages à passer par l'interface utilisateur de Bitbucket. Tout d'abord, vous avez la possibilité de comparer votre branche à la branche cible. Cette comparaison révèle souvent une ou deux choses que vous voudrez corriger immédiatement. Ensuite, à partir de l'écran de comparaison des branches, il vous suffit d'appuyer sur le bouton Create pull request (Créer une pull request), de choisir vos réviseurs et c'est parti.

Capture d'écran d'une pull request des workflows Bitbucket | CI/CD Atlassian

Bitbucket est (en toute honnêteté) plutôt performant en matière de pull requests. En plus des options habituelles comme les différenciations côte à côte et les commentaires contextuels, vous pouvez également définir des règles. Certaines équipes de développement d'Atlassian définissent une règle selon laquelle les pull requests ne peuvent être mergées que lorsque deux personnes au minimum les ont approuvées. D'autres équipes désignent une sorte de contrôleur : des autorisations relatives à la branche cible sont définies, de manière à ce que seul le contrôleur puisse effectuer des merges. D'autre part, toutes les équipes devraient activer la règle empêchant de merger une pull request en cas de builds défaillants sur cette branche.

Conseil de pro : pour la branche principale et celle à partir de laquelle vous effectuez la livraison, vous voudrez certainement faire un build immédiatement après chaque push. Configurez un déclencheur de build automatique pour ces éléments dans Bamboo avec un calendrier de poll agressif ou une notification Push depuis Bitbucket.

Étape 4 : à présent, livrez vos produits (pour de bon) !

(Y a-t-il d'autres fans de développement dans le coin ? « Quand de nouvelles lignes de code arrivent, vous devez les livrer. » Non ? OK... on dirait que je ne vais pas quitter mon travail tout de suite.)

Capture d'écran d'un déploiement de build grâce aux workflows Bamboo | CI/CD Atlassian

Une fois que le build est fonctionnel sur votre branche de version, vous êtes potentiellement prêt à livrer. Je dis « potentiellement » parce que c'est votre équipe qui décide si la livraison doit ou non avoir lieu. (Est-ce qu'elle répond à tous les critères d'acceptation ? Les artefacts ont-ils été suffisamment malmenés par les tests de charge ?)

Vous pouvez certainement utiliser Bamboo pour déployer automatiquement le build en staging ou directement en production si vous êtes dans une logique de déploiement continu. Mais cela ne convient pas à toutes les équipes et à tous les produits, comme nous allons le voir.

Dans les prochaines sections, je vais reprendre les étapes 1 à 4 et indiquer en quoi elles diffèrent de ce qui est décrit dans le workflow de branche par ticket de base, le cas échéant.

Workflow de livraison continue pour les produits SaaS

En ce qui concerne les branches avec lesquelles vous travaillez et la façon dont le code se déplace entre elles, le workflow SaaS est identique au workflow de base.

Capture d'écran d'un workflow SaaS | CI/CD Atlassian

Étape 1 : Créez votre branche

La seule chose à noter ici est que les équipes SaaS créent généralement leurs branches de fonctionnalités à partir de la branche principale.

Étape 2 : Programmez, testez, répétez

Les équipes SaaS souhaitent souvent s'approcher le plus possible du déploiement continu et elles ont le luxe de travailler sur un produit bien adapté pour cela. Pour que cela soit viable, vous devrez automatiser les déploiements vers un environnement de test ou de staging dans le cadre de cette étape, au lieu d'attendre après l'étape de pull request.

Heureusement, grâce à des technologies telles que Puppet, Chef, Docker et Vagrant, il est de plus en plus facile et rapide de mettre en place et de démanteler des environnements légers. (J'aurais aimé faire une analyse approfondie de la question, mais ce sera l'objet d'un autre article, un autre jour...) Et Bamboo prend en charge les déploiements automatisés à partir de n'importe quelle branche. Ainsi, que vous travailliez avec des environnements temporaires ou permanents, vous pouvez le configurer pour déployer chaque build réussi de votre branche dans un environnement où il pourra subir une batterie de tests automatisés d'interface utilisateur et/ou de charge.

Supposons que vous ayez déjà créé un projet de déploiement dans Bambo associé à ce plan de build. Récupérez (ou créez) les configurations de Bamboo pour l'environnement que vous souhaitez déployer, puis créez un déclencheur qui déploiera automatiquement chaque build de branche réussi.

Capture d'écran d'un environnement de test | CI/CD Atlassian

Même si votre équipe ne rêve pas de déploiement continu et préfère prendre elle-même la décision de livrer, déployer des builds de branche concluants dans un environnement est une idée judicieuse. Cette action donne à votre équipe l'occasion d'exécuter un certain nombre de tests exploratoires avant de réaliser un merge en amont.

Étape 3 : Mergez en amont

Le nombre d'environnements de pré-production utilisés par votre équipe influencera le moment exact auquel vous passez à cette étape. En général, les développeurs exécutent des tests en cours de processus sur leur branche à chaque build et, si ces tests sont concluants, ils les déploient dans un environnement de test pour des tests d'interface utilisateur, de charge et/ou exploratoires. Une fois que tout est en ordre dans le test, ils créent la pull request et mergent en amont vers la branche à partir de laquelle vous livrez la version (encore une fois, il s'agit généralement de la principale).

Étape 4 : Effectuez la livraison

À ce stade, la boucle est bouclée : vous avez mergé en amont vers la branche principale et vérifié que les tests avaient réussi. C'est également à ce stade que nous observons de nombreuses variations dans l'approche des différentes équipes.

Certaines équipes déclenchent un déploiement automatique après chaque build réussi de la principale (dans ce cas, les flags de fonctionnalités sont essentiels), d'autres attendent qu'une masse critique de changements se trouve sur la branche principale avant d'étiqueter une version et de déclencher un déploiement. De même, certaines équipes déploient directement en production, d'autres transfèrent le build dans un environnement de staging pour une dernière série de tests de contrôle avant de le mettre en service.

Il n'y a pas de « meilleure » façon magique de transférer le code de la branche principale vers les clients. Tant que vous automatisez autant que possible, vous êtes sur la bonne voie.

Workflow de livraison continue pour les produits installés

La principale différence avec le workflow de branche par ticket de base est l'existence de branches au long cours pour héberger chaque version que vous prenez en charge. Pour les produits B2B d'entreprise comme ceux d'Atlassian, il existe probablement une demi-douzaine de ces branches (ou plus). Pour les apps mobiles, il peut y en avoir seulement deux ou trois (voire moins).

Capture d'écran de plusieurs versions d'un workflow | CI/CD Atlassian

Étape 1 : Créez votre branche

L'endroit à partir duquel vous créez une branche dépendra du type de changement que vous apporterez. Devez-vous corriger un bug sur la version que vous avez livrée la semaine dernière ? Ou bien devez-vous créer une nouvelle fonctionnalité pour la prochaine version ?

Dans ce dernier cas, vous créerez une branche à partir de la principale. Dans le premier cas, vous baserez votre branche sur celle de la version la plus ancienne à laquelle le changement est destiné (c'est-à-dire la première version dans laquelle le bug est apparu).

Étape 2 : Programmez, testez, répétez

Comme avec les produits SaaS, il est judicieux de déployer des builds concluants depuis votre branche dans un environnement de test lorsque tous les tests en cours de fabrication ont été réalisés. Mais les raisons associées à cet intérêt sont un peu différentes.

Mettre à jour une version avec des corrections de bug est beaucoup plus difficile avec les produits installés qu'avec les produits SaaS, que ce soit pour votre équipe ou pour vos clients. En d'autres termes, les enjeux sont plus importants lorsqu'il s'agit de découvrir des bugs.

Ainsi, dans ce workflow, le déploiement vers un environnement de test pour les tests d'interface utilisateur, de charge et/ou exploratoires doit être considéré comme « vraiment pas facultatif ». D'ailleurs, je dirais que les tests exploratoires ne sont pas facultatifs non plus, compte tenu des enjeux. Mais je m'égare...

Étape 3 : réalisez un merge en amont (et/ou en aval)

C'est là que les choses deviennent intéressantes.

Si vous travaillez sur un élément destiné à une version à venir, vous faites une pull request et vous mergez votre branche vers la principale, comme dans le workflow de base. Mais si vous avez basé votre branche sur une branche de version stable, vous mergerez d'abord vers celle-ci et vous vous assurerez que tous vos tests réussissent. Ensuite, vous devrez revenir aux versions plus anciennes qui ont besoin de la même mise à jour, en testant chacune d'entre elles en cours de route. Enfin, vous mergerez vers la branche principale pour que toutes les versions futures comportent le même changement.

Capture d'écran de plusieurs versions d'un workflow | CI/CD Atlassian

Vos outils Atlassian peuvent vous aider de plusieurs façons. Tout d'abord, vous pouvez faire en sorte que Bitbucket réalise automatiquement en cascade vos merges en aval sur les branches de version stables. Assurez-vous que chaque branche est configurée pour faire un build automatique à chaque fois qu'elle reçoit une nouvelle ligne de code.

Vous pouvez également profiter du merge automatique de Bamboo (décrit ci-dessus) pour déplacer les changements entre les branches de version stables. Dans ce cas, vous devez par contre utiliser l'option Gatekeeper.

Capture d'écran de Gatekeeper | CI/CD Atlassian

Par exemple, disons que vous avez mergé une correction de bug dans la branche pour la v1.2. Allez dans les configurations de cette branche du plan et configurez-la pour qu'elle soit automatiquement mergée pour la v1.1, et ainsi de suite.

Étape 3.5 : Créez une branche de version stable

Naturellement, si vous travaillez sur des nouveautés pour la prochaine version, vous créerez une branche de version stable lorsque vous disposerez d'une masse critique de fonctionnalités qui seront prêtes. (prête = implémentée, testée, validée, etc.) Il s'agit généralement d'une copie de la branche principale et, comme celle-ci, elle est configurée pour être buildée et testée automatiquement à chaque fois que des changements y sont apportés.

Si (c'est-à-dire : quand) vous découvrez que d'autres changements sont nécessaires avant de livrer la version, éliminez ces branches de fonctionnalités de la branche de version stable. Une fois les changements prêts, mergez-les dans la branche de version stable et effectuez les tests à ce moment-là. En supposant que tout se passe bien, répercutez votre changement jusqu'à la branche principale, comme dans le schéma ci-dessus.

C'est à vous de décider si votre équipe doit utiliser des pull requests pour les merges en cascade. Il s'agit d'une bonne mesure de sécurité, mais les pull requests et les fonctionnalités de merge automatique offertes par Bitbucket et Bamboo ne font pas bon ménage. Il faut donc peser le pour et le contre de l'automatisation par rapport à des revues de code supplémentaires.

Étape 4 : Effectuez la livraison

Une fois que vos tests en cours de réalisation réussissent sur la branche de version stable, le moment est venu de procéder au déploiement. L'emplacement du déploiement dépend de vous et de votre équipe. La plupart des équipes commencent par déployer leur version dans un environnement de staging, mais d'autres sont suffisamment confiantes dans les tests effectués jusqu'à ce stade pour livrer directement en production.

Livraison continue, la méthode Gitflow

Au lieu d'une seule branche principale, cette approche utilise deux branches pour suivre l'historique du projet. Alors que la branche principale contient des tags et/ou des commits qui enregistrent l'historique officiel de la version du projet, une branche d'intégration partagée (généralement appelée « développement ») donne à votre équipe un espace pour repérer les bugs et les changements incompatibles.

Capture d'écran de Gitflow | CI/CD Atlassian

Étape 1 : Créez votre branche

Là encore, la différence avec le workflow de base réside simplement dans le point de départ de la branche. Pour les nouvelles tâches de développement, votre branche de fonctionnalité sera basée sur la branche « développement » (assurez-vous de choisir un commit propre à partir duquel la créer !). Les corrections de bugs sur une version que vous avez déjà livrée seront basées sur une branche de version stable (non représentée ci-dessus, mais vous voyez l'idée). Pour en savoir plus sur les variations de Gitflow et leurs structures de branches, consultez notre tutoriel. Bitbucket prend en charge toutes les variations, ainsi que les autorisations de branche qui vous donnent la possibilité de contrôler l'accès aux branches principales ou de version.

Quel que soit le point d'origine de votre branche, utilisez la fonctionnalité de mise à jour des branches de Bamboo (mentionnée ci-dessus) pour faire le pull des changements de la branche d'origine vers votre branche de fonctionnalité à chaque build. Vous découvrirez immédiatement les problèmes d'intégration et serez en mesure de les corriger sur votre branche de fonctionnalité au lieu de les découvrir seulement après avoir mergé vers la branche de développement. À ce stade, vous l'avez déjà polluée.

Avec le modèle Gitflow, il est possible de livrer une version à partir de la branche principale ou des branches de version stables. Nous vous recommandons de faire de votre version la branche principale pour vos builds Bamboo (cela sera important au moment du déploiement) et d'activer les branches de plan afin que toutes les branches soient testées de manière approfondie.

Étape 2 : Programmez, testez, répétez

L'étape de test devient intéressante avec Gitflow. Utilisez les branches de plan dans Bamboo pour soumettre votre branche de fonctionnalité à des tests (comme dans tous les workflows de livraison continue). La différence est que, lorsque l'implémentation est terminée et que tous vos tests réussissent, vous devez merger vers la branche de développement au lieu de la principale.

La branche develop est une sorte de marmite dans laquelle mijotent tous les changements apportés par votre équipe ; or, vous avez besoin d'un feedback pour chaque commit afin de faciliter le débogage en cas d'échec aux tests (réduction du nombre de changements à trier entre chaque build). La meilleure façon d'y parvenir est de configurer la branche develop de manière à déclencher les builds en fonction des notifications push de Bitbucket. Interroger régulièrement le dépôt permettra parfois de détecter des changements issus de commits multiples dans un seul build, compte tenu du nombre élevé de changements que reçoit la branche develop. (La méthode convient mieux aux branches pour lesquelles les changements sont plus espacés.)

Capture d'écran d'un type de déclencheur | CI/CD Atlassian

Conseil de pro : un autre avantage des builds déclenchés par le dépôt pour le développement est qu'ils utilisent efficacement le processeur de Bamboo, comme je l'ai mentionné dans Dépôts Git compatibles avec la CI. Pour les équipes qui effectuent des livraisons continues à grande échelle, cela fait vraiment la différence.

Comme pour le workflow de base, assurez-vous de merger la branche de développement dans votre branche de fonctionnalité (ou rebasez-la) et d'exécuter les tests une dernière fois avant de passer à la branche de développement.

Étape 3 : Mergez en amont

La création d'une pull request lors du merge de votre branche de fonctionnalité vers la branche de développement est une pratique standard. Il est beaucoup plus facile d'effectuer des revues de code par les pairs à ce stade que de les repousser jusqu'à ce que vous soyez prêt à livrer, auquel cas vous devriez revoir tous les changements depuis la dernière version en une seule fois. Non, merci.

Inévitablement, vous mergerez votre branche de fonctionnalité vers la branche de développement et vous vous heurterez alors à des échecs de tests. Au lieu d'apporter des changements directement dans la branche de développement, faites un nouveau check-out de votre branche et effectuez le travail à ce niveau. (La plupart des équipes chez Atlassian ont des accords tacites pour ne jamais faire de commits directement sur la branche principale, seulement des commits de merge.)

Étape 4 : Effectuez la livraison

En désignant votre branche de version comme la branche principale de votre plan de build dans Bamboo, vous vous assurez que vos projets de déploiement seront assez simples. Quelle que soit la branche principale du plan de build, elle sera automatiquement la branche principale de vos tâches de déploiement, bien que vous puissiez configurer le projet de déploiement pour déployer les builds à partir des branches de fonctionnalités également.

Comme pour le workflow SaaS, vous pouvez créer automatiquement des tags sur la branche principale en fonction de chaque build de développement réussi et déployer immédiatement à partir de ces tags. Vous pouvez aussi attendre que plusieurs fonctionnalités aient été ajoutées à la branche de développement et créer le tag manuellement. Cela dépend simplement de si vous passez au déploiement continu ou souhaitez poursuivre avec la livraison continue. Gitflow accepte les deux approches.

Ouf ! Quatre workflows, cinq schémas et environ 3 200 mots plus tard, nous y voilà. (Si vous êtes toujours en train de lire ces lignes, félicitations !)

Espérons que cela vous a permis de comprendre comment Jira Software, Bitbucket et Bamboo interagissent pour prendre en charge le modèle de branche par ticket dans la livraison continue. Si ce n'est pas le cas, écrivez-moi un tweet et dites-moi comment je peux améliorer ce billet, c'est important.

Nous avons ainsi pu constater l'intérêt de créer une branche pour chaque ticket sur lequel vous travaillez. Vous ne marcherez pas sur les plates-bandes de vos coéquipiers, et vos branches les plus importantes resteront propres et livrables à tout moment. Alors, dites-le avec moi :

Créer des branches qui déchirent à l'extérieur de votre workflow : « Good Thing™ ».

Faites des branches !