Continuous Integration : définition de l’intégration continue

Les développeurs connaissent bien les problèmes de l’intégration : un nouveau code a été écrit et le plus gros du travail est maintenant fait. Il s’agit à présent d’intégrer le code source dans le projet global et c’est à ce moment que les problèmes surviennent. Afin d’éviter qu’une catastrophe se produise au terme de la longue phase de développement, de nombreuses équipes optent pour la continuous integration (l’intégration continue) : les modifications sont ainsi intégrées directement dans le projet au jour le jour et, dans le meilleur des cas, plusieurs fois par jour.

Tout comme la continuous delivery, l’intégration continue est avant tout privilégiée dans un environnement de développement logiciel agile. L’objectif de cette approche moderne est de progresser par étapes afin de concevoir le processus de développement plus efficacement et de pouvoir réagir aux modifications avec flexibilité. L’intégration continue a été évoquée pour la toute première fois dans la description de la méthode agile de l’Extreme Programming de Kent Beck. Mais a priori, l’idée d’une intégration continue serait antérieure. Elle intervient par exemple déjà dans la méthode Booch.

Qu’est-ce que la continuous integration ?

L’intégration continue nous fournit une bonne solution lorsque l’entreprise travaille sur un vaste projet ou un client souhaite avoir un logiciel à la fois complet et complexe. Différentes équipes travaillent à la conception de pans de l’application et les développeurs se chargent de programmer les différentes fonctionnalités. Après un travail de plusieurs mois voire de plusieurs années, l’intégralité du travail doit être regroupée et c’est alors que les problèmes surviennent. Dans un tel cas, la détection et la correction des erreurs, le regroupement de tous les fragments de code peut prendre plusieurs mois pour finalement se rapprocher de la phase de test finale et du déploiement.

Dans le cadre de la continuous integration, l’intégration du nouveau code est effectuée de façon bien plus précoce et pas uniquement lorsque toutes les parties prenantes ont terminé leur sous-domaine. Au lieu de cela, les développeurs intègrent leur code terminé une ou plusieurs fois par jour dans la mainline, le code source qui est accessible par tous les programmeurs. Étant donné qu’il s’agit toujours dans ce cas de sections de code relativement courtes, l’intégration est elle aussi plutôt rapide. Seules quelques minutes sont nécessaires à un développeur pour mettre le résultat de son travail à disposition du reste de l’équipe. Si l’on découvre alors une erreur, elle peut être immédiatement localisée et, dans le meilleur des cas, corrigée rapidement.

Définition

La continuous integration (en français « intégration continue ») est une technique de développement de logiciel agile. Pour ce type d’intégration, les développeurs intègrent les fragments de code terminés régulièrement, parfois plusieurs fois par jour, dans l’application au lieu de les intégrer tous en même temps à la fin du projet.

Manière de procéder

En pratique, l’intégration continue se déroule généralement de la façon suivante : un développeur a pour tâche de créer une fonctionnalité. Avant de s’atteler au travail de programmation, il télécharge la version actuelle du code complet de l’application, qu’on appelle mainline. Il peut travailler dans cette version qui se trouve à présent sur son ordinateur personnel (également appelée working copy). Lorsqu’il a terminé sa tâche, il teste le programme, corrige les erreurs éventuelles et peut à présent publier la nouvelle version dans la mainline.

Le développeur n’est toutefois pas seul à travailler sur le programme. Alors qu’il procédait à ses modifications, ses collègues ont très certainement effectué d’autres tâches et chaque développeur de l’équipe dispose ainsi d’une version différente sur son ordinateur. Par ailleurs, des modifications ont pu être apportées à la version de la mainline depuis son téléchargement et le programmeur doit donc tout d’abord les intégrer dans sa copie de travail (working copy). Si une erreur se produit, à lui de la corriger. Une fois ce travail réalisé, le programmeur peut alors insérer ses modifications dans la mainline. Il teste une nouvelle fois le programme. Lorsqu’aucune erreur ne se produit lors du test (une erreur pouvant par exemple survenir s’il n’a pas actualisé correctement sa copie de travail), le processus est effectivement terminé et le développeur peut se consacrer à sa tâche suivante.

Comportements

Plusieurs règles doivent être observées lorsque l’on travaille de cette façon : en procédant de la sorte, les programmeurs se basent généralement sur les principes élaborés à l’époque par Martin Fowler (lui-même développeur de logiciel) pour réussir une intégration continue. Ces principes visent tout d’abord à garantir que toutes les parties prenantes se trouvent au même niveau et que personne n’entraîne de catastrophe en adoptant une approche différente.

Une seule et même source

Même si cela semble évident, il s’agit d’un des principaux facteurs : tous les membres de l’équipe doivent utiliser la même source (le même dépôt ou repository) lorsqu’ils travaillent sur le code. Cela ne s’applique pas uniquement au code source à proprement parler. En effet, d’autres éléments, comme des bases de données, sont nécessaires pour garantir une application viable. Ces bases de données doivent également être regroupées en un même endroit. C’est pourquoi Martin Fowler recommande de mettre en place un dépôt, de telle sorte que même un développeur s’équipant d’un ordinateur de travail entièrement neuf puisse travailler et trouver l’ensemble des fichiers nécessaires de façon centralisée à un seul et même endroit.

