Chaîne d'intégration continue pour les applications Symfony

Chez Les-Tilleuls.coop, la plupart de nos applications sont basées sur les mêmes procédures :

  • Le langage PHP avec les frameworks Symfony et Doctrine pour le développement back
  • CoffeeScript, Javascript, AngularJS ou encore Twitter Bootstrap pour le développement front (Grunt comme système de construction, Yeoman pour le "scaffolding", Karma et Jasmine pour les tests).
  • Des dépôts de Git privés (hébergés sur Github)
  • Des librairies privées et des bundles partagés entre les applications et exposés comme des packages Composer
  • Des tests unitaires PHPSpec
  • Doctrine Data Fixtures (avec Alice et Faker)
  • Des scenarii Behat
  • De la PHPdoc exhaustive
  • Des scripts Capifony pour le déploiement

Nous avons construit un système d'intégration continue permettant la réalisation d'applications Symfony de haute qualité. Dans ce tutoriel, vous allez découvrir son fonctionnement et comment le mettre en place étape par étape. Si vous n'en utilisiez pas auparavant, cela va augmenter drastiquement la qualité de vos projets Symfony mais également les performances de vos développeurs.

Notre système de chaîne d'intégration continue repose essentiellement sur Jenkins. A chaque commit il :

  • met à jour notre package Composer
  • exécute tous les tests et scenarios, y compris les tests "web acceptance"
  • vérifie la qualité du code : sécurité, code mort, duplication de code, l'analyse de la complexité cyclomatique, structuration et le respect des bonnes pratiques du framework Symfony
  • génération d'une documentation de l'API
  • déploiement continu de la nouvelle version de l'application

Les feature branches dans lesquelles les nouvelles fonctionnalités sont développées sont relues puis mergées dans master par un lead dev via des Pull Requests GitHub lorsque tous les tests et vérifications sont au vert.

Le tutoriel suivant peut être suivi sur Debian (Wheezy) et Ubuntu.

Installer Jenkins

L'équipe Jenkins maintient un dépôt Debian fournissant des packages binaires mis à jour. Installez-le sur votre serveur accueillant la chaîne d'intégration continue :

# wget -q -O - http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key | apt-key add -
# echo "deb http://pkg.jenkins-ci.org/debian binary/" >> /etc/apt/sources.list
# apt-get update
# apt-get install jenkins

Sécuriser l'installation

Si tout c'est bien passé, l'interface utilisateur de Jenkins est désormais disponible sur le port 8080 de votre serveur d'intégration continue.

Dès lors, toute personne connaissant l'URL de votre installation Jenkins peut en prendre le contrôle. Il est judicieux de sécuriser l'accès à la chaîne d'intégration continue.

  • Allez dans "Manage Jenkins" puis dans "Setup Security"
  • Allez dans "Enable Security"
  • Dans la section "Security Realm", sélectionnez comme système d'utilisateur “Jenkins’ own user database” (si vous disposez d'un annuaire LDAP ou d'un autre système de gestion centralisé des utilisateurs pour votre organisation, vous pouvez également l'utiliser)
  • N'oubliez pas de cocher "Allow users to sign up", c'est obligatoire si vous souhaitez être en mesure de vous connecter après l'activation de la sécurité
  • Dans la partie "Autorization", choississez "Project-based Matrix Authorisation Strategy", laissez les cases "Anonymous" non remplies et créez un un admin ayant tous les droits
  • Activez la protection CSRF en cochant "Prevent Cross Site Request Forgery exploits"
  • Sauvegardez et retournez à l'accueil
  • Cliquez sur "Sign Up" et créez un compte avec le même nom d'utilisateur à qui vous aviez donné les droits d'administration

Jenkins est maintenant sécurisé. Retournez dans les paramètres de sécurité pour désactiver le formulaire d'inscription.

Connecter Jenkins aux dépôts Github

Jenkins doit être en mesure de récupérer les codes sources à partir de vos dépôts Github privés. Le meilleur moyen que nous ayons trouvé est de créer un Github Machine User capable de se connecter aux dépôts privés. Vous pouvez ajouter des utilisateurs ayant uniquement la possibilité de lecture de vos dépôts de Github en cliquant dans "Settings" puis "Collaborators". Pour des raisons de sécurité, rappelez-vous de donner uniquement la permission de lecture à l'utilisateur de la machine.

Maintenant, nous allons créer des clés SSH privées et publiques pour le compte UNIX dont se sert Jenkins (sur Debian, il est nommé jenkins):

# su jenkins # Switch to the jenkins user
$ ssh-keygen -t rsa # Generate SSH keys

La dernière étape consiste à ajouter la clé publique au compte Github de l'utilisateur de la machine. A partir de la page d'accueil de Github, connectez-vous en tant qu'utilisateur de la machine, allez dans "Setting" puis dans "SSH Keys". Ajoutez ensuite une nouvelle clé avec ce contenu :

