Intégration Continue - Schéma
« L’intégration continue chez AT Internet »

J’ai décidé cette fois ci de synthétiser l’ensemble de mon propos en un unique visuel, en l’accompagnant d’explications plus détaillées pour ceux qui souhaitent entrer plus dans le détail :

Les grands principes de l’intégration continue

C’est un ensemble de pratiques visant à livrer efficacement le code logiciel produit par les équipes de développement. On y retrouve différents objectifs parmi lesquels :

  • La limitation des actions manuelles par l’automatisation des builds, des livraisons et autres opérations de déploiement. Ceci limite le risque d’erreur humaine et permet aux experts de se concentrer sur leur produit plutôt que d’investir continuellement du temps à effectuer des opérations répétitives qu’une machine peut très bien faire à leur place.
  • La mise à disposition rapide de feedbacks offrant une bonne visibilité sur les impacts potentiels des modifications apportées au code existant. Chaque membre des équipes de développement peut alors sereinement apporter des modifications à la base de code existante et s’appuyer sur les automatismes en place pour l’informer de la bonne intégration de son code dans le produit.

On parle d’intégration continue du nouveau code, de livraison continue des livrables et de déploiement continu des produits mais comment faire le lien entre le code source, les livrables et les environnements dans le processus global. Certaines questions reviennent souvent :

  • Quand je pratique la ‘promotion’, est-ce de la promotion de mon code ? de la promotion de livrables ? de la promotion d’environnement ?
  • Quel lien entre le déploiement en production et la branche master du dépôt de code ?
  • Quels automatismes puis-je mettre en place pour assurer une cohérence entre la vie de mon dépôt de code et celle de mon application, à travers les différents environnements ?

Ces questions peuvent trouver des réponses différentes suivant le contexte technique ou projet, le secteur d’activité ou le niveau de maturité des processus dans l’entreprise. Je vais donc tenter dans cet article de détailler les concepts et principes, sans créer de dépendance avec tel ou tel outil. Il est en effet question du cycle de livraison des logiciels, indépendamment des moyens choisis pour sa mise en œuvre, même si certains outils peuvent parfois faciliter la vie !

Le concept du « build once »

Intégration continue - Build-once - Schéma
« L’intégration continue: le build-once »

Un des principes clés de l’intégration continue est le « build once » ou autrement dit ne construire un nouveau livrable que si le code métier a été modifié. Cette pratique vise à réduire le risque de construire un livrable différent au moment de déployer celui-ci sur un nouvel environnement. En effet, on trouve trop souvent des pratiques de re-build au moment de livrer, en pensant bien sûr obtenir un livrable identique.

Mais il subsiste des risques (parfois importants) d’avoir un souci lors de ce nouveau build :

  • Problème de machine (disque plein, autre…)
  • Souci de réseau
  • Problème lié à l’outil de build (en maintenance, indisponible)
  • Embarquer une version différente d’une des dépendances de notre produit
  • Se baser involontairement sur une version différente du code

On peut donc, sans s’en rendre compte, en toute bonne foi et malgré de multiples précautions, obtenir un produit différent de celui qui a passé avec succès les différentes phases de validation de notre cycle de développement. On perd alors tout le bénéfice des tests et vérifications menés.

Le meilleur moyen d’éviter ce risque est de construire une seule fois le livrable puis de l’utiliser tel quel, lors des déploiements à venir, pour les phases de validation et jusqu’à la mise en production finale, c’est ce qu’on appelle la pratique du « build once ».

La promotion de livrables

Intégration continue promotion de livrables schéma
« L’intégration continue: la promotion de livrables »

Maintenant que nous avons notre livrable, nous allons vouloir lui faire subir un certain nombre de tests pour pouvoir valider in fine sa mise en production. Nous avons alors besoin de différentes « étagères » pour stocker nos livrables afin d’identifier facilement les livrables en fonction de leur avancement dans les phases de validation.

Ces « étagères » peuvent prendre différentes formes suivant les technologies (gestionnaires de livrables, dossiers de livraison, archivage d’artefacts, dépôts d’images docker etc.) et leur nombre dépend du cycle de livraison choisi. Certaines entreprises vont avoir besoin de plus de phases de validation et d’intégration que d’autres, pour des raisons de conformité à certaines normes, d’intégrations complexes ou autres…

Chez AT Internet, nous avons fait le choix de disposer de 4 « étagères » pour organiser nos livrables (dev, integ, preprod, prod) et d’une supplémentaire (staging) pour permettre la livraison urgente de bugfixes.

