Intégration continue - Continuous integration

En génie logiciel , l'intégration continue ( CI ) est la pratique consistant à fusionner toutes les copies de travail des développeurs sur une ligne principale partagée plusieurs fois par jour. Grady Booch a d' abord proposé le terme CI dans sa méthode de 1991 , bien qu'il ne prône pas l'intégration plusieurs fois par jour. La programmation extrême (XP) a adopté le concept de CI et a préconisé l'intégration plus d'une fois par jour - peut-être jusqu'à des dizaines de fois par jour.

Raisonnement

Lorsqu'il se lance dans un changement, un développeur prend une copie de la base de code actuelle sur laquelle travailler. Au fur et à mesure que d'autres développeurs soumettent du code modifié au référentiel de code source , cette copie cesse progressivement de refléter le code du référentiel. Non seulement la base de code existante peut changer, mais un nouveau code peut être ajouté ainsi que de nouvelles bibliothèques et d'autres ressources qui créent des dépendances et des conflits potentiels.

Plus le développement se poursuit sur une branche sans fusionner avec la ligne principale, plus le risque de conflits d'intégration et d'échecs multiples est grand lorsque la branche développeur est finalement fusionnée. Lorsque les développeurs soumettent du code au référentiel, ils doivent d'abord mettre à jour leur code pour refléter les modifications apportées au référentiel depuis qu'ils ont pris leur copie. Plus le référentiel contient de modifications, plus les développeurs doivent travailler avant de soumettre leurs propres modifications.

Finalement, le référentiel peut devenir si différent des bases de référence des développeurs qu'ils entrent dans ce que l'on appelle parfois "l'enfer de la fusion" ou "l'enfer de l'intégration", où le temps nécessaire à l'intégration dépasse le temps nécessaire pour apporter leurs modifications d'origine. .

Flux de travail

Exécuter des tests localement

CI est destiné à être utilisé en combinaison avec des tests unitaires automatisés écrits selon les pratiques de développement piloté par les tests . Cela se fait en exécutant et en réussissant tous les tests unitaires dans l' environnement local du développeur avant de s'engager dans la ligne principale. Cela permet d'éviter que le travail en cours d'un développeur ne casse la copie d'un autre développeur. Si nécessaire, les fonctionnalités partiellement complètes peuvent être désactivées avant la validation, en utilisant des bascules de fonctionnalités par exemple.

Compiler le code en CI

Un serveur de build compile le code périodiquement ou même après chaque commit et rapporte les résultats aux développeurs. L'utilisation de serveurs de build a été introduite en dehors de la communauté XP (programmation extrême) et de nombreuses organisations ont adopté CI sans adopter tout XP.

Exécuter des tests en CI

En plus des tests unitaires automatisés, les organisations utilisant CI utilisent généralement un serveur de génération pour mettre en œuvre des processus continus d'application du contrôle qualité en général - de petits efforts, appliqués fréquemment. En plus d'exécuter les tests unitaires et d'intégration, ces processus exécutent des analyses statiques supplémentaires, mesurent et profilent les performances, extraient et formatent la documentation du code source et facilitent les processus manuels d' assurance qualité . Sur le populaire service Travis CI pour l'open source, seulement 58,64 % des tâches CI exécutent des tests.

Cette application continue du contrôle qualité vise à améliorer la qualité du logiciel et à réduire le temps nécessaire pour le livrer, en remplaçant la pratique traditionnelle consistant à appliquer le contrôle qualité après avoir terminé tout le développement. Ceci est très similaire à l'idée originale d'intégrer plus fréquemment pour faciliter l'intégration, appliquée uniquement aux processus d'assurance qualité.

Déployer un artefact à partir de CI

Désormais, la CI est souvent liée à la livraison continue ou au déploiement continu dans ce que l'on appelle le pipeline CI/CD. La « livraison continue » garantit que le logiciel enregistré sur la ligne principale est toujours dans un état pouvant être déployé pour les utilisateurs et le « déploiement continu » rend le processus de déploiement entièrement automatisé.

Histoire

Le premier travail connu sur l'intégration continue était l'environnement Infuse développé par GE Kaiser, DE Perry et WM Schell.

En 1994, Grady Booch a utilisé l'expression intégration continue dans l' analyse et la conception orientées objet avec applications (2e édition) pour expliquer comment, lors du développement à l'aide de microprocessus, « les versions internes représentent une sorte d'intégration continue du système et existent pour forcer fermeture du microprocessus".

En 1997, Kent Beck et Ron Jeffries ont inventé l' Extreme Programming (XP) alors qu'ils travaillaient sur le projet Chrysler Comprehensive Compensation System , y compris l'intégration continue. Beck a publié sur l'intégration continue en 1998, soulignant l'importance de la communication face à face par rapport au support technologique. En 1999, Beck a développé davantage dans son premier livre complet sur la programmation extrême. CruiseControl , l'un des premiers outils de CI open source, a été publié en 2001.

