Technologies DevOps : l'intégration continue

Les systèmes logiciels sont complexes. Ainsi, une modification apparemment simple et autonome d'un seul fichier peut avoir des effets secondaires indésirables sur l'ensemble du système. Lorsqu'un grand nombre de développeurs travaillent sur des systèmes associés, il peut s'avérer difficile de coordonner les mises à jour de code et d'assurer la compatibilité des modifications apportées par différents développeurs.

Nous avons créé l'intégration continue (CI) pour résoudre ces problèmes. La CI part du principe qu'une opération à laquelle vous consacrez beaucoup de temps et d'énergie doit être effectuée plus souvent, ce qui vous oblige à la rendre moins fastidieuse. En créant des boucles de rétroaction rapides et en veillant à ce que les développeurs travaillent par petits lots, la CI permet aux équipes de concevoir des logiciels de haute qualité, de réduire sans cesse les coûts de développement et de maintenance des logiciels, tout en améliorant leur productivité.

Mettre en œuvre la CI

Lorsque votre organisation utilise la CI, les développeurs intègrent régulièrement l'ensemble de leurs travaux à la version principale du code base (également appelée branche principale, branche maître ou trunk). Les recherches menées sur les données DORA (DevOps Research and Assessment) (PDF) montrent que les équipes sont plus performantes lorsque les développeurs fusionnent leur travail avec la branche principale au moins une fois par jour. Un ensemble de tests automatisés est exécuté avant et après la fusion afin de vérifier que les modifications n'introduisent pas de bugs de régression. Si ces tests automatisés échouent, l'équipe arrête ce qu'elle est en train de faire afin de résoudre immédiatement le problème.

La CI permet de garantir le bon fonctionnement du logiciel et de s'assurer que les branches des développeurs ne divergent pas de manière significative de la branche principale. La CI offre des avantages considérables : les recherches (PDF) montrent qu'elle génère une fréquence de déploiement plus élevée, des systèmes plus stables et des logiciels de meilleure qualité.

Voici les principaux éléments permettant de réussir la mise en œuvre de l'intégration continue :

  • Chaque commit doit déclencher un build du logiciel.
  • Chaque commit doit déclencher un ensemble de tests automatisés permettant d'obtenir des retours en quelques minutes.

Pour les mettre en œuvre, vous avez besoin des éléments suivants :

  • Un processus de compilation automatisé. La première étape de la CI consiste à créer des packages pouvant être déployés dans n'importe quel environnement à l'aide d'un script automatisé. Les packages créés par le build CI doivent faire autorité et être utilisés dans tous les processus en aval. Ces builds doivent être numérotés et reproductibles. Vous devez exécuter et mener à bien le processus de compilation au moins une fois par jour.
  • Une suite de tests automatisés. Si vous n'en avez pas, commencez par écrire quelques tests unitaires et tests de validation (PDF) couvrant les principales fonctionnalités de votre système. Assurez-vous que les tests sont fiables. Ainsi, lorsqu'ils échouent, vous savez que votre système a une défaillance. Sinon, vous êtes certain qu'il ne présente aucun risque. Vérifiez ensuite que toutes les nouvelles fonctionnalités font l'objet de tests. Ces tests doivent être exécutés rapidement pour que les développeurs puissent prendre connaissance des retours dès que possible. Ils doivent être effectués correctement au moins une fois par jour. À terme, si vous disposez de tests de performances et de validation, les développeurs peuvent recevoir des retours chaque jour.
  • Un système CI exécutant le build et les tests automatisés à chaque enregistrement. Le système doit également permettre à l'équipe de consulter l'état. Amusez-vous à le faire. Vous pouvez, par exemple, indiquer que le build est défectueux à l'aide de klaxons ou de feux tricolores. En revanche, n'envoyez pas de notifications par e-mail : beaucoup de personnes les ignorent ou créent un filtre pour les masquer. L'envoi de notifications dans un système de chat est un moyen plus efficace et plus répandu d'y parvenir.

L'intégration continue, telle que définie par Kent Beck et la communauté d'Extreme Programming à l'origine du terme, inclut également deux autres pratiques permettant de prédire des performances plus élevées en matière de livraison de logiciel :

  • Le développement à branche unique permettant aux développeurs de travailler par petits lots en dehors de la branche principale/trunk. Ils fusionnent leur travail avec une branche trunk/principale au moins une fois par jour, au lieu de travailler sur des branches de fonctionnalités de longue durée.
  • Un accord selon lequel la réparation du build doit prévaloir sur toute autre tâche en cas de défaillance.

La CI nécessite des tests unitaires automatisés. Ces tests doivent être suffisamment complets pour vous assurer que le logiciel fonctionne comme prévu. Leur exécution ne doit pas prendre plus de quelques minutes. Sinon, les développeurs ne voudront pas les exécuter de manière régulière. Si les tests sont rarement exécutés, ils peuvent échouer en raison des nombreuses modifications apportées, ce qui rend le débogage difficile. Les tests rarement exécutés sont difficiles à gérer.