Conseil

Pour que la gestion d’une telle source fonctionne efficacement, il est pertinent d’utiliser un système de gestion de versions. Dans le cas d’un nombre important de collaborateurs, il est nettement plus simple de garder une vue d’ensemble avec un logiciel adapté.

Builds automatisés

Afin de concevoir un programme viable à partir du code source, les développeurs doivent le compiler, actualiser les bases de données et déplacer les fichiers au bon endroit. Ce processus peut être automatisé. Dans l’idéal, il faudrait pouvoir exécuter un processus de build à l’aide d’une seule commande.

Système avec test automatique

En intégrant des mécanismes de test dans le processus de build, l’équipe profite d’une plus grande automatisation et ainsi d’une accélération de l’intégration continue. Tout comme le processus de build à proprement parler, les tests peuvent être exécutés avec un minimum d’effort (pour bien faire, on peut implémenter tout un groupe de différents mécanismes de test).

Note

La méthode agile dite « Test Driven Development » (TDD) accorde une grande importance aux tests. D’après Martin Fowler, il n’est pas nécessaire de mettre en œuvre l’intégralité du TDD pour utiliser l’intégration continue.

Intégration quotidienne

L’intégration continue peut uniquement fonctionner lorsque tous les membres de l’équipe contribuent au système. Lorsqu’un collègue publie un code non définitif dans la mainline, les autres partent sur des bases erronées. Tous acceptent de travailler à un système stable, mais si quelqu’un retient le code pendant une trop longue période (plus d’un jour), la recherche d’erreurs qui s’ensuit peut devenir un problème. Comme souvent, la communication est un facteur essentiel dans l’intégration continue, mais lorsque les développeurs se tiennent régulièrement informés, les petites difficultés peuvent être rapidement surmontées.

Mainline opérationnelle

Le code de programme que l’on trouve dans la mainline doit toujours être testé et opérationnel. C’est pourquoi chaque développeur peut intégrer son code uniquement dans cette branche principale et non dans une branche secondaire personnelle. Ce faisant, chaque développeur doit par ailleurs veiller à ce que sa contribution personnelle soit opérationnelle. Après l’intégration, il doit également tester le code et le build. Si une erreur se produit, il doit la corriger. Ceci permet de garantir un code toujours exempt d’erreurs.

Réparation immédiate

En cas d’intégration continue, il est capital que la mainline ne comporte pas de version erronée. Pour les développeurs, cela implique que les corrections ne peuvent pas être reportées. D’après Martin Fowler, le fait que des builds ne fonctionnent pas et que le code doive être retravaillé ne constitue pas un problème en soi, mais le système d’intégration continue exige que la correction soit effectuée immédiatement. En effet, l’ensemble des développeurs doivent pouvoir compter sur un code fonctionnel dans la Mainline. Si tel n’est pas le cas, toute l’équipe travaille dans des systèmes instables, ce qui déclenche une avalanche d’erreurs.

Une courte période d’intégration

L’intégration effective du code (y compris la phase de test) doit être effectuée aussi rapidement que possible. L’« extreme programming » (XP) prévoit 10 minutes seulement pour l’intégration. Étant donné que, dans certaines circonstances, un développeur est amené à intégrer le code plusieurs fois par jour, les délais de build entraînent des pertes de temps considérables. Il est par conséquent nécessaire de mettre en place des mécanismes accélérant le processus. Afin d’atteindre une telle rapidité, il faut également accepter de ne pas effectuer directement chaque test possible et imaginable. On choisit plutôt d’implémenter un système en deux étapes : lors de la première phase, qui survient au cours du travail quotidien, les tests sont effectués de telle sorte que l’on puisse atteindre des délais de build courts. La seconde phase de test dure en revanche plusieurs heures et comprend également des vérifications plus approfondies.

Environnement de test copié

Il est en principe pertinent d’effectuer des tests dans un environnement délocalisé et sécurisé. Il convient toutefois de veiller dans ce cadre à ce que les tests soient configurés de la même façon que dans l’environnement de production. Dans certains cas, cela peut s’avérer très coûteux, car la machine doit être réglée précisément de la même façon. Toutefois, grâce la virtualisation d’ordinateurs complets, ce facteur de coût est toujours moins important.

Un accès simple

Toutes les parties prenantes doivent pouvoir accéder simplement à la dernière version et exécuter le programme. Y parvenir est relativement simple : étant donné que l’intégration continue impose dans tous les cas le regroupement de tous les fichiers dans un même dépôt, cet emplacement doit être connu de tous. Il y a plusieurs bonnes raisons à cela : les testeurs peuvent ainsi commencer sans attendre les tests supplémentaires lors du processus de programmation en cours, les parties prenantes peuvent utiliser les fichiers exécutables à des fins de démonstration et les gestionnaires de la qualité peuvent vérifier les chiffres.

