vendredi 25 septembre 2026

À propos

Contact

Tests

Hooks pre-commit : lancer PHPCS et les tests avant chaque commit sans ralentir l’équipe

Mettre en place GrumPHP ou Husky pour bloquer un commit non conforme aux standards, en ne vérifiant que les fichiers modifiés pour rester rapide.

Par Clément Hadrot • 17 juin 2021 • 3 min de lecture • Aucun commentaire
Hooks pre-commit : lancer PHPCS et les tests avant chaque commit sans ralentir l'équipe

Après trois commits consécutifs cassant les standards de code sur une même semaine, chacun détecté seulement au moment de la revue de pull request, l’équipe a décidé de déplacer la vérification plus tôt dans le flux : directement avant que le commit ne soit créé, sur le poste du développeur. Le piège classique de cette approche est de vouloir tout vérifier à chaque commit — tests complets compris — et de transformer un geste censé prendre deux secondes en pause café obligatoire de deux minutes.

Deux outils dominent selon la nature du projet : GrumPHP pour un projet essentiellement PHP, Husky quand le projet mélange PHP et JavaScript avec un package.json déjà présent. Les deux reposent sur le même mécanisme natif Git : le hook pre-commit.

Installer GrumPHP sur un projet WordPress

composer require --dev phpro/grumphp

# grumphp.yml
grumphp:
    tasks:
        phpcs:
            standard: WordPress
        phpunit:
            config_file: phpunit.xml

Par défaut, GrumPHP installe automatiquement le hook Git à l’installation de Composer, sans configuration supplémentaire. Chaque git commit déclenche alors les tâches définies.

Ne vérifier que les fichiers modifiés

Le piège le plus courant consiste à lancer PHPCS ou PHPUnit sur l’ensemble du dépôt à chaque commit. Sur un projet de plusieurs centaines de fichiers, cela ralentit chaque commit de plusieurs secondes, voire dizaines de secondes, ce qui pousse rapidement les développeurs à utiliser --no-verify pour contourner le hook. GrumPHP restreint nativement PHPCS aux fichiers modifiés via l’option triggered_by et l’analyse du diff Git :

grumphp:
    tasks:
        phpcs:
            standard: WordPress
            triggered_by: ['php']
        git_commit_message:
            max_body_width: 0
L'essentiel à retenir : Ne vérifier que les fichiers modifiés, jamais tout le dépôt ; GrumPHP pour un projet PHP, Husky pour un projet JS/mixte ; Toujours garder une option d'échappement documentée

Husky pour un projet avec du JavaScript

Sur un thème ou un bloc Gutenberg avec un package.json, Husky couplé à lint-staged offre un équivalent qui ne traite que les fichiers indexés dans le commit en cours :

npx husky init
echo "npx lint-staged" > .husky/pre-commit
{
  "lint-staged": {
    "*.php": ["vendor/bin/phpcs"],
    "*.{js,jsx}": ["eslint --fix"],
    "*.scss": ["stylelint --fix"]
  }
}

lint-staged ne transmet aux linters que les fichiers effectivement modifiés dans le commit, ce qui garde le hook rapide quelle que soit la taille du dépôt.

Toujours documenter une échappatoire

Un hook trop strict qui bloque un commit d’urgence en pleine astreinte produit exactement l’effet inverse de celui recherché : les développeurs prennent l’habitude d’utiliser git commit --no-verify par réflexe, y compris quand ce n’est pas justifié.

La règle adoptée sur nos projets : le hook pre-commit ne vérifie que le style et les erreurs de syntaxe évidentes, jamais la suite de tests complète. Les tests d’intégration restent réservés à la pull request et à l’intégration continue, où le temps d’exécution compte moins.

Que garder pour le pre-commit, que garder pour la CI

  • Pre-commit : PHPCS sur les fichiers modifiés, détection de secrets, validation du message de commit
  • Pre-push (optionnel) : tests unitaires purs, rapides et sans base de données
  • Intégration continue : suite complète de tests d’intégration, PHPStan, analyse de sécurité

En résumé

Un hook pre-commit efficace se limite volontairement à ce qui s’exécute en quelques secondes sur les fichiers réellement modifiés. Le pipeline d’intégration continue, plus lent mais exhaustif, reste le bon endroit pour la suite de tests complète : les deux niveaux se complètent, ils ne se remplacent pas l’un l’autre.

Partager :

À propos de l'auteur

Clément Hadrot

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi