Vous êtes sur la page 1sur 86

INTÉGRATION CONTINUE D’UN

PROJET PHP AVEC JENKINS.


http://joind.in/talk/view/2863

Hugo Hamon – Confoo 2011 – Montreal, Canada


Qui suis-je ?

v  Hugo HAMON (@hhamon)

v  Responsable des formations

v  Secrétaire de l’AFUP (2010)

v  Contributeur au projet Symfony

v  Coauteur & contributeur à des ouvrages Eyrolles


Introduction…

« L'intégration continue est un ensemble de


pratiques qui consistent à vérifier à chaque
changement du code source que le résultat des
modifications ne produit pas de régression de
l'application en cours de développement »
Avantages…

Détecter les problèmes le plus tôt possible…


Avantages…

… afin d’alerter l’équipe le plus vite possible !


Avantages…

Générer des compilations régulièrement…


Avantages…

…afin d’obtenir des versions stables et


déployables le plus souvent possible.
Pratiques quotidiennes…

q  Maintenir un dépôt unique de code versionné


q  Tous les développeurs committent quotidiennement
q  Automatiser les compilations (builds)
q  Tout commit doit compiler le tronc du code versionné
q  Maintenir une compilation courte en permanence
q  Rendre disponible le résultat du build à tout le monde
q  Automatiser le déploiement
Workflow de l’Intégration Continue

Alice

Build
Successful
SCM Server
Bob

Carlos
CI Server
Workflow de l’Intégration Continue

Alice

Build Failed

SCM Server
Bob

Carlos Alerter l’équipe CI Server


Workflow de l’Intégration Continue

Alice

Build
Successful
SCM Server
Bob

Carlos
CI Server
Intégration Continue PHP

q  Exécution de la suite de tests unitaires (PHPUnit)


q  Génération du rapport de couverture de code (PHPUnit)
q  Génération de la documentation d’API (PHPDocumentor)
q  Génération du rapport des dépendances (PDepend)
q  Analyse statique du code source (PMD)
q  Détection des violations de codage (PHP_CodeSniffer)
q  Détection du code dupliqué (PHPCPD)
q  Génération du navigateur de code (PHP Code Browser)
Marché de l’Intégration Continue

¨  Maven (Java, Open Source)


¨  CruiseControl (Java, Open Source)
¨  Bamboo (Java, Commercial)
¨  Jenkins (Java, Open Source)
¨  Sonar (Java, Open Source)
¨  Xinc (PHP, Open Source)
Jenkins CI

¨  Hudson rebaptisé Jenkins en février 2011


¨  Ecrit en Java
¨  Exécute des tâches Ant, Maven, Shell et Windows
¨  +300 plugins
¨  Analyse des rapports de compilation
¨  Génération de statistiques et de graphiques (métriques)
Ils utilisent Jenkins CI
Installation

Installation de Jenkins
Installer Jenkins CI

¨  Télécharger le fichier jenkins.war sur jenkins-ci.org


http://mirrors.jenkins-ci.org/war/latest/jenkins.war

¨  Exécuter le fichier jenkins.war


$ java –jar jenkins.war
Installer Jenkins

http://localhost:8080/
Installer les outils PHP

¨  XDebug ¨  PHPUnit 3.5.x

¨  PDepend ¨  PHPCPD

¨  PHP Mess Detector ¨  PHP Documentor

¨  PHP CodeSniffer ¨  PHP CodeBrowser


Installer les outils PHP
$ pecl install xdebug

$ pear channel-discover pear.pdepend.org


$ pear channel-discover pear.phpmd.org
$ pear channel-discover pear.phpunit.de
$ pear channel-discover components.ez.no
$ pear channel-discover pear.symfony-project.com
$ pear channel-discover pear.phing.info

$ pear install phing/phing


$ pear install pdepend/PHP_Depend-beta
$ pear install phpmd/PHP_PMD-alpha
$ pear install phpunit/phpcpd
$ pear install PHPDocumentor
$ pear install PHP_CodeSniffer
$ pear install --alldeps phpunit/PHP_CodeBrowser-alpha
$ pear install --alldeps phpunit/PHPUnit
Installer les plugins Jenkins

¨  Subversion pour l’intégration des dépôts SVN

¨  Git pour l’intégration des dépôts Git

