Husky : intégration continue et équipes
Désactiver Husky en intégration continue
Section intitulée « Désactiver Husky en intégration continue »En CI, les hooks sont inutiles (la CI exécute elle-même les contrôles) et peuvent même gêner (modification du dépôt, installation de scripts). Trois approches :
HUSKY=0 npm ci # variable d'environnement : Husky ne s'active pasnpm ci --ignore-scripts # n'exécute aucun script d'installationOu rendre le script prepare tolérant :
{ "scripts": { "prepare": "husky || true" }}|| true évite l’échec de npm ci quand Husky n’est pas disponible (installation de production sans dépendances de développement) :
npm ci --omit=dev # Husky (devDependency) absent : prepare ne doit pas échouerDans un workflow Gitea Actions :
jobs: qualite: runs-on: ubuntu-latest env: HUSKY: '0' steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 24 cache: npm - run: npm ci - run: npm run lint && npm run format:check && npm testVoir Gitea Actions : écrire un workflow.
Refaire en CI les contrôles des hooks
Section intitulée « Refaire en CI les contrôles des hooks »Les hooks locaux se contournent : la CI doit refaire les mêmes contrôles, de façon obligatoire.
| Contrôle du hook | Équivalent en CI |
|---|---|
pre-commit : lint-staged |
npm run lint et npm run format:check sur tout le projet |
commit-msg : commitlint |
npx commitlint --from origin/main --to HEAD |
pre-push : tests |
npm test (avec couverture) |
- run: npx commitlint --from "origin/${{ gitea.base_ref }}" --to HEAD --verbose if: gitea.event_name == 'pull_request'La checkout par défaut est superficielle : ajouter fetch-depth: 0 à actions/checkout pour disposer de l’historique nécessaire à commitlint --from.
Équipes : tout le monde a les mêmes hooks
Section intitulée « Équipes : tout le monde a les mêmes hooks »| Pratique | Raison |
|---|---|
Versionner .husky/ et les configurations (lint-staged, commitlint, ESLint, Prettier) |
Mêmes règles pour tous |
Script prepare |
Active les hooks à l’installation, sans geste manuel |
Épingler les versions (package-lock.json) |
Mêmes résultats d’un poste à l’autre |
Documenter dans README ou CONTRIBUTING |
Une phrase : « les hooks s’installent avec npm install » |
| Garder les hooks rapides | Sinon, contournement par habitude |
| Refaire les contrôles en CI | Filet de sécurité |
Extrait de CONTRIBUTING.md :
## Avant de contribuer
1. `npm install` : installe les dépendances et active les hooks Git (Husky).2. Les commits suivent Conventional Commits (`feat(portée): description`).3. Avant chaque commit, le code est formaté et analysé automatiquement.4. Avant chaque envoi, les tests sont exécutés.Monorepo ou dépôt dans un sous-dossier
Section intitulée « Monorepo ou dépôt dans un sous-dossier »Quand package.json n’est pas à la racine du dépôt Git :
{ "scripts": { "prepare": "cd .. && husky frontend/.husky" }}Husky doit être exécuté depuis la racine du dépôt (là où se trouve .git) en indiquant le dossier des hooks (frontend/.husky). Les commandes du hook s’exécutent alors depuis la racine : se déplacer dans le sous-dossier si nécessaire :
cd frontendnpx lint-stagedPour un monorepo géré par un espace de travail (pnpm, npm workspaces), installer Husky à la racine et configurer lint-staged par motif de chemin.
Machines des développeurs : Node.js et PATH
Section intitulée « Machines des développeurs : Node.js et PATH »Les clients Git graphiques lancent les hooks sans charger le profil du shell : Node.js installé par nvm n’est alors pas trouvé. Créer ~/.config/husky/init.sh (exécuté avant chaque hook) :
export NVM_DIR="$HOME/.nvm"[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"Voir Node.js : gérer les versions.
Hooks et sécurité
Section intitulée « Hooks et sécurité »- Un hook est un script exécuté sur la machine de chaque contributeur : une modification malveillante de
.husky/s’exécuterait chez tous au prochain commit. Relire les changements de.husky/en revue de code. - Ne pas mettre de secrets dans les hooks.
- Ne pas faire d’appels réseau dans les hooks (lenteur, dépendance à la connexion).
- Les dépôts clonés depuis une source inconnue ne devraient pas être installés sans relecture (le script
prepares’exécute ànpm install).
Retour d’expérience : gérer les contournements
Section intitulée « Retour d’expérience : gérer les contournements »| Constat | Réponse |
|---|---|
--no-verify fréquent |
Hook trop lent ou instable : l’alléger |
| Hooks ignorés par une partie de l’équipe | Documenter, vérifier en CI |
| Messages refusés pour des détails | Assouplir les règles (avertissement plutôt qu’erreur), documenter la convention |
| Formatage qui modifie beaucoup de fichiers | Formater tout le projet en un commit dédié, puis laisser lint-staged maintenir |
Dépannage
Section intitulée « Dépannage »| Symptôme | Piste |
|---|---|
npm ci échoue en CI avec husky: not found |
HUSKY=0, --ignore-scripts, ou "prepare": "husky || true" |
.git can't be found |
husky lancé hors de la racine du dépôt : cd .. && husky dossier/.husky |
commitlint --from : fatal: bad revision |
fetch-depth: 0 dans actions/checkout |
| Les hooks ne se lancent pas chez un collègue | npm install non exécuté, ou core.hooksPath modifié localement |
| Les hooks modifient des fichiers en CI | HUSKY=0 |
| Conflit avec un autre outil de hooks | Un seul outil à la fois : vérifier git config core.hooksPath |
Ubuntu 24.04 et 26.04 : différences à connaître
Section intitulée « Ubuntu 24.04 et 26.04 : différences à connaître »Aucune propre à Ubuntu. Sur les runners de CI sous Ubuntu, Node.js et Git doivent être disponibles pour npm ci (voir Gitea : Actions (CI)).