Mettre en place une CI/CD avec Slim Framework (PHP)
Objectif
Mettre en place une CI/CD très simple pour une application PHP utilisant le framework SLIM.
Pré-requis
Pour mettre en place une CI/CD simple, nous devons posséder :
- un dépôt GitLab,
- un clone de votre dépôt en local sur votre poste,
- un GitLab Runner, lien vers l'article,
- un hébergement avec un accès SFTP.
Pour ma part, j'utilise un dépôt sur Froggit. Si vous souhaitez plus d'informations sur Froggit, je vous invite à consulter ce lien.
Votre dépôt doit contenir uniquement un fichier README.md.
Tutoriel
Le projet Git de cet article est disponible sur Froggit, lien vers le dépôt.
Création du runner SSH
Pour se connecter au serveur distant, le runner SSH utilise, soit le mot de passe, soit la clé SSH. Il est préférable d'utiliser la clé SSH car le mot de passe n'est pas crypté lorsqu'il est enregistré dans le fichier de configuration du GitLab Runner.
Voici la marche à suivre pour créer une clé SSH : ssh-keygen -t ed25519 -C "comment"
.
Une fois la clé générée, il faut l'envoyer sur le serveur distant en lançant : ssh-copy-id -i ~/.ssh/mykey user@host
.
Procéder ensuite à la création d'un nouveau runner via la commande : gitlab-runner register
. Mon GitLab Runner SSH n'est pas créé dans le groupe où se trouve le dépôt, il est créé dans le projet GitLab.
Pour utiliser votre runner SSH, il faut installer Git sur le serveur où se connectera le runner.
Création du fichier .gitlab-ci.yml
Notre pipeline sera composé de 2 jobs, un premier utilisant un runner Docker
avec l'image php:8.0.1-fpm-buster
pour tester notre code PHP. Nous indiquons le runner à utiliser en précisant le tag. Le second job utilisera le runner SSH
pour déployer notre code sur notre serveur.
Commençons par tester que nos 2 runners fonctionne correctement, pour cela, créer le fichier .gitlab-ci.yml
à la racine du projet, insérer le contenu ci-dessous dans le fichier et envoyer le sur le serveur via un git push
.
stages:
- test
- deploy
docker:test:
stage: test
tags:
- docker
image: php:8.0.1-fpm-buster
before_script:
- echo "Before Script"
script:
- echo "Script"
ssh:deploy:
stage: deploy
needs:
- docker:test
tags:
- ssh
script:
- echo "Script"
Il est possible que votre runner SSH vous renvoie l'erreur suivante : ERROR: Job failed (system failure): prepare environment: Process exited with status 1. Check https://docs.gitlab.com/runner/shells/index.html#shell-profile-loading for more information
. Pour corriger cela, il faut, sur le serveur distant, commenter les lignes ci-dessous du fichier .bash_logout
de l'utilisateur utilisé par le runner SSH.
if [ "$SHLVL" = 1 ]; then
[ -x /usr/bin/clear_console ] && /usr/bin/clear_console -q
fi
Une fois le pipeline exécuté avec succès, nous allons créer l'environnement de développement Docker.
Création du projet Docker
L'environnement de développement est très simple. Tout d'abord, nous allons créer un fichier .env
à la racine du projet. Ceci est nécessaire pour Docker Compose. Le contenu du fichier est le suivant :
COMPOSE_PROJECT_NAME=basecicddockerforslimframework
Je ne vais pas vous détailler la partie Docker dans cet article, je vous invite à télécharger le contenu du projet Base CI/CD & Docker for Slim Framework présent sur Froggit.
Une fois le projet cloné, vous trouverez 2 dossiers bin
et docker
. Le dossier bin
contient quelques commandes utiles. Par exemple :
- Pour construire les images Docker :
./bin/docker build
- Pour lancer les conteneurs Docker :
./bin/docker up -d
- Pour installer un paquet via Composer :
./bin/composer require ...
Ce dossier peut contenir autant de commandes que vous le souhaitez.
Dès que les conteneurs sont lancés, vous pouvez passer à la création du projet PHP.
Création du projet PHP
L'installation de Slim PHP est très simple, il suffit de suivre leur documentation. Voici les commandes à lancer depuis la racine du projet :
./bin/composer require slim/slim:"4.*"
./bin/composer require slim/psr7
./bin/composer require nyholm/psr7 nyholm/psr7-server
./bin/composer require guzzlehttp/psr7 http-interop/http-factory-guzzle
./bin/composer require laminas/laminas-diactoros
Terminer la création du projet en créant le dossier public
et intégrant le contenu suivant dans le fichier public/index.php
:
<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
require __DIR__ . '/../vendor/autoload.php';
$app = AppFactory::create();
$app->get('/', function (Request $request, Response $response, $args) {
$response->getBody()->write("Hello world!");
return $response;
});
$app->run();
Je vous invite à vérifier que tout fonctionne en ouvrant la page http://localhost:8000
dans votre navigateur.
Installation & Paramétrage de PHPUnit 9
L'installation de PHPUnit est réalisée facilement en lançant la commande : ./bin/composer require --dev phpunit/phpunit
. Le paramétrage nécessite quelques interventions.
Commençons par ajouter .phpunit.result.cache
au fichier .gitignore
. Puis créer le dossier app
à la racine du projet et ajouter le contenu suivant dans le fichier composer.json
au même niveau que require
et require-dev
. :
"autoload": {
"classmap": [
"app/"
]
},
Lancer ensuite la commande : ./bin/composer dump-autoload
pour générer les fichiers d'autoload. Voici un lien vers Grafikart pour quelques précisions supplémentaires.
À la racine du projet, nous allons créer le fichier phpunit.xml
avec le contenu suivant :
<phpunit bootstrap="vendor/autoload.php">
<testsuites>
<testsuite name="baseTests">
<directory>tests</directory>
</testsuite>
</testsuites>
</phpunit>
Ce fichier nous servira à mieux organiser les tests unitaires.
En lançant la commande ./bin/phpunit
, le résultat affiché doit être :
PHPUnit 9.5.2 by Sebastian Bergmann and contributors.
No tests executed!
Terminons cette partie en mettant à jour notre Ci dans le fichier .gitlab-ci.yml
. Remplacer toute la partie docker:test
par :
docker:test:
stage: test
tags:
- docker
image: php:8.0.1-fpm-buster
before_script:
- apt-get update -yqq
- apt-get install -yqq zip curl unzip libzip-dev libxml2-dev libonig-dev
# Install PHP extensions
- docker-php-ext-install dom mysqli xml zip
# Install and run Composer
- curl -sS https://getcomposer.org/installer | php
- php composer.phar install --ignore-platform-reqs
script:
- php vendor/bin/phpunit --configuration phpunit.xml
Avant de passer à l'étape suivante, nous devons tester notre CI en réalisant un push dans le projet Git.
Mise en place de la CD
Pour le déploiement de l'application, je dispose d'un conteneur LXC sous Debian dans lequel j'ai installé Git, Nginx, PHP-FPM ainsi que les extensions PHP, sans oublier Composer, que nous avons utilisé dans notre application.
Au sein du serveur distant, créons un dossier app
dans /var/www/html/app
. Dans ce dernier, nous allons cloner le dépôt du projet. Dès que le projet a été cloné, nous pouvons modifier le fichier .gitlab-ci.yml
pour remplacer le contenu du job ssh:deploy
par celui-ci :
ssh:deploy:
stage: deploy
needs:
- docker:test
tags:
- ssh
only:
refs:
- master
script:
- cd /var/www/html/app
- git fetch origin
- git checkout master
- git pull
- composer install
Dans ce job, nous précisons que le runner ayant le tag ssh
exécutera le script dès que le job docker:test
est finalisé et uniquement si le git push
a été réalisé sur la branche master
.
Vous pouvez push vos modifications sur le dépôt du projet et contrôler que le déploiement fonctionne.