¨  Checkstyle pour l’analyse des rapports PHP_CodeSniffer

¨  Dry pour l’analyser des rapports PHPCPD

¨  HTML Publisher pour la publication des logs de couverture de code

¨  Green Balls pour avoir des billes vertes au lieu des bleues J
Installer les plugins Jenkins

¨  JDepend pour l’analyse des rapports PHP_Depend

¨  PMD pour le traitement des rapports PHP Mess Detector

¨  Violations pour le traitement de rapports variés

¨  xUnit pour le traitement des logs de tests PHPUnit

¨  Clover pour le traitement des logs de couverture de code de PHPUnit


Nouveau projet

Démarrer un nouveau projet


Initialiser un nouveau projet

¨  Création d’un nouveau « projet free-style »


Initialiser un nouveau projet

¨  Ajout d’une description et suppression des anciens builds


Configuration du dépôt SVN

Dépôt de code
Subversion

Dossier local

Préférer les updates


au lieu des checkouts
Configuration du dépôt SVN

¨  Définition des droits d’accès au dépôt de code Subversion.


Configuration du dépôt Git

URL du dépôt de code

Git

Branche à construire

Navigateur de
code source
Configuration du déclenchement

¨  Le build est déclenché toutes les 5 minutes.


¨  Un nouveau build est déclenché si des commits ont eu lieu

Syntaxe de crontab
Exécution et contrôle du build

Build réussi !
Exécution et contrôle du build

¨  La page d’accueil affiche la tendance de chaque projet…


¨  … et l’état du dernier build effectué sur chaque projet.
Phing

Configuration de Phing
Configuration de Phing

¨  Phing est un portage de Ant en PHP


¨  Outil d’automatisation de tâches
¨  Phing exécute des tâches à la suite
¨  Les tâches sont décrites dans un fichier build.xml
¨  Supporte les dépendances entre les tâches
¨  Tâches prédéfinies pour PHPUnit, Code Sniffer, PMD…
Configuration de Phing (build.xml)
<?xml version="1.0" encoding="UTF-8"?>
<project name="Syndication Component" basedir="." default="main"> ${ws} est une
<property name="builddir" value="${ws}/build" /> variable perso
<property name="srcdir" value="${project.basedir}" override="true" />
<property name="package" value="Syndication" override="true" />

<target name="clean" description="Clean the build environment">


<delete dir="${builddir}" />
<delete dir="generatedJUnitFiles" /> Nettoyage
</target>

<target name="prepare" depends="clean" description="Clean the build environment">


<mkdir dir="${builddir}" />
<mkdir dir="${builddir}/logs" />
<mkdir dir="${builddir}/logs/coverage" />
<mkdir dir="${builddir}/docs" /> Préparation
<mkdir dir="${builddir}/browser" />
</target>

<target name="build" depends="prepare" description="Build the project">


<!-- build target commands here -->
</target>
</project> Build
Commande SHELL à exécuter

phing –f $WORKSPACE/build.xml build –Dws=$WORKSPACE


PHPUnit

Configuration des tests unitaires


Configurer la suite de tests unitaires

¨  Configurer et exécuter la suite de tests unitaires

¨  Génération du rapport de la suite au format JUnit

¨  Génération du rapport XML de couverture de code (Clover)

¨  Génération du rapport HTML de couverture de code


PHPUnit – phpunit.xml
<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false" backupStaticAttributes="false"


colors="true" convertErrorsToExceptions="true"
convertNoticesToExceptions="true" convertWarningsToExceptions="true"
processIsolation="true" stopOnFailure="false"
syntaxCheck="false" bootstrap="src/autoload.php">

<testsuites>
<testsuite name="Syndication Component Test Suite">
<directory>./tests/Syndication/</directory>
</testsuite>
</testsuites>

<filter>
<whitelist>
<directory>./src/Syndication/</directory>
</whitelist>
</filter>
</phpunit>
Configurer la suite de tests unitaires
<?xml version="1.0" encoding="UTF-8"?>

<project name="Syndication Component" basedir="." default="main">

<!-- ... -->

<target name="build" depends="prepare" description="Building the project">


<phingcall target="phpunit" />
</target>

<target name="phpunit" description="Running unit tests and coverage analysis">