Le passage d’un livrable d’une étagère vers l’autre est conditionné par le bon déroulement de différentes phases de test et de validations. Si toutes les conditions sont réunies, on peut déplacer le livrable vers l’étagère suivante : c’est la promotion. Certains procèderont à une simple copie (plutôt qu’à un déplacement). Certains outils exposent directement des méthodes de promotion des livrables qu’ils hébergent.

On a alors une vue d’ensemble sur les livrables et leur niveau de validation, en observant simplement leur place dans le dépôt. La présence d’un livrable sur une des étagères décrit également son caractère de candidat à un environnement donné. C’est ce lien fort qui conduit parfois au terme de « promotion d’environnement ».

Les environnements de dev

Intégration continue environnement et tests schéma
« L’intégration continue: les environnements et leurs tests »

Une fois ces livrables obtenus et stockés quelque part, il faut leur faire subir les différentes étapes de test et de validation pour décider si oui ou non, nous pouvons les livrer en production. Il est alors nécessaire de déployer chaque livrable sur l’environnement auquel il est candidat. C’est la mise en service du produit, sur un environnement donné, pour lui faire subir des tests dynamiques. Ces tests sont des tests dits « boite noire », indépendants du code ou de la technologie utilisée pour l’implémentation.

Développement : la première phase de déploiement

On commence ainsi à déployer chaque livrable sur l’environnement de développement et on le soumet à une première phase de tests. Le premier de ces tests consiste à valider la mécanique de déploiement. C’est en effet la première fois qu’on tente de déployer ce livrable quelque part. Le bon déroulement du déploiement constitue une première étape pour se rassurer sur notre capacité à livrer le produit jusqu’en production.

On va ensuite valider sur cet environnement un certain nombre de propriétés de notre système (fonctionnelles ou non fonctionnelles) mais aussi la validité de certaines configurations de notre livrable.

Si tout est ok, on peut alors promouvoir le livrable et le déployer sur l’environnement suivant pour la phase d’intégration.

Intégration : valider tous les scénarios

Dans cette phase, le système validé isolément est mis en présence des autres systèmes de la solution logicielle. Il pourra alors être mis en jeu dans la phase de tests d’intégration de systèmes qui vise à dérouler des usecases métier qui traversent plusieurs systèmes afin de valider le bon branchement des différents éléments de la solution.

A chaque succès de la validation sur l’environnement de développement, on peut mettre à jour cet environnement d’intégration.

Préproduction : répétition générale

En préproduction, on procède à une dernière phase de tests avant de mettre en production, en déployant uniquement les fonctionnalités qu’on décide de mettre en production lors de la prochaine release. Cette décision n’est pas une étape nécessaire et elle est souvent liée à une décision marketing ou commerciale.

Il s’agit bien souvent sur cet environnement d’opérations de recette et d’acceptation, qui n’ont pas vocation à détecter des bugs dans le produit. Si des bugs sont trouvés à cette étape, c’est bien souvent signe d’un manque de test dans une des étapes précédentes.

Si la livraison en production n’est pas liée à des contraintes de communication client ou d’accompagnement de ces derniers, on peut tout à fait envisager de n’avoir qu’un seul environnement « pré-production », en lieu et place des environnements d’intégration et de préproduction. On accepte alors la contrainte (ou l’avantage) que tout le code validé en dev part tout droit en production s’il passe avec succès les étapes de validation suivantes.

Staging

Le staging permet de valider une correction à apporter rapidement en production. On déploiera sur cet environnement le code actuel de production, avec pour seule modification la correction apportée, en vue de valider la bonne correction du problème constaté. On vérifie également l’absence d’effet de bord (régressions) de cette modification apportée au produit.

Production

Certains tests d’un type différent peuvent tout à fait se dérouler en production, on parle souvent de « Tests Post Déploiement ». Il s’agit là plutôt de valider les aspects liés à l’environnement, les configurations spécifiques, les systèmes de monitoring ou encore de ce que je qualifierais d’expérimentations fonctionnelles (canari testing, A/B testing, feature flipping) etc…

A cette étape, l’objectif n’est pas non plus de détecter d’éventuels bugs dans un des systèmes mis en jeu (même si cela peut arriver !)

L’automatisation de la livraison

Jenkins automatisation livraison