Une communication claire et compréhensible

Il est essentiel que toutes les parties prenantes aient accès au texte et au fichier exécutable et sachent clairement qui doit procéder à quelles modifications. La communication inclut également le fait que les développeurs s’entendent entre eux lorsqu’ils sont dans un processus de build. Pour cela, certaines équipes utilisent des affichages séparés ou des représentations visuelles qui indiquent qu’une intégration est en cours.

Une répartition automatisée

Il est par ailleurs nécessaire d’automatiser la répartition logicielle. Les fichiers doivent être transposés d’un environnement à un autre, ce qui peut s’avérer chronophage. Ici, il est donc pertinent d’utiliser des scripts. Ces scripts permettent d’automatiser et d’accélérer le processus.

Avantages et inconvénients d’une intégration continue

Lors du travail quotidien, on constate souvent que l’intégration continue ne présente pas que des avantages en dépit de ses qualités. Si elle permet effectivement de faire l’économie d’une phase d’intégration longue et fastidieuse en fin de projet et de régler les problèmes de façon précoce, pour les équipes qui interviennent, le passage à l’intégration continue peut s’avérer très compliqué. Dans un tel cas, ce processus peut même demander plus de temps qu’il ne permet d’en économiser.

Avantages Inconvénients
Possibilité de recherche précoce des erreurs Conversion de processus habituels
Feedback permanent Nécessite des serveurs et des environnements supplémentaires
Pas de surcharge contrairement à une seule grande intégration finale Nécessité de mettre au point des processus de test adaptés
Enregistrement précis des modifications Si plusieurs développeurs souhaitent intégrer leur code approximativement au même moment, des délais d’attente peuvent survenir
Disponibilité continue d’une version actuelle opérationnelle  
Nécessité d’un travail progressif  

Présentation des outils d’intégration continue utiles

En principe, il est possible de gérer une intégration continue sans outil créé spécialement à cet effet, car toutes les étapes de travail peuvent être effectuées manuellement. Cela demande toutefois une très grande discipline et un effort encore plus conséquent. Il est possible de se faciliter la tâche avec des outils utiles. Ces derniers mettent généralement un serveur à disposition et aident à la construction et au contrôle des versions.

  • Jenkins : le très populaire Jenkins est programmé sous Java et est un fork de Hudson dont le développement a été arrêté depuis. Ce logiciel open source utilise différents outils de build et des systèmes de gestion de versions.
  • Travis CI : cet outil d’intégration continue est particulièrement apprécié car il fonctionne sans difficulté avec GitHub. Le dépôt en ligne informe Travis des modifications survenues dans le code. Le logiciel est disponible en version gratuite pour les projets open source et en version payante pour tous les autres projets.
  • Bamboo : avec le serveur Bamboo, les développeurs peuvent procéder à l’intégration, au déploiement et à la gestion des versions. Le fabricant Atlassian propose ce logiciel en tant qu’interface Web basée sur Java. Bamboo assiste les développeurs avec des automatisations et fonctionne avec différents outils de build. Pour les projets open source, cette offre normalement payante est également disponible gratuitement.
  • GitLab CI : GitLab propose un programme propre pour l’intégration continue qui fonctionne avec ce célèbre système de gestion des versions. Le pipeline peut être personnalisé et adapté à chaque projet. Par ailleurs, GitLab supporte également CI Docker.
  • CircleCI : ce programme d’intégration continue est disponible en deux versions. Il est possible d’opter pour une version directement sur le Cloud du fournisseur ou de créer un serveur local dédié pour l’utilisation.
  • CruiseControl : initialement développé par ThoughtWorks (une société bâtie autour de Martin Fowler), CruiseControl est entre-temps devenu un projet indépendant. Ce logiciel libre est basé sur Java et peut être utilisé sur différentes plateformes. CruiseControl offre notamment aux développeurs un tableau de bord, un site Internet propre, sur lequel ils peuvent identifier l’état du build.
  • Codeship : Codeship entend fournir aux développeurs une possibilité d’intégration continue d’une extrême simplicité. Des automatismes peuvent être facilement créés sur la base de la technologie de conteneurs. Pour cette tâche, l’entreprise propose deux versions différentes : la version basique et la version pro.
  • TeamCity : le logiciel commercial TeamCity accorde une grande importance à l’interopérabilité avec d’autres outils. De nombreux programmes sont déjà supportés par la version standard, mais la gamme peut également être étendue avec des plugins. On trouve par ailleurs une autre particularité dans l’approche « Pre-Tested Commit ». TeamCity vérifie automatiquement le code réécrit avant l’intégration dans la mainline et informe le développeur en cas d’erreurs.
Note

Dans notre article de fond, vous en apprendrez davantage sur les avantages et les inconvénients des différents outils d’intégration continue.