<exec command="phpunit
--log-junit ${builddir}/logs/phpunit.xml
--coverage-clover ${builddir}/logs/coverage/clover.xml
--coverage-html ${builddir}/logs/coverage/ ${ws}/tests"
/>
</target>

</project>
Configurer la suite de tests unitaires

¨  Analyse des logs JUnit générés par PHPunit

¨  Publication des graphiques sur le tableau de bord


Configurer la couverture de code
¨  Analyse et publication des rapports de couverture de code
Analyse de la couverture de code
Analyse des rapports de tests unitaires

9/9
Analyse des tests unitaires
Publication de la couverture de code
Publication de la couverture de code
PHPDocumentor

Configuration de PHPDocumentor
Générer la documentation d’API

¨  La PHPDoc est générée dans le dossier build/docs.


Générer la documentation d’API
<project name="Syndication Component" basedir="." default="main">
<!-- ... -->

<target name="build" depends="prepare" description="Building the project">


<phingcall target="phpunit" />
<phingcall target="phpdoc" />
</target>

<!-- Generating API Documentation -->


<target name="phpdoc" description="Generating api documentation..." >
<phpdoc title="Syndication API Documentation"
destdir="${builddir}/docs" sourcecode="true"
parseprivate="true" output="HTML:Smarty:PHP">
<fileset dir="./src">
<include name="**/*.php" />
</fileset>
</phpdoc>
</target>
</project>
Publication de la documentation API

Accès à la doc API


Publication de la documentation API
PHPCPD

Configuration de PHPCPD
Rechercher les duplications de code

¨  PHPCPD détecte le code dupliqué dans les fichiers


¨  Le rapport est généré au format PMD
Rechercher les duplications de code
<?xml version="1.0" encoding="UTF-8"?>
<project name="Syndication Component" basedir="." default="main">

<!-- ... -->


<target name="build" depends="prepare" description="Building the project">
<phingcall target="phpunit" />
<phingcall target="phpdoc" />
<phingcall target="phpcpd" />
</target>

<!-- Detecting duplicated code -->


<target name="phpcpd" description="Detecting duplicated code">
<exec command="phpcpd
--min-lines 5
--min-tokens 5
--log-pmd ${builddir}/logs/pmd-cpd.xml src/" />
</target>
</project>
Rechercher les duplications de code
Rechercher les duplications de code
Rechercher les duplications de code
Ce graphique montre que le
code dupliqué a bien été
retiré dans le nouveau
commit qui a donné lieu au
dernier build.

Le graphique ci-contre
montre l’évolution du nombre
de tests unitaires réussis au
dernier build.
PHPDepend

Configuration de PHPDepend
Déterminer les dépendances
¨  PDepend est un portage en PHP de JDepend (Java)
¨  Analyse statistique du code
n  Complexité cyclomatique
n  Qualité globale du code
n  Nombre de classes / méthodes / fonctions / interfaces
n  Nombre d’appels d’une méthode
n  Nombre de propriétés / méthodes publiques vs privées
n  Nombre de lignes de code en commentaires….
Déterminer les dépendances
<?xml version="1.0" encoding="UTF-8"?>
<project name="Syndication Component" basedir="." default="main">

<!-- ... -->


<target name="build" depends="prepare" description="Building the
project">
<phingcall target="phpunit" />
<phingcall target="phpdoc" />
<phingcall target="phpcpd" />
<phingcall target="pdepend" />
</target>

<target name="pdepend" description="Generating JDepend report">


<exec command="pdepend
--jdepend-xml=${builddir}/logs/jdepend.xml src/" />
</target>
</project>
Publier les dépendances
PMD

Configuration de PHP Mess Detector


Analyse statistique du code

¨  PHP Mess Detector est un portage en PHP de PMD (Java)


¨  Analyse statistique du code
¨  Recherche de bugs potentiels
¨  Recherche de code mort (méthodes non appelées par exemple)
¨  Code non optimisé
¨  Expressions trop complexes…
Configurer PHP Mess Detector

Fichier de log généré par PMD


Configurer PHP Mess Detector
<?xml version="1.0" encoding="UTF-8"?>
<project name="Syndication Component" basedir="." default="main">

<!-- ... -->