La création de suites de tests unitaires automatisés faciles à gérer est complexe. L'approche de développement piloté par les tests (TDD) est un bon moyen d'aborder ce problème. Cela permet aux développeurs d'écrire des tests automatisés qui échouent initialement avant d'ajouter le code permettant de les réussir. Cette approche présente plusieurs avantages. Les développeurs peuvent par exemple écrire un code modulaire facile à tester, ce qui réduit les coûts de maintenance des suites de tests automatisés obtenues. Beaucoup d'entreprises ne disposent pas de suites de tests unitaires automatisés et, malgré cela, ne mettent toujours pas en application le TDD.

Objections à la CI

Comme décrit précédemment, la CI est parfois considérée comme une pratique controversée. La CI exige de vos développeurs qu'ils décomposent les fonctionnalités importantes et d'autres modifications en étapes incrémentielles plus petites pouvant être intégrées régulièrement à la branche principale. C'est un changement pour les développeurs qui n'ont pas l'habitude de travailler de cette manière. En outre, lorsque les équipes optent pour de petites étapes, la mise au point des fonctionnalités importantes peut prendre plus de temps. Néanmoins, en règle générale, vous ne souhaitez pas optimiser la vitesse à laquelle les développeurs peuvent déclarer une fonctionnalité importante comme terminée sur une branche. Vous souhaitez plutôt que les modifications soient examinées, intégrées, testées et déployées aussi vite que possible. Ce processus aboutit à un développement et à une livraison de logiciels plus rapides et plus stables (PDF) lorsque vous apportez de petites modifications autonomes, et que les branches sur lesquelles elles reposent sont de courte durée. Travailler par petits lots permet également aux développeurs de recevoir des retours réguliers sur l'impact de leur travail sur le système dans son ensemble (autres développeurs, testeurs et clients), ainsi que sur des tests automatisés de performances et de sécurité. Cela facilite et accélère la détection, le tri et la résolution des problèmes.

Malgré ces objections, toute organisation souhaitant se lancer dans la livraison continue doit mettre un point d'honneur à aider les équipes de développement de logiciels à la mettre en œuvre.

Problèmes les plus courants

Voici quelques problèmes courants qui empêchent l'adoption de la CI à grande échelle :

  • Ne pas tout mettre dans le dépôt de code. Tous les éléments nécessaires à la création et à la configuration de l'application et du système doivent se trouver dans votre dépôt. Même si cela peut sembler sortir du champ de la CI, il s'agit d'un principe fondamental.
  • Ne pas automatiser le processus de compilation. Les étapes manuelles peuvent entraîner des erreurs et un manque de documentation des étapes.
  • Ne pas déclencher de tests rapides à chaque modification. Vous devez effectuer des tests complets de bout en bout, mais également des tests rapides (généralement des tests unitaires) pour accélérer les retours faits aux développeurs.
  • Ne pas corriger les builds défectueux immédiatement. L'un des objectifs principaux de la CI consiste à disposer d'une version stable à partir de laquelle tout le monde peut développer. Si vous ne parvenez pas à corriger le build en quelques minutes, vous devez identifier et rétablir la modification à l'origine de la défaillance.
  • Exécuter des tests bien trop longs. L'exécution des tests ne doit pas prendre plus de quelques minutes, avec une limite maximale de 10 minutes selon les recherches menées sur les données DORA (PDF). Si l'exécution du build prend plus de temps, vous devez améliorer l'efficacité des tests, ajouter davantage de ressources de calcul afin de pouvoir les exécuter en parallèle, ou répartir les tests plus longs dans un build distinct à l'aide du modèle de pipeline de déploiement.
  • Ne pas fusionner assez régulièrement les éléments avec la branche principale. Beaucoup d'entreprises ont automatisé des tests et des builds, mais n'imposent pas une fusion quotidienne avec la branche principale. Les développeurs doivent donc faire face à des branches de longue durée beaucoup plus difficiles à intégrer et à de longues boucles de rétroaction.

Méthodes pour évaluer la CI

Les concepts de CI abordés précédemment présentent des moyens d'évaluer l'efficacité de la CI dans vos systèmes et dans votre environnement de développement, comme indiqué dans le tableau suivant. La collecte de ces métriques vous permet d'optimiser vos processus et vos outils. Vos développeurs peuvent ainsi appliquer de meilleures pratiques en matière de CI, tout en bénéficiant de boucles de rétroaction plus courtes.

Facteur à tester Données à évaluer
Les commits de code déclenchent un build du logiciel. Pourcentage de commits de code qui génèrent un build de logiciel sans intervention manuelle.
Les commits de code déclenchent une série de tests automatisés. Pourcentage de commits de code qui génèrent l'exécution d'une suite de tests automatisés sans intervention manuelle.
Les builds et les tests automatisés sont bien exécutés chaque jour. Pourcentage de builds et de tests automatisés exécutés chaque jour.
Les builds actuels sont mis à la disposition des testeurs à des fins de tests exploratoires. Disponibilité des builds pour les testeurs, ou à l'inverse, indisponibilité des builds pour ces derniers.
Les développeurs reçoivent chaque jour des retours à partir des tests de validation et de performances. Disponibilité des retours pour les développeurs à partir des tests de validation et de performances, à savoir le pourcentage de tests permettant de fournir des retours aux développeurs au cours d'une journée.
Les builds défectueux sont immédiatement corrigés. Délai entre l'interruption du build et sa correction, soit en procédant à l'enregistrement permettant de résoudre le problème, soit en annulant la modification destructive.

Étapes suivantes