« On dirait que le job dure éternellement pour changer une phrase dans le fichier readme » : cette remarque, glissée dans une discussion d’équipe autour d’une extension de gestion de formations professionnelles, a suffi à déclencher un audit rapide des déclenchements de pipeline sur les quatre dernières semaines. Résultat : quatre pushs sur dix ne touchaient à aucun fichier PHP, seulement de la documentation, des fichiers de configuration d’éditeur ou des images.
Chacun de ces pushs déclenchait pourtant la suite PHPUnit complète, avec son installation d’environnement, sa base de données de test et ses centaines d’assertions, pour un gain d’information nul : aucun de ces fichiers n’affecte le comportement testé. Le filtrage en amont du déclenchement, avant même de démarrer un job, corrige ce gaspillage sans toucher à la parallélisation de la suite elle-même.
Ce que l’API GitHub expose avant le job
Un événement de push contient, dans sa charge utile, la liste des commits inclus. Chaque commit référence les fichiers ajoutés, modifiés et supprimés. Un workflow GitHub Actions peut interroger cette information très tôt, avant de lancer l’installation de l’environnement de test, grâce à une étape dédiée qui compare les fichiers modifiés à un motif défini.
jobs:
filtrer-changements:
runs-on: ubuntu-latest
outputs:
php_modifie: ${{ steps.filtre.outputs.php_modifie }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2
- id: filtre
run: |
FICHIERS=$(git diff --name-only HEAD^ HEAD)
if echo "$FICHIERS" | grep -qE '\.php$'; then
echo "php_modifie=true" >> "$GITHUB_OUTPUT"
else
echo "php_modifie=false" >> "$GITHUB_OUTPUT"
fi
Conditionner le job PHPUnit à ce résultat

Le job qui lance la suite de tests dépend ensuite de ce premier job, et ne se déclenche que si la sortie php_modifie vaut true :
tests-phpunit:
needs: filtrer-changements
if: needs.filtrer-changements.outputs.php_modifie == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Installer PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
- run: composer install --no-progress
- run: vendor/bin/phpunit
GitHub Actions marque ce job comme ignoré plutôt que comme échoué lorsqu’il n’est pas déclenché, ce qui n’affecte pas les règles de protection de branche configurées pour exiger sa réussite.
Le cas des fichiers indirects
Un premier filtrage naïf, limité à l’extension .php, avait laissé passer un incident : un push modifiant uniquement composer.json pour changer une contrainte de version de dépendance n’était plus testé, alors qu’il pouvait casser la compatibilité. Le motif de filtrage a été élargi pour inclure également composer.json, composer.lock et les fichiers de configuration PHPUnit eux-mêmes.
Adapter le filtre aux dossiers du projet
Un motif purement basé sur l’extension reste parfois trop large ou trop étroit selon la structure du dépôt. Pour un projet qui sépare clairement son code applicatif de sa documentation dans des dossiers distincts, un filtrage par chemin complète utilement le filtrage par extension :
- Exclure explicitement le dossier
docs/et les fichiers*.md, même s’ils contiennent occasionnellement des blocs de code PHP en exemple. - Inclure systématiquement tout changement touchant aux fichiers de configuration de build ou de dépendances.
- Revoir le motif à chaque incident constaté, plutôt que de le considérer figé une fois écrit.
Une CI qui s’exécute pour de mauvaises raisons coûte aussi cher qu’une CI qui ne s’exécute pas assez.
En résumé
Filtrer les fichiers modifiés avant de déclencher la suite PHPUnit complète élimine une part significative des exécutions inutiles, sans nécessiter de toucher à la parallélisation ou à la structure des tests eux-mêmes. Sur ce projet de formations professionnelles, quatre pushs sur dix ne concernaient aucun fichier PHP : les ignorer a rendu le budget de minutes de CI disponible pour les changements qui en avaient réellement besoin.