L’objectif de l’intégration continue est de :
Fabriquer un état stable du produit à partir d’incréments fonctionnels à une fréquence élevée.
Pour atteindre cet objectif, plusieurs conditions sont nécessaires :
- Chaque personne (ou équipe au niveau système) doit être responsable de l’intégration de sa partie
- Le contrôle de l’état stable doit être défini communément
- Le contrôle de l’état stable doit être passé avant intégration et revérifié après intégration
- La fabrication et le contrôle de l’état stable doivent être automatisés
- La fabrication et le contrôle de l’état stable doivent être effectués en moins d’un cycle d’intégration
- La gestion de configuration doit être adaptée à ce processus (et non l’inverse)
- Toute action apportant un état instable doit être corrigée en priorité avant toute autre action
Chaque personne (ou équipe au niveau système) doit être responsable de l’intégration de sa partie
Dans un contexte d’intégration continue, il est de la responsabilité de celui qui produit de vérifier que son apport ne casse rien. Et il lui faut aussi fournir les éléments de contrôle qui serviront aux autres pour vérifier que sa production reste stable.
- Vérifier avant soumission que rien n’est cassé
- Fournir les éléments de contrôle de la partie à soumettre
Le contrôle de l’état stable doit être défini communément
Il s’agit des tests de non régression. Qu’ils soient de niveau tests unitaires, tests d’intégration ou tests fonctionnels.
Ces tests doivent être définis au niveau global et non pas au choix par personne ou équipe.
Cela permet de garantir que les vérifications effectuées avant soumission soient cohérentes d’une personne (ou équipe) à l’autre.
Plusieurs niveaux de contrôles peuvent être définis en fonction du temps d’exécution de ceux-ci et la fréquence de passage adaptée.
Par exemple, les tests unitaires peuvent être passés tous les jours, les tests fonctionnels complets toutes les semaines, un sous-ensemble des tests fonctionnels minimum peut être défini pour passé tous les jours, c’est ce que j’appelle les tests de maturité. Ils ne couvrent pas la totalité des fonctionnalités, mais servent à vérifier le plus rapidement possible (1 à 2 heures), que le produit ne plante pas sur les cas nominaux.
Le contrôle de l’état stable doit être passé avant intégration et revérifié après intégration
Processus à respecter absolument.
- Je pars d’un état stable (nouveau branchement ou mise à jour)
- Je développe mon code (et tests). Partie techniquement cohérente, doit correspondre à une tâche du backlog de sprint pour ceux qui ont la chance d’être en mode Agile
- Je passe mes tests
- Je me remets à jour du dernier état stable.
- Je repasse mes tests et passe les tests de contrôle d’état stable
- Si ok, je soumets mon développement
Si non, je corrige et reproduit le cycle depuis étape 2
Entre étape 4 et 6, il ne faut pas qu’il y ait d’autres soumissions. N’importe quel mécanisme de sémaphore peut être utilisé, de la peluche gizmo au blocage de l’outil de gestion de conf. (Je préfère de loin la peluche)
La fabrication et le contrôle de l’état stable doivent être automatisés
Dans un processus où il n’y a qu’une livraison de temps en temps (cycle en V ou en cascade), le coût d’automatisation est élevé par rapport au nombre de fois où il est exécuté.
Dans le cas de l’intégration continue, avec un passage au moins quotidien, le rapport du coût d’automatisation sur le nombre d’exécution est réduit.
De plus l’approche Test Driven réduit encore ce coût par la mise en commun des charges de spécifications et de tests.
D’autre part, il y a maintenant une multitude d’outils d’excellente qualité répondant à tous les niveaux d’automatisation des builds et des tests et ce dans la plupart des langages de programmation actuels.
La fabrication et le contrôle de l’état stable doivent être effectués en moins d’un cycle d’intégration
Comme évoqué plus haut, lors d’une phase d’intégration, il ne doit pas y avoir d’autres soumissions en parallèle. Pour ne pas bloquer le processus d’intégration continue, cette contrainte impose que les temps d’intégration soit très raccourcis.
Tant la fabrication du produit (build) que les tests de non régression (contrôle de l’état stable).
Un effort important est à consacrer à cette diminution du temps de cycle.
Des cycles différents peuvent être effectués, par exemple :
- Cycle rapide (daily build) : build incrémental et tests de régression minimum
- Cycle moyen (Weekly build) : build total et tests de non régression normal
- Cycle long avant livraison (Release build) : build complet et tests complets
L’intérêt aussi d’un cycle court est qu’il limite le volume produit, les risques d’impact et de conflit et donc la charge d’intégration.
La gestion de configuration doit être adaptée à ce processus (et non l’inverse)
La gestion des projets (VOB ClearCase, repository Subversion,…), des composants, des branches doivent être adaptés pour faciliter ce processus.
Eviter l’organisation par composant, mais bien par projet incluant les composants.
Limiter le nombre de branches :
- Un tronc commun
- Une branche par version ou feature pour les gros projets (organisation Feature team)
- Seulement deux versions :
- celle représentant la dernière version en production
- celle pour le développement en cours
- Eventuellement une branche spécifique dans le cadre des prototypages, pour lesquels la totalité du code produit ne sera peut être pas réintégré, voire pas du tout.
Toute action apportant un état instable doit être corrigée en priorité avant toute autre action
Respecter le « Stop the line »
Rien de ne sert de produire plus, si la sortie est fermée.
Les outils d’intégration continue doivent alerter tout le monde.
Soit par mail, soit par un écran visible de tous, soit par add-on i-buddy
L’alerte doit être simple
- Etat du build : ok ou en erreur, vert ou rouge
- et/ou
- Etat des tests : ok ou anomalie détectée, vert ou rouge
Toute personne de l’équipe doit se sentir responsable de la remise en état du produit.
5 commentaires:
"Fabriquer un état stable du produit à partir d’incréments fonctionnels à une fréquence élevée." <= très réducteur de mon point de vue.
Garantir un état stable mais aussi :
- offrir une visibilité a tout instant de l'avancement et de la qualité du produit
- garantir un échange et une standardisation des pratiques entre les équipes,
- encourager l’équipe a rendre visible son travail.
De plus, certaine pratiques comme :
"Le contrôle de l’état stable doit être passé avant intégration et revérifié après intégration", doivent être nuancée suivant le contexte. On peut se demander si cela a réellement de la plus value de faire manuellement des étapes, alors que la platforme est la pour le faire. Je pense qu'il est important de séparé la qualité d'un build/intégration en journée, ou les développeurs peuvent rendre partiellement certain modules 'instables' mais sous controle, et la version nocturne qui doit être parfaite.
La gestion des branches me chatouille aussi un petit peu :
"# Un tronc commun
# Une branche par version ou feature pour les gros projets (organisation Feature team)"
Une branche pour les grosses features ... quel meilleurs moyen de recréer des problèmes d'intégration à la fin ... Je pense qu'il faut encourager les notions d'incrément et de compatibilité ascendante/descendante.
De même :
"# Seulement deux versions :
* celle représentant la dernière version en production
* celle pour le développement en cours"
Pourquoi pas une seule ? a partir du moment ou on a confiance dans ce que l'on fait, pourquoi ne pas livrer la dernière version générée en même temps que le bug fix ?
Et que faire, quand on n'a pas 1, mais plusieurs version en production ?
La section stop de line, tu insistes sur le build, les tests (unitaires ? fonctionnels ? intégration ? ), mais quid des outils d'analyses de code ?
J'ai l'air de critiquer :) mais bel effort pour essayer de synthétiser les pratiques autours de l'intégration continue.
Hello,
Je viens de voir sur ton blog un article sur l'intégration continue et ça m'a fait penser à un article lu il y a peu sur l'utilisation de la gestion de conf distribuée pour assurer un build incassable, i.e. le code sur le trunk est toujours stable. En fait le truc c'est qu'il y a un repository sur chaque poste de dev pour pouvoir bosser en local + un repository par developpeur sur le serveur d'integration et enfin un repository officiel sur le serveur et Hudson est assez malin pour écouter le repository de chaque developpeur sur le serveur et quand il y a une modif il fait un merge avec le repo officiel, passe la compilation et les tests, si tout est OK alors il reverse la modif dans le repo officiel...
C'est plus clair dans l'article:
http://blog.octo.com/gestion-de-version-distribuee-et-build-incassable/
Mathieu Cousy (depuis bubus par lolo)
@Mathieu:
Je suis par contre pas trés chaud pour le merge automatique, l'objectif est bien que chaque développeur sache et maitrise ce qu'il fait.
Je pense qu'avant d'arriver à cette solution, ils ont bien du s'amuser!
From Mathieu:
Pour moi l'intérêt n'est pas dans le merge automatique mais dans la vérification (la confiance n'exclut pas le contrôle... ;)) mais dans la pertinence du système...
@Laurent T :
On peut parler d’objectifs directs et d’objectifs dérivés.
"En tant que product owner, je veux que la fabrication de mon produit soit contrôlée, afin d'offrir une visibilité sur l'avancement, garantir ..."
Dans le contrôle de l'état stable avant/après, je n'ai pas dis qu'il fallait le faire manuellement. Il faut même utiliser les mêmes moyens de contrôles que ceux de l’intégration continue. Il faut un apprentissage, une confiance, avant le tout automatique.
Pour les branches par feature, je me suis mal exprimé. Il faut bien évidement les intégrer de manière incrémentale. Mais cela laisse un peu plus de souplesse dans le quotidien.
Quant aux outils d'analyse de code, je les plaçais de-facto dans le build. Et tu a raison d'en signaler l'importance.
Ne t’inquiètes pas, je prends les critiques comme elles viennent, la tienne est constructive et je ne pense pas avoir la vérité absolue
Enregistrer un commentaire