<target name="build" depends="prepare" description="Building the project">
<phingcall target="phpunit" />
<phingcall target="phpdoc" />
<phingcall target="phpcpd" />
<phingcall target="pdepend" />
<phingcall target="pmd" />
</target>

<target name="phpmd" description="Generating PHP Mess Detector report">


<exec command="phpmd src/ xml codesize,unusedcode --reportfile $
{builddir}/logs/pmd.xml" />
</target>

</project>
Publier les rapports PMD
PHP_CodeSniffer

Configuration de PHP_CodeSniffer
Analyser les violations de codage

¨  Analyse des conventions de codage avec PHP_CodeSniffer

¨  PHPCS « sniffs » le code à la recherche de violations de règles

¨  Nombreuses règles par défaut

¨  Standards prédéfinis : PEAR, Zend, Squiz, PHPCS…

¨  Possibilité d’ajouter des règles et standards supplémentaires


Installation du standard Symfony2
$ # Looking for the PEAR PHP directory
$ pear config-show | grep php_dir

$ # Move to the CodeSniffer standards folder


$ cd /path/to/pear/PHP/CodeSniffer/Standards

$ # Checkout the Symfony2 CodeSniffer standard from Github


$ git clone git://github.com/opensky/Symfony2-coding-standard.git Symfony2

$ # Eventually, set Symfony2 as your default CodeSniffer standard


$ phpcs --config-set default_standard Symfony2
Configuration de PHP_CodeSniffer
<?xml version="1.0" encoding="UTF-8"?>
<project name="Syndication Component" basedir="." default="main">

<!-- ... -->


<target name="build" depends="prepare" description="Building the project">
<phingcall target="phpunit" />
<phingcall target="phpdoc" />
<phingcall target="phpcpd" />
<phingcall target="pdepend" />
<phingcall target="phpmd" />
<phingcall target="checkstyle" />
</target>

<target name="checkstyle" description="Looking for codestyle violations...">


<exec command="phpcs --standard=Symfony2 --report=checkstyle
${project.basedir}/src > ${builddir}/logs/checkstyle.xml"
escape="false" />
</target>

</project>
Publier le rapport des violations
Publier le rapport des violations
PHP Code Browser

Configuration de PHP Code Browser


Générer le navigateur de code

¨  La navigateur est généré dans le dossier build/browser.


Générer le navigateur de code
<?xml version="1.0" encoding="UTF-8"?>
<project name="Syndication Component" basedir="." default="main">
<!-- ... -->
<target name="build" depends="prepare" description="Building the project">
<phingcall target="phpunit" />
<phingcall target="phpdoc" />
<phingcall target="phpcpd" />
<phingcall target="pdepend" />
<phingcall target="phpmd" />
<phingcall target="checkstyle" />
<phingcall target="phpcb" />
</target>

<target name="phpcb" description="Generating code browser...">


<exec command="phpcb
--log ${builddir}/logs
--source ${project.basedir}/src
--output ${builddir}/browser" />
</target>
</project>
Publier le navigateur de code

Accès au navigateur de code


Publier le navigateur de code
Prévenir et guérir au plus vite

Configurer des alertes


Moyens de communication

¨  Emails

¨  Twitter

¨  Jabber

¨  RSS

¨  …
Alerter l’équipe par e-mail

¨  Saisie des adresses email des équipiers du projet

¨  Possibilité d’alerter les responsables d’un build en échec


Industrialisation

Industrialiser l’intégration continue


d’un projet PHP dans Jenkins ?
Industrialiser l’intégration d’un projet

¨  Réutilisation d’un template de projet Jenkins


¨  Dites merci à Sebastian Bergmann !
¨  «  PHP Jenkins Template » project

https://github.com/sebastianbergmann/php-jenkins-template
Pour aller plus loin

Aller plus loin…


Aller plus loin…

¨  Générer des archives PHAR, PEAR, TAR ou ZIP


¨  Automatiser le déploiement des builds stables
¨  Faciliter les audits de code
¨  Intégration avec un bug tracker (Trac, Redmine, Jira)
¨  Exécution de tests Sélénium / Fitness
Merci !
Questions!

Sensio S.A.
92-98, boulevard Victor Hugo
92 115 Clichy Cedex
FRANCE

www.sensiolabs.com - www.symfony.com - trainings.sensiolabs.com

Vous aimerez peut-être aussi