Certains de nos projets sont hébergés sur GitLab plutôt que GitHub, notamment ceux de clients qui disposent déjà d’une instance GitLab interne. GitLab CI fonctionne différemment de GitHub Actions dans sa syntaxe, mais répond au même besoin : automatiser la vérification et le déploiement du code à chaque changement. Voici le pipeline qu’on a construit, pensé pour un projet Bedrock avec des blocs Gutenberg personnalisés.
La structure en étapes (stages)
GitLab CI organise le pipeline en stages exécutés séquentiellement, chaque stage pouvant contenir plusieurs jobs exécutés en parallèle. On sépare volontairement lint, tests, build et déploiement, pour que l’échec d’une étape bloque clairement les suivantes sans ambiguïté :
stages:
- lint
- test
- build
- deploy
variables:
COMPOSER_CACHE_DIR: "$CI_PROJECT_DIR/.composer-cache"
Lint : PHP et JavaScript en parallèle
lint:php:
stage: lint
image: php:8.1-cli
before_script:
- curl -sS https://getcomposer.org/installer | php
- php composer.phar install --no-progress
script:
- vendor/bin/phpcs --standard=WordPress web/app/themes/mon-theme
lint:js:
stage: lint
image: node:18
script:
- npm ci
- npm run lint:js
- npm run lint:css
Ces deux jobs tournent en parallèle car ils appartiennent au même stage et n’ont aucune dépendance déclarée entre eux. Le pipeline attend qu’ils réussissent tous les deux avant de passer au stage suivant.
Tests et build

test:phpunit:
stage: test
image: php:8.1-cli
services:
- mysql:5.7
variables:
MYSQL_DATABASE: wordpress_test
MYSQL_ROOT_PASSWORD: root
script:
- bash bin/install-wp-tests.sh wordpress_test root root mysql
- vendor/bin/phpunit
build:assets:
stage: build
image: node:18
script:
- npm ci
- npm run build
artifacts:
paths:
- web/app/themes/mon-theme/build/
expire_in: 1 hour
Le mot-clé services lance un conteneur MySQL dédié, accessible depuis le job sous le nom d’hôte mysql, indispensable pour les tests PHPUnit qui nécessitent une vraie base de données. Les artifacts du job de build conservent le résultat de la compilation JavaScript pendant une heure, pour que le job de déploiement suivant n’ait pas à recompiler les mêmes fichiers.
Déploiement, avec validation manuelle en production
deploy:staging:
stage: deploy
image: alpine:latest
only:
- develop
before_script:
- apk add --no-cache openssh-client rsync
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | ssh-add -
script:
- rsync -avz --delete web/app/themes/mon-theme/
deploy@staging.exemple.fr:/var/www/site/web/app/themes/mon-theme/
deploy:production:
stage: deploy
image: alpine:latest
only:
- main
when: manual
before_script:
- apk add --no-cache openssh-client rsync
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | ssh-add -
script:
- rsync -avz --delete web/app/themes/mon-theme/
deploy@production.exemple.fr:/var/www/site/web/app/themes/mon-theme/
La ligne when: manual sur le déploiement en production est un choix délibéré : le pipeline vérifie automatiquement tout ce qui peut l’être, mais la bascule finale en production reste un acte volontaire d’un humain, déclenché depuis l’interface GitLab. Le déploiement vers staging, lui, reste entièrement automatique sur chaque push de la branche develop.
Les variables sensibles
La clé SSH_PRIVATE_KEY et les autres secrets sont déclarés dans les paramètres CI/CD du projet GitLab (menu Settings puis CI/CD, section Variables), avec l’option « masquée » activée pour qu’ils n’apparaissent jamais dans les journaux d’exécution, même en cas d’erreur de script qui les afficherait par accident.
| Stage | Rôle | Déclenchement |
|---|---|---|
| lint | Vérifie le style de code PHP et JS | Automatique, à chaque push |
| test | Exécute les tests PHPUnit | Automatique, si lint réussit |
| build | Compile les assets JavaScript et CSS | Automatique, si test réussit |
| deploy | Déploie vers staging ou production | Auto (staging) / manuel (production) |
Le déploiement manuel en production n’est pas un manque de confiance envers le pipeline. C’est la reconnaissance qu’un humain doit choisir le moment de la bascule — après une fenêtre de maintenance annoncée, par exemple — même quand tout le reste est automatisé.
En résumé
Un pipeline GitLab CI bien structuré pour WordPress repose sur une séparation claire des responsabilités entre lint, tests, build et déploiement, avec des artefacts qui évitent le travail redondant entre étapes. Garder le déploiement en production comme geste manuel, tout en automatisant le reste, offre un bon équilibre entre rapidité et contrôle sur les projets les plus sensibles.