Intégration continue des projets PHP avec Jenkins

Preview:

Citation preview

INTÉGRATION CONTINUE D’UN PROJET PHP AVEC JENKINS.

Hugo Hamon – Confoo 2011 – Montreal, Canada

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

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éri"er à chaque changement du code source que le résultat des modi"cations 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…

… a"n d’alerter l’équipe le plus vite possible !

Avantages…

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

Avantages…

…a"n 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

Bob

Carlos

SCM Server

CI Server

Build Successful

Workflow de l’Intégration Continue

Alice

Bob

Carlos

SCM Server

CI Server

Build Failed

Alerter l’équipe

Workflow de l’Intégration Continue

Alice

Bob

Carlos

SCM Server

CI Server

Build Successful

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 "chier jenkins.war sur jenkins-ci.org

¨  Exécuter le "chier jenkins.war

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

$ java –jar jenkins.war

Installer Jenkins

http://localhost:8080/

Installer les outils PHP

¨  XDebug

¨  PDepend

¨  PHP Mess Detector

¨  PHP CodeSniffer

¨  PHPUnit 3.5.x

¨  PHPCPD

¨  PHP Documentor

¨  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

Subversion Dépôt de code

Dossier local

Préférer les updates au lieu des checkouts

Configuration du dépôt SVN

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

Configuration du dépôt Git

Git

URL du dépôt de code

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

Con"guration 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 "chier build.xml

¨  Supporte les dépendances entre les tâches

¨  Tâches prédé"nies pour PHPUnit, Code Sniffer, PMD…

Configuration de Phing (build.xml) <?xml version="1.0" encoding="UTF-8"?> <project name="Syndication Component" basedir="." default="main"> <property name="builddir" value="${ws}/build" /> <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" /> </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" /> <mkdir dir="${builddir}/browser" /> </target> <target name="build" depends="prepare" description="Build the project"> <!-- build target commands here --> </target> </project>

Nettoyage

Préparation

Build

${ws} est une variable perso

Commande SHELL à exécuter

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

PHPUnit

Con"guration des tests unitaires

Configurer la suite de tests unitaires

¨  Con"gurer 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

Con"guration 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

Con"guration de PHPCPD

Rechercher les duplications de code

¨  PHPCPD détecte le code dupliqué dans les "chiers

¨  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

Con"guration 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

Con"guration 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

Con"guration 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é"nis : 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

Con"guration 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

Con"gurer 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 !

Sensio S.A. 92-98, boulevard Victor Hugo

92 115 Clichy Cedex FRANCE

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

Questions!