Cette orchestration de la livraison d’un produit logiciel a vocation à être systématique et répétitive. Il est donc naturel de penser à automatiser tout cela. Différents outils permettent bien sûr de mettre en place cette orchestration (Jenkins, Travis CI, GitlabCI etc…) mais les principes sont indépendants du choix de cet outil. Au-delà des étapes essentielles de cette automatisation (présentes à droite sur l’image liée à l’article), il me parait important de souligner seulement quelques détails :

  • La publication : c’est le dépôt du livrable sur une des « étagères » en vue de son déploiement à venir sur un des environnements. L’étagère choisie dépend de la branche de code considérée. Voici les chemins de publication identifiés :
    • Branche ‘develop’ => livrables candidats à l’environnement de ‘développement’
    • Branche ‘release’ => livrables candidats à l’environnement de ‘préproduction’
    • Branche ‘hotfix’ => livrables candidats à l’environnement de ‘staging’
    • Toute autre branche => pas de publication du livrable (on peut tout de même le récupérer si on le souhaite pour le soumettre à des tests)
  • On peut profiter de l’étape de promotion pour automatiser différentes opérations. (certains préfèreront garder la main sur ces opérations ou les intégrer à l’étape suivante : la phase de déploiement)
    • Promotion intégration > préproduction
      • merger le code de ‘develop’ vers ‘release’
      • incrémenter la version mineure et remettre à ‘0’ la version patch sur ‘develop’
    • Promotion préproduction > production
      • merger le code de ‘release’ vers ‘master’
      • appliquer un tag sur ‘master’
    • Promotion staging > production
      • merger le code de ‘hotfix’ vers ‘master’
      • appliquer un tag sur ‘master’
  • Chez AT Internet, nous utilisons Jenkins et une question revient souvent dans les équipes : doit-on orchestrer tout cela en un seul grand job ou en plusieurs jobs distincts. La réponse est quelque part entre les deux et dépend de votre avancée dans la mise en place des différentes étapes de l’intégration continue. Certains principes sont pourtant importants à considérer :
    • Le déploiement d’un livrable existant doit être possible à tout moment, sans dépendre des étapes de construction de ce livrable.

Le lancement de certains tests sur un environnement donné doit être possible à tout moment, sans dépendre des étapes de construction et de promotion des livrables.

L’intégration dis-continue

« L’intégration discontinue: des actions manuelles dans le flux »

Le flux idéal qui permet la livraison continue en production requiert un certain nombre d’automatismes et d’outils qui sont autant de remparts de sécurité qui permettent de valider graduellement les produits jusqu’à leur mise en production. Il manque bien souvent certains éléments dans la chaine pour confier totalement la responsabilité à des scripts et autres robots de test la « décision » de livrer en production. Voici l’ordre dans lequel ces éléments sont souvent mis en place, dans l’évolution d’une R&D :

  1. Construction du livrable (build)
  2. Tests unitaires
  3. Scripts de déploiement
  4. Qualité de code
  5. Déclenchement des tests
  6. Mécaniques de promotions

Quand un ou plusieurs de ces éléments manquent, l’opération reste manuelle. On déclenche alors également manuellement la suite des opérations, si des automatismes sont présents pour poursuivre. Nous sommes alors dans une situation que je qualifierais d’intégration dis-continue.

A un niveau de maturité supérieur, toutes les opérations sont automatisées mais nous ne sommes pas encore prêts à nous passer d’actions manuelles pour déclencher les mises en production. C’est souvent le cas si toutes les mécaniques sont disponibles mais les tests sur les différents environnements trop peu étoffés. On a alors toujours besoin de se rassurer avec quelques actions manuelles pour « recetter » et augmenter notre niveau de confiance. Jusqu’au jour où on peut avec plaisir se rendre compte qu’on n’intervient plus que pour déclencher la suite des opérations, en se basant simplement sur le statut qu’affichent certains systèmes. On peut alors relier cette opération au reste de la chaîne car notre action n’apporte plus aucune valeur ajoutée. Le passage à ce stade de livraison continue requiert également de bons systèmes de surveillance de la production pour être confiant sur la résilience du système à une défaillance qui serait passée à travers les différentes étapes de validation sans être détectée. Ceci pourra faire l’objet d’un prochain article !

Author

Fort de plus de 10 ans d’expérience en stratégie et implémentation de tests logiciels en environnement Agile, Alexandre est en charge de l’industrialisation des développements chez AT Internet. Son challenge au quotidien : accompagner nos équipes de développement dans la mise en place d’outils et méthodes afin de garantir à nos clients des livraisons régulières et de qualité.

Comments are closed.