05.06 — Husky + lint-staged + commitlint + commitizen#
Discipline de commits stricte. Conventionnels, signés, format-checkés.
Outils#
| Outil | Rôle |
|---|---|
| Husky | Installe les hooks Git locaux (pre-commit, commit-msg) |
| lint-staged | Lance des outils seulement sur les fichiers staged |
| commitlint | Vérifie que le message de commit suit la convention |
| commitizen + cz-commitlint | CLI interactive pour composer un message conforme |
Config#
.husky/#
Dossier contenant les hook scripts :
.husky/
├── pre-commit
└── commit-msgpre-commit :
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
pnpm exec lint-stagedcommit-msg :
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
pnpm exec commitlint --edit "$1".lintstagedrc.cjs#
module.exports = {
"*.{js,ts,jsx,tsx,json,md,mdx,html,css,scss,yml,yaml}": ["prettier --write"],
};→ Sur chaque fichier staged : prettier --write. Si Prettier modifie, les modifications sont automatiquement rattachées au commit.
.commitlintrc.cjs#
module.exports = { extends: ["@commitlint/config-conventional"] };→ Hérite de @commitlint/config-conventional :
<type>(<scope>): <subject>
<body>
<footer>Types acceptés : feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert.
.czrc#
{ "path": "@commitlint/cz-commitlint" }→ Indique à commitizen d’utiliser @commitlint/cz-commitlint comme adapter. La commande pnpm commit lance la CLI interactive.
Chaîne de commit#
1. Développeur : git add foo.tsx
↓
2. Développeur : pnpm commit
↓
3. commitizen (cz-commitlint) ouvre une CLI interactive :
? Select the type of change: feat
? What is the scope (optional): dashboard
? Write a short, imperative tense description: add OTP screen
? Provide a longer description: ...
? Are there any breaking changes? no
? Issues this commit closes: -
↓
4. Le message est validé localement contre la config conventional
↓
5. git-cz appelle `git commit` avec le message construit
↓
6. .husky/pre-commit s'exécute :
lint-staged → prettier --write sur les fichiers staged
↓
7. .husky/commit-msg s'exécute :
commitlint --edit COMMIT_EDITMSG
→ vérifie une dernière fois (au cas où l'utilisateur a fait git commit -m direct)
↓
8. Si tout passe : commit crééPipeline alternatif : git commit -m "..."#
Si le développeur shortcut via git commit -m "fix some bug" (sans utiliser pnpm commit) :
pre-commitlancelint-staged(prettier sur les staged).commit-msglancecommitlint --edit "$1".- « fix: some bug » serait OK. « stuff » serait rejeté.
Donc : on peut shortcut, mais le commitlint impose la convention quand même.
is-ci || husky dans prepare#
"scripts": {
"prepare": "is-ci || husky"
}→ Le script prepare est exécuté automatiquement par pnpm install (ou npm install).
- Si on est en CI (
is-ciretournetrue),||court-circuite, husky n’est pas installé. - Si on est en local,
is-ciretournefalse,huskyest installé (= les hooks.husky/*sont enregistrés dans.git/hooks/*).
Discipline#
| Bénéfice | Détail |
|---|---|
| Historique git lisible | git log --oneline donne feat(dashboard): add OTP screen, exploitable par gh release (changelog) |
| Pas de PR avec format cassé | Prettier auto-applique sur staged, on ne commit jamais du code non-formaté |
| Plus de discussion sur le format en revue | Le format est décidé par Prettier, pas par la revue |
Format vs contenu#
Le pre-commit lint-staged applique Prettier mais n’applique pas ESLint.
- Prettier corrige le format sans changer la sémantique. Auto-safe.
- ESLint peut détecter des erreurs sémantiques (unused var, missing dep dans
useEffect). Si on le lançait en pre-commit, il pourrait bloquer le commit pour quelque chose qui mérite d’être discuté en revue.
→ Le lint est laissé pour la CI (wireit lint). Le format est immédiat.
Pourquoi l’Igoristan a tout ça pour un projet « démo »#
Pour avoir l’approbation de Napoléon.