En 2010, Timothy Fitz a publié un article détaillant comment l' équipe d'ingénierie d' IMVU avait construit et utilisé le premier système CI pratique. Bien que son message ait été initialement accueilli avec scepticisme, il a rapidement fait son chemin et a été largement adopté dans le cadre de la méthodologie de développement de logiciels Lean , également basée sur IMVU.

Pratiques courantes

Cette section répertorie les meilleures pratiques suggérées par divers auteurs sur la manière de réaliser une intégration continue et d'automatiser cette pratique. L'automatisation de la construction est une bonne pratique en soi.

L'intégration continue - la pratique consistant à intégrer fréquemment son code nouveau ou modifié avec le référentiel de code existant - devrait se produire suffisamment fréquemment pour qu'il ne reste aucune fenêtre intermédiaire entre commit et build , et qu'aucune erreur ne puisse survenir sans que les développeurs ne les remarquent et ne les corrigent immédiatement. La pratique normale consiste à déclencher ces builds à chaque validation dans un référentiel, plutôt qu'une build périodiquement planifiée. Les aspects pratiques de le faire dans un environnement multi-développeurs de commits rapides sont tels qu'il est habituel de se déclencher peu de temps après chaque commit, puis de démarrer une construction lorsque ce minuteur expire ou après un intervalle un peu plus long depuis la dernière construction . Notez que puisque chaque nouvelle validation réinitialise le minuteur utilisé pour le déclencheur à court terme, il s'agit de la même technique utilisée dans de nombreux algorithmes anti-rebond de bouton. De cette façon, les événements de validation sont « anti-rebonds » pour éviter les builds inutiles entre une série de validations rapides. De nombreux outils automatisés proposent cette planification automatiquement.

Un autre facteur est le besoin d'un système de contrôle de version qui supporte les commits atomiques ; c'est-à-dire que toutes les modifications d'un développeur peuvent être considérées comme une seule opération de validation. Il ne sert à rien d'essayer de construire à partir de seulement la moitié des fichiers modifiés.

Pour atteindre ces objectifs, l'intégration continue repose sur les principes suivants.

Maintenir un référentiel de code

Cette pratique préconise l'utilisation d'un système de contrôle de révision pour le code source du projet. Tous les artefacts requis pour construire le projet doivent être placés dans le référentiel. Dans cette pratique et dans la communauté du contrôle des révisions, la convention est que le système doit pouvoir être construit à partir d'une nouvelle extraction et ne pas nécessiter de dépendances supplémentaires. L' avocat de l' Extreme Programming, Martin Fowler, mentionne également que lorsque le branchement est pris en charge par des outils, son utilisation doit être minimisée. Au lieu de cela, il est préférable d'intégrer les modifications plutôt que de maintenir simultanément plusieurs versions du logiciel. La ligne principale (ou tronc ) doit être l'emplacement de la version de travail du logiciel.

Automatiser la construction

Une seule commande devrait avoir la capacité de construire le système. De nombreux outils de construction, tels que make , existent depuis de nombreuses années. D'autres outils plus récents sont fréquemment utilisés dans les environnements d'intégration continue. L'automatisation de la construction doit inclure l'automatisation de l'intégration, qui inclut souvent le déploiement dans un environnement de type production . Dans de nombreux cas, le script de construction compile non seulement les binaires, mais génère également de la documentation, des pages de site Web, des statistiques et des supports de distribution (tels que les fichiers Debian DEB , Red Hat RPM ou Windows MSI ).

Faire l'auto-test de construction

Une fois le code construit, tous les tests doivent être exécutés pour confirmer qu'il se comporte comme les développeurs s'attendent à ce qu'il se comporte.

Tout le monde s'engage sur la ligne de base chaque jour

En s'engageant régulièrement, chaque commiter peut réduire le nombre de changements conflictuels. L'enregistrement d'une semaine de travail risque d'entrer en conflit avec d'autres fonctionnalités et peut être très difficile à résoudre. Au début, de petits conflits dans une zone du système amènent les membres de l'équipe à communiquer sur le changement qu'ils sont en train d'apporter. La validation de toutes les modifications au moins une fois par jour (une fois par fonctionnalité créée) est généralement considérée comme faisant partie de la définition de l'intégration continue. De plus, il est généralement recommandé d' effectuer une construction nocturne . Ce sont des limites inférieures ; la fréquence typique devrait être beaucoup plus élevée.

Chaque commit (à la ligne de base) doit être construit

Le système doit générer des commits vers la version de travail actuelle pour vérifier qu'ils s'intègrent correctement. Une pratique courante consiste à utiliser l'intégration continue automatisée, bien que cela puisse être fait manuellement. L'intégration continue automatisée utilise un serveur ou un démon d' intégration continue pour surveiller le système de contrôle des révisions à la recherche de modifications, puis exécuter automatiquement le processus de génération.

Chaque commit de correction de bogue doit être accompagné d'un cas de test

Lors de la correction d'un bogue, il est recommandé de pousser un scénario de test qui reproduit le bogue. Cela évite que le correctif ne soit annulé et que le bogue ne réapparaisse, ce qui est connu sous le nom de régression . Les chercheurs ont proposé d'automatiser cette tâche : si un commit de correction de bogue ne contient pas de cas de test, il peut être généré à partir des tests déjà existants.

Gardez la construction rapide

La construction doit se terminer rapidement, de sorte que s'il y a un problème d'intégration, il soit rapidement identifié.

Tester dans un clone de l'environnement de production

Disposer d'un environnement de test peut entraîner des défaillances dans les systèmes testés lorsqu'ils se déploient dans l' environnement de production, car l'environnement de production peut différer de manière significative de l'environnement de test. Cependant, la construction d'une réplique d'un environnement de production est d'un coût prohibitif. Au lieu de cela, l'environnement de test, ou un environnement de pré-production distinct (« staging ») doit être conçu pour être une version évolutive de l'environnement de production afin de réduire les coûts tout en maintenant la composition et les nuances de la pile technologique . Dans ces environnements de test, la virtualisation des services est couramment utilisée pour obtenir un accès à la demande à des dépendances (par exemple, des API, des applications tierces, des services, des mainframes , etc.) qui échappent au contrôle de l'équipe, continuent d'évoluer ou sont trop complexes à configurer dans un laboratoire de test virtuel.

Facilitez l'obtention des derniers livrables

Rendre les builds facilement accessibles aux parties prenantes et aux testeurs peut réduire la quantité de retouches nécessaires lors de la reconstruction d'une fonctionnalité qui ne répond pas aux exigences. De plus, les tests précoces réduisent les chances que les défauts survivent jusqu'au déploiement. Trouver les erreurs plus tôt peut réduire la quantité de travail nécessaire pour les résoudre.

Tous les programmeurs devraient commencer la journée en mettant à jour le projet à partir du référentiel. De cette façon, ils resteront tous à jour.

Tout le monde peut voir les résultats de la dernière version

Il devrait être facile de savoir si le build s'effondre et, si c'est le cas, qui a effectué le changement pertinent et en quoi consistait ce changement.

Déploiement automatisé

La plupart des systèmes CI autorisent l'exécution de scripts une fois la construction terminée. Dans la plupart des situations, il est possible d'écrire un script pour déployer l'application sur un serveur de test en direct que tout le monde peut consulter. Une autre avancée dans cette façon de penser est le déploiement continu , qui nécessite que le logiciel soit déployé directement en production, souvent avec une automatisation supplémentaire pour éviter les défauts ou les régressions.

Coûts et bénéfices

L'intégration continue est destinée à produire des avantages tels que :

  • Les bogues d'intégration sont détectés tôt et sont faciles à localiser grâce à de petits ensembles de modifications. Cela permet d'économiser du temps et de l'argent sur la durée de vie d'un projet.
  • Évite le chaos de dernière minute aux dates de sortie, lorsque tout le monde essaie de vérifier leurs versions légèrement incompatibles
  • Lorsque les tests unitaires échouent ou qu'un bogue apparaît, si les développeurs doivent rétablir la base de code à un état sans bogue sans débogage , seul un petit nombre de modifications sont perdues (car l'intégration se produit fréquemment)
  • Disponibilité constante d'une version « actuelle » à des fins de test, de démonstration ou de publication
  • La vérification fréquente du code pousse les développeurs à créer un code modulaire et moins complexe

Avec les tests automatisés continus, les avantages peuvent inclure :

Certains inconvénients de l'intégration continue peuvent inclure :

  • La construction d'une suite de tests automatisée nécessite une quantité de travail considérable, y compris un effort continu pour couvrir les nouvelles fonctionnalités et suivre les modifications intentionnelles du code.
  • Il y a du travail à faire pour mettre en place un système de build , et cela peut devenir complexe, ce qui rend difficile la modification de manière flexible.
  • L'intégration continue n'est pas nécessairement utile si la portée du projet est petite ou contient du code hérité non testable.
  • La valeur ajoutée dépend de la qualité des tests et du degré de testabilité du code.
  • Des équipes plus grandes signifient que du nouveau code est constamment ajouté à la file d'attente d'intégration, donc le suivi des livraisons (tout en préservant la qualité) est difficile et la mise en file d'attente des builds peut ralentir tout le monde.
  • Avec plusieurs commits et fusions par jour, le code partiel d'une fonctionnalité peut facilement être poussé et donc les tests d'intégration échoueront jusqu'à ce que la fonctionnalité soit terminée.
  • La sécurité et l'assurance du développement critique (par exemple, DO-178C , ISO 26262 ) nécessitent une documentation rigoureuse et une revue en cours de processus qui sont difficiles à réaliser en utilisant l'intégration continue. Ce type de cycle de vie nécessite souvent la réalisation d'étapes supplémentaires avant la sortie du produit lorsque l'approbation réglementaire du produit est requise.

Voir également

Les références

Liens externes