/var/lib/jenkins/.ssh/id_rsa.pub

Jenkins est maintenant capable de se connecter à nos dépôts Github.

Installer PHP

Le langage PHP est requis pour mener à bien nos tests et les autres outils tels que Composer et Satis. Installez-le.

apt-get install php5-cli php5-apc php5-sqlite

Remarquerez que nous avons également installé APC pour accélérer l'exécution des scripts.

Installer Satis

Satis est le dépôt Composer le plus populaire et le seul qui soit Open Source.  Cet outil crée un index Composer statique. Plus tard, nous ajouterons une tâche dans Jenkins pour reconstruire le dépôt à chaque commit. Cela nous permettra d'avoir toujours une mise à jour des dépôts du package Composer. Pour cela, nous devons installer Satis et l'utilisateur de Jenkins doit être capable de s'en servir. 

Satis doit être installé à partir de Composer. Passez à l'utilisateur Jenkins, installez Composer, puis Satis.

# su jenkins
$ cd ~
$ curl -sS https://getcomposer.org/installer | php
$ php composer.phar create-project composer/satis --stability=dev

Ensuite, créez un fichier de configuration pour Satis appelé packages.json :

{
    "name": "Your repository name",
    "homepage": "http://packages.example.com/",
    "repositories": [
        { "type": "vcs", "url": "git@github.com:coopTilleuls/repo1.git" },
        { "type": "vcs", "url": "git@github.com:coopTilleuls/repo2.git" }
    ],
    "require-all": true
}

Ce fichier de configuration permettra d'avoir deux packages Composer privés (repo1 et repo2). Grâce aux clés SSH configurées ultérieurement, l'utilisateur de jenkins pourra se connecter à nos dépôts Github privés. Bien sûr, ces dépôts doivent avoir à leur racine un fichier composer.json

Toutes les options de configuration de Satis se trouvent sur le site de Composer.

Dans un premier temps, générez le package manuellement :

satis/bin/satis --no-interaction build /var/www/packages.json packages

La prochaine étape est d'exposer nos packages vers HTTP. Pour cela, nous utiliserons nginx. Revenez à la racine Ctrl + d et tapez :

# apt-get install nginx

Ensuite, modifiez ce contenu /etc/nginx/sites-enabled/default par celui ci :

server {
        root /var/lib/jenkins/packages;
        index index.html;

        location / {
                try_files $uri $uri/ /index.html;
                allow <my-ip>;
                deny all;
        }
}

N'oubliez pas de remplacer <my-ip> par la liste des adresses IP autorisées à avoir accès aux dépôts. Cela vous empêchera la mauvaise surprise de découvrir que vos dépôts privés sont exposés à tout l'internet.

Redémarrez nginx :

# /etc/init.d/nginx restart

Vous devriez être en mesure de parcourir les dépôts avec votre navigateur Web favori.

Autoriser Git et support de GitHub

Le support de Git et de GitHub existent sous forme de plugins Jenkins. Allez dans "Manage Jenkins" puis "Manage Plugins" et installez les plugins nommés "Git Plugin" et "GitHub Plugin". Leur appellation est explicite.

Ensuite, nous allons configurer un Webhook GitHub afin de déclencher un build à chaque fois qu'un commit est poussé, dans n'importe quelle branche.

Allez dans vos dépôts GitHub, cliquez sur "Settings" puis "Webhooks & Services". Cliquez sur la boîte de sélection "Add service" et choisissez "Jenkins (GitHub plugin)".

Dans la boîte, entrez le point de terminaison de votre Webhook Jenkins. Il devrait s'agir de quelque chose comme http://ci.les-tilleuls.coop:8080/github-webhook/ (remplacez juste la partie domaine de l'URL). Cliquez sur "Add service".

Le Webhook est en place ! Jenkins sera notifié à chaque fois que nous poussons du code dans notre dépôt GitHub. Répétez cette étape à chaque fois que vous souhaitez qu'un dépôt Github déclenche des builds.

Installer PHP CS Fixer

PHP CS Fixer est un excellent outil libre développé par SensioLabs. Sa version 1.0 est sortie il y a peu. Il trouve et corrige automatiquement les violations des normes de codage PSR-0, PSR-1, PSR-2 et Symfony. Avec son option --dry-run, il peut être utilisé dans notre chaîne d'intégration continue pour vérifier que le code produit est propre.

PHP CS Fixer est conditionné en tant qu'archive PHAR. Installons-le :

# su jenkins # Switch to the jenkins user
$ cd # Change to the home directory of the jenkins user
$ wget http://get.sensiolabs.org/php-cs-fixer.phar # Download PHP CS Fixer

Installer phpDocumentator

Test d'acceptation avec Behat et PhantomJS