· Poster vos modifications
Une fois que les modifications que vous avez
effectuées sont fonctionnelles, vous pouvez envoyer vos changements sur
le dépôt. Pour se faire, placez-vous à la racine de votre
copie de travail, et exécutez la commande :
- svn commit -m "Mon résumé de mes changements"
· Créer un Tag de version du logiciel
Une fois que vous estimez que le "tronc" (trunk) courant est
stable, vous pouvez créer un tag pour une nouvelle version de votre
logiciel. Généralement, cela se fait à chaque livraison au
client. Pour ce faire, exécutez la commande :
- svn cp http://svn.web-srv-yde.com/projet2/trunk
- http://svn.web-srv-yde.com/projet2/tags/numero.de.version
Une convention assez courante de numérotation de
version est une numérotation à 3 chiffres : 1.2.3 ou :
· 1 est le numéro de version majeur. Il change
lorsque le logiciel subit de grosses modifications de fond, et n'est plus
compatible avec la version précédente.
· 2 est le numéro de version mineur. Il
représente l'ajout de nouvelle fonctionnalités, ou la
modification d'existantes, tout en restant compatible avec la version
précédente du logiciel.
· 3 est le numéro de correctif. Il
représente le nombre de mise à jour correctives appliquées
sur le logiciel depuis la dernière version mineure.
· Afficher la liste des modifications entre 2
révisions
La commande suivante:
- svn diff -r 310 :304 -- summarize
Affiche la liste des fichiers modifiés entre la
révision 304 et la révision 310.
I.3.4 Tronc, branches,
tags
Les notions de tronc, de branches et de tags sont
assez spécifiques aux logiciels de contrôle de versions. C'est ce
qui explique que les arborescences des répertoires de projet contiennent
souvent comme premier niveau de sous-répertoires les dossiers trunk,
branches et tags. En général, on définit par
« tronc » la version centrale du programme, le
développement principal « officiel ». Une
« branche » est en général
créée lorsqu'un développement
« secondaire » est mis en route, que ce soit pour ajouter
une nouvelle fonctionnalité ou parce que certains développeurs
souhaitent essayer de prendre une autre direction pour certains aspects du
développement. Une branche peut, au bout d'un certain temps, soit
être à nouveau fusionnée dans le
« tronc », soit disparaître, soit donner lieu
à un nouveau programme. La notion de tags correspond en
partie à celle de release, c'est à dire de marquage
d'une certaine révision du projet comme composant une version du projet.
Une fois que le développement a atteint une certaine stabilité,
on pourra par exemple créer un tag pour marquer la sortie de la
version 1.0. Ceci permettra de revenir facilement à cette version,
indépendamment du numéro de révision sous-jacent
correspondant. Nous n'entrerons pas dans le détail de ces concepts et
commandes ici, mais on peut juste citer que la création de
branches ou de tags ne sont en fait que des copies
créées par la commande svn copy. La commande svn switch, elle,
permet de faire passer la copie de travail d'une branche à une autre.
Figure 3 : Arborescence de la copie
locale
I.4 Les tests unitaires
Le but des tests unitaires est d'automatiser les tests de
non-régression. Quand on développe un logiciel, on peut
facilement faire des modifications sans se rendre compte qu'elles introduisent
des bugs dans certains cas particuliers. C'est ce qu'on appelle des bugs de
régression, en ce sens qu'on introduit de nouveaux bugs à la
suite d'une évolution fonctionnelle. Comme il n'est pas humainement
possible de tester systématiquement tous les cas d'utilisation possible,
ces bugs peuvent se retrouver déployés en production, avec tous
les problèmes que cela comporte.
Une des notions importantes, quand on fait du
développement, est de savoir que plus un bug est détecté
tôt, plus il sera facile à corriger. Les gros soucis arrivent
quand on fait du "sur-développement" par-dessus un bug de
régression ; il devient très difficile de faire un retour en
arrière sur le code incriminé, car cela impliquerait de supprimer
des fonctionnalités. Il faut alors corriger ce nouveau code, en essayant
de trouver une aiguille dans une botte de foin.
Concrètement, les tests unitaires consistent en un
ensemble de scripts, qui ont chacun en charge la validation d'un morceau de
code (ou d'une classe lorsqu'il d'agit de la programmation orientée
objet). Il est assez évident de tester de la sorte les
bibliothèques de fonction : les "librairies" peuvent être
vues comme des boîtes noires, avec des entrées et des sorties. Il
suffit d'injecter certaines données en entrée, et vérifier
la conformité de ce qu'on obtient en sortie. Pour du code applicatif,
c'est un peu plus délicat, car on est parfois obligé de mettre en
place un environnement de test sophistiqué (bases de données avec
lots de test, génération de données aléatoires,
gestion des tentatives de hack, ...). Mais bien heureusement il existe de
très nombreux Framework pour nous aider à y arriver ;
suivant la plate-forme de développement, on distingue :
§ Java : JUnit,
§ PHP : SimpleTest, PHPunit
§ C++ : CppUnit,
§ JavaScript : JSUnit,
§ ActionScript : ASUnit,
§ Ruby : Test::Unit,
§ Perl : Test::Unit,
§ Python : unittest ,
§ .NET: NUnit.
Au cours du développement, il faut évidemment
prendre le temps de réaliser les tests équivalents à
chaque nouvelle fonctionnalité, à chaque nouveau cas particulier.
Mais ce temps se récupère au moment du test et du
débogage. Il suffit de lancer les tests unitaires pour savoir rapidement
où les bugs se situent, ce qui permet de les corriger sans perdre de
temps.
I.5 Le cycle d'un gestionnaire de
version
Figure 4 : Cycle de vie du
gestionnaire de versions
I.6 Avantage de
l'architecture
Les pratiques sont les suivantes :
§ Maintenir un dépôt unique de code source
versionné;
§ Automatiser les compilations ;
§ Rendre les compilations auto-testantes ;
§ Tout le monde commit tous les jours ;
§ Tout commit doit compiler le tronc sur une machine
d'intégration ;
§ Maintenir une compilation courte ;
§ Tester dans un environnement de test
cloné ;
§ Rendre disponible facilement le dernier
exécutable ;
§ Tout le monde doit voir ce qui se passe ;
§ Automatiser le déploiement.
Chapitre II.
L'INTEGRATION CONTINUE
II.1
Contexte
Avant de commencer avec l'intégration continue, il
faut comprendre l'architecture "idéale" de développement d'une
application (dans notre cas d'une application Web). Elle se compose de cinq
environnements :
§ Les postes des développeurs
(dits "locaux"), avec les différents outils traditionnels (IDE, outils
de modélisation de base de données, éditeurs XML, ...)
§ L'environnement de
développement. Il est réservé aux
développeurs qui en ont tous les droits (administrateurs). On verra que
c'est l'environnement cible de l'intégration continue. Il est ainsi
toujours à jour avec la dernière version disponible de
l'application. De plus son état est souvent plus ou moins stable
(redémarrage fréquent des applications, données volatiles
insérées par les développeurs dans le cadre de leurs
tests, ...)
§ L'environnement de test à
destination du client (par exemple le comité de direction). Ce dernier
valide le bon développement de l'application par rapport à ses
besoins. Dans le cadre d'un développement itératif, il permet
surtout de découvrir à temps les besoins réels du client
qui sont trop souvent mal exprimés ou incomplets. Une nouvelle version
de l'application est déployée depuis l'environnement de
développement dès que l'application est estimée stable et
qu'elle contient suffisamment de nouveautés ou corrections de bugs par
rapport à la version précédente. Ces déploiements
sont tout de même fréquents (toutes les 1 à 2 semaines) et
sont généralement effectués manuellement à la
demande du chef de projet. On offre alors généralement un fichier
changes.txt qui décrit les différentes évolutions et
corrections de bugs apportées depuis la version
précédente.
§ L'environnement de
pré-production pour tester la version finale de l'application.
Il reproduit à l'identique l'environnement de production (nombre de
machines, processeurs, mémoires, versions des applications, ...). Il
permet de réaliser les tests de charge et de valider la bonne
exécution de l'application lors du passage en production.
§ L'environnement de production
accessible par les clients.
§ Hormis les machines locales, ces environnements sont
indépendants entre eux et exécutent leurs propres serveurs
(Apache, conteneur J2EE, base de données, serveur de mail...). Seules
les machines locales et l'environnement de développement se partagent
quelques applications :
§ le serveur SCM (Source Control
Management) comme CVS ou Subversion. Il centralise toutes les sources des
différents projets et gère les notions liées au
versionning (branche, différences entre deux versions d'un même
fichier, ...).
Figure 5 : Architecture
intégration continue
II.2
Objectifs
L'intégration continue est un processus
d'automatisation de tâches récurrentes liées à
l'environnement de développement. Les plus connues sont :
· construction ("build") de l'application à partir
des données contenues dans le SCM. Cela comprend la compilation des
sources et la construction des releases (JAR, WAR, EAR, ...)
· déploiement de l'application sur l'environnement
de développement (copie des librairies, configuration et
redémarrage)
· exécution des tests unitaires et
d'intégration
· génération de rapports, par exemple
phpdocumentor
Tout l'intérêt de cette automatisation
réside dans sa fréquence d'exécution, qui doit être
au minimum quotidienne. On dispose alors régulièrement d'un
environnement mis à jour avec la toute dernière version de
l'application, mais surtout de l'état du projet (succès de la
compilation, des tests et du déploiement). Et c'est là un des
gros avantages de l'intégration continue : le fait que l'on sache
immédiatement qu'une tâche a échoué apporte une
certaine discipline au développeur. Finis les "ca
compile pas chez moi!" (mais chez le voisin oui). Ces problèmes prennent
toujours plus de temps à trouver leur origine qu'à les corriger
(oubli d'archivage de fichier, suppression d'un fichier encore utilisé
quelque part ailleurs, modification de code impactant un autre composant, ...).
Avec l'intégration continue on connaît tout de suite la nature et
l'origine du problème.
Un autre gros avantage est la réduction du
coût de correction des bugs, à condition bien entendu de
l'existence de tests... La fréquence élevée
d'intégration diminue le délai de détection d'un bug. Le
contexte est alors encore d'actualité pour les développeurs et
les modifications de code depuis l'insertion du bug sont peu nombreuses et
encore connues. En effet quoi de plus coûteux qu'un bug découvert
longtemps après son insertion ! (5% des bugs représentent
95% du coût de correction).
On peut encore trouver d'autres avantages à
l'intégration continue :
· gain de temps pour ceux qui avaient la longue et
laborieuse tâche de déployer en développement.
· connaissance plus concrète du chef de projet de
l'état d'avancement du développement.
Bien entendu vous aurez compris que l'intégration
continue n'a d'intérêt que dans le cadre d'un développement
itératif. Et elle peut être mise en place quelque
soit la taille du projet, même si il n'y a qu'un développeur...
II.3 Serveur
d'intégration
Parmi les serveurs d'intégration continue existants,
ceux qui répondent à nos attentes et dont les
caractéristiques intègrent les outils que nous avons choisis
sont :
§ CruiseControl + l'extension phpUnderControl.
§ Xinc.
|
CruiseControl
|
Xinc
|
Plateforme d'exécution
|
JVM
|
PHP
|
Programme d'installation
|
Installeur Windows
|
PEAR
|
Outil de build préférés
|
Ant, Maven
|
Phing
|
Autres outil de build supportés
|
Phing (intégration instable)
|
|
Support SCM
|
CVS, SVN, Perforce,...
|
SVN
|
Langages supportés
|
Tout ce qui peut être construit avec Ant
|
PHP
|
Web Front end_
|
Jetty
|
Apache
|
Extensible via
|
XSL, JSP, Java
|
Xinc Plugins (PHP)
|
Tableau 1: CruiseControl vs
Xinc
·
Rétroaction
§ Les résultats de l'intégration
sont notifiés à l'équipe développement et
publiés sur un site web accessible aux parties prenantes au projet.
§ La correction des constructions en erreur est
une priorité des membres de l'équipe de
développement :
Ø Gain de temps
Ø Diminution des coûts
Corriger les défauts détectés
avant qu'ils ne se manifestent.
·
Inspection
§ L'intégration continue permet d'obtenir
continuellement des indicateurs d'avancement et d'état qualitatif d'un
projet en cours de développement.
§ Les outils d'assurance de qualité
participent au contrôle des risques :
Ø Risques de faible qualité
logicielle
Ø Risques de découverte tardive des
défauts
Pour les projets de développement basé
sur le langage PHP, il existe un serveur d'intégration continue
écrit en PHP 5 : Xinc. Il comprend nativement le
support de Subversion et de Phing (et donc PHPUnit). Il peut aussi être
étendu pour travailler avec d'autres outils de gestion de code source ou
de build.
II.4 Système de
build
Pour un petit programme avec une douzaine de fichiers,
la construction de l'application peut être juste une question de commande
unique pour un compilateur. Des projets plus importants ont besoin d'un peu
plus que la compilation fichier par fichier : tests, compilation
simultanée, déplacement de fichiers compilés,
création d'auto-docs, compression, mise en ligne avec CVS/Subversion....
Dans ces cas, vous avez des fichiers dans plusieurs répertoires. Vous
devez vous assurer que le code objet qui en résulte est au bon endroit.
Vous avez le code généré à partir d'autres fichiers
qui doit être généré avant de pouvoir être
compilé. Les tests doivent être exécutés
automatiquement. Une grande construction prend souvent du temps, vous ne
voulez pas faire toutes ces étapes si vous avez seulement fait un petit
changement. Ainsi, un bon outil de build analyse juste ce qui doit être
changé dans le cadre du processus. La façon courante de le faire
est de vérifier les dates du code source et des fichiers objets et ne
compiler que si le code source est plus ancien. La gestion des
dépendances devient alors compliquée : si on change de fichier
objet ceux qui en dépendent peuvent aussi avoir besoin d'être
reconstruit. Les compilateurs peuvent gérer ce genre de chose, ou
pas. Tout dépend de ce que l'on veut, on peut avoir besoin de
différentes sortes de choses à la construction. Vous pouvez
construire un système avec ou sans code de test, ou à
différents jeux de tests. Certains éléments peuvent
être construits autonome. Un script de build devrait vous permettre de
construire des cibles (target) alternatives pour les différents cas.
Une fois que vous avez passé une ligne de commande simple, des
scripts prennent souvent en charge le reste. Ceux-ci peuvent être des
scripts shell ou utiliser un langage plus sophistiqué de script tel que
Perl ou Python. Mais plus tard il s'avère logique d'utiliser un
environnement conçu pour ce genre de chose, comme le font les outils
« Make » sous Unix.
Dans notre développement PHP nous avons
rapidement découvert que nous avons besoin d'une solution plus
appropriées. Phing est un outil inspiré d'apache Ant et
destiné à PHP. Nous pouvons l'utiliser pour nous assister dans la
réalisation de certaines tâches tout au long du cycle de vie de
nos projets tels que la génération de code, la construction des
releases, la génération de la documentation, la
génération de rapports (tests unitaires, couverture du code,
aspect du code...), le déploiement dans différents
environnements...
II.4.1 Les avantage de Phing
Phing a de nombreux avantages,
comparé à un système de build plus archaïque
construit à partir d'un ensemble de scripts de déploiement
(fichiers PHP, Shell ou batch).
|