Hooks et règles¶
Les hooks¶
| Hook | Rôle |
|---|---|
post-checkout |
Avertit dès qu'on arrive sur une branche mal nommée (non bloquant) |
pre-commit |
Refuse les branches mal nommées, bloque les commits directs sur les branches protégées (main/master par défaut), détecte les secrets, formate uniquement le contenu stagé (le travail non stagé est préservé), signale les fonctions ajoutées sans commentaire |
prepare-commit-msg |
Préfixe le message d'après la branche : sur feat/bean, git commit -m "ajoute X" → feat(bean): ajoute X |
commit-msg |
Impose Conventional Commits, 72 caractères maximum |
pre-push |
Refuse les branches mal nommées et le push direct sur les branches protégées (protectedBranches, création initiale permise), et les messages des commits poussés (même règle que la CI, git rebase -i proposé pour corriger) ; lint (shellcheck pour les scripts shell, actionlint pour les workflows GitHub) puis build et tests du commit poussé, seulement pour les projets touchés (succès : une ligne de résumé par projet ; échec : sortie complète) |
post-merge |
Après un git pull : supprime les branches locales mergées (classique ou squash) dont la branche distante a été supprimée ; jamais une branche contenant du travail non intégré |
Contournement ponctuel : git commit --no-verify, git push --no-verify — la CI refait les vérifications.
Secrets au pre-commit¶
Avec gitleaks installé, le contenu stagé est analysé avant chaque commit. Un secret trouvé refuse le commit et dit où il est, sans jamais afficher sa valeur :
✖ Secret détecté : commit refusé.
config/app.ini:3 (github-pat)
Que faire :
1. Retirer la valeur du fichier (variable d'environnement, fichier ignoré), puis recommencer le commit.
2. Fichier qui ne doit jamais être versionné : l'ajouter à .gitignore, puis git rm --cached <fichier>.
3. Clé qui a pu fuir ailleurs (déjà poussée, partagée) : la révoquer chez son fournisseur.
Faux positif : ajouter son empreinte à .gitleaksignore :
config/app.ini:github-pat:3
gitleaks en panne (configuration invalide, version incompatible) refuse aussi le commit, avec son message d'erreur : la détection n'a pas été faite, ce n'est jamais présenté comme une fuite. Sans gitleaks, le commit passe avec un avertissement : la vérification secrets de la CI fera le contrôle, et la commande d'installation est donnée (aussi proposée en étape suivante par repowarden statut). Désactiver pour un dépôt : git config repowarden.skip secrets.
Fichier sensible ni suivi ni ignoré¶
gitleaks ne lit un fichier qu'une fois indexé. Avant, un fichier non suivi au nom sensible, absent de .gitignore (et de .git/info/exclude), est signalé à chaque commit et par repowarden statut : un git add . le publierait. Avertissement seulement, le commit passe ; le contenu du fichier n'est jamais lu.
⚠ Fichier sensible ni suivi ni ignoré : un git add . le publierait. Lignes à ajouter à .gitignore :
.env
outils/set-npm-token.sh
Noms signalés par défaut (sans casse) : .env, .env.*, *token*, *secret*, *.pem, *.key, id_rsa* ; .env.example jamais. Autres motifs : sensitiveFiles = .env *.p12 dans .repowarden.conf (remplace la liste). Désactiver : git config repowarden.skip sensitive-files (skip secrets le coupe aussi).
Fonctions sans commentaire¶
Consigne pour les agents (et pour tous) : toute nouvelle fonction a, juste au-dessus, une à deux lignes qui disent ce qu'elle fait et pourquoi, sans paraphraser le code. Le pre-commit et la CI (vérification comments) le contrôlent : une fonction ajoutée sans commentaire (ni docstring en Python) est signalée avec fichier:ligne. Les fonctions existantes ne le sont jamais, même retouchées. Shell (.sh, .bash, scripts à shebang sh/bash), Python, JavaScript et TypeScript (function, const f = (…) =>) ; méthodes de classe non analysées.
⚠ src/panier.ts:12 : fonction total sans commentaire juste au-dessus
ℹ 1 fonction(s) ajoutée(s) sans commentaire : une à deux lignes juste au-dessus, qui disent ce qu'elle fait et pourquoi (avertissement, non bloquant).
Avertissement seulement, jamais bloquant. Un décorateur ou une directive d'outil (# shellcheck disable=…, // eslint-disable…) entre le commentaire et la fonction est sauté ; seul, il ne compte pas comme commentaire. Désactiver : git config repowarden.skip comments.
Lint au pre-push¶
Le hook pre-push lance des linters sur les fichiers modifiés avant les tests :
| Linter | Fichiers ciblés | Outil requis |
|---|---|---|
| shellcheck | *.sh, *.bash et scripts sans extension avec shebang (#!/bin/sh, #!/bin/bash, #!/usr/bin/env bash…) |
shellcheck |
| actionlint | .github/workflows/*.yml, .github/workflows/*.yaml |
actionlint |
Sévérité shellcheck¶
Réglage repowarden.lintSeverity (dans .repowarden.conf ou git config) :
| Valeur | Comportement | Checks activés |
|---|---|---|
error |
Bloque seulement sur les erreurs | Obligatoires niveau error |
warning (défaut) |
Bloque sur erreurs + avertissements | Obligatoires error + warning |
style |
Bloque aussi sur les remarques de style | Tous + optionnels (-o all) |
info |
Bloque sur tout | Tous + optionnels (-o all) |
Désactiver le lint¶
repowarden.skip lint(git config ou.repowarden.conf) : désactive complètement le lint au push.- Mode strict CI (
REPOWARDEN_WARN_FILEdéfini) : outil manquant = échec.
Installation des outils¶
Si un linter est absent, un message d'avertissement indique la commande d'installation selon l'OS :
- macOS : brew install shellcheck / brew install actionlint
- Linux : apt-get install shellcheck / go install github.com/rhysd/actionlint/cmd/actionlint@latest
- Windows : choco install shellcheck / scoop install actionlint
Messages de commit¶
Format <type>(<scope>): <description> ; ! après le type pour un changement majeur (feat!: …).
| Type | Usage | Release |
|---|---|---|
feat |
nouvelle fonctionnalité | version mineure (1.4.0) |
fix |
correction de bug | correctif (1.4.1) |
perf |
performance | correctif |
docs |
documentation | correctif |
style, refactor, test, build, ci, chore, revert |
formatage, restructuration, tests, build, CI, maintenance, annulation | aucune à eux seuls |
Agents IA : les signatures d'agent (Co-Authored-By: Claude …, « 🤖 Generated with … ») sont retirées du message, et un commit dont l'auteur ou le committer est un agent (noreply@anthropic.com, Copilot, Cursor, Devin) est refusé : l'historique porte l'identité d'une personne. Les bots d'automatisation (github-actions, App repowarden, Dependabot) ne sont pas concernés. Pour autoriser les agents : git config repowarden.allowAgentSignatures true (ou dans .repowarden.conf). Pour arrêter un agent avant qu'il ne modifie une branche protégée ou ne contourne les hooks : garde-fou des agents (repowarden agents init).
Un ! (feat!: …) ou un pied de page BREAKING CHANGE: donne une version majeure. Voir releases automatiques.
Assistant de commit : git cc¶
Pour écrire un message conforme sans retenir le format, git cc guide pas à pas (alias installé par install.sh), dans la langue choisie à l'installation :
$ git cc
◆ repowarden · commit conventionnel
Entrée = valeur proposée entre [crochets] · Ctrl+C pour abandonner
◇ 1/5 Type de changement
1 ✨ feat nouvelle fonctionnalité
2 🐛 fix correction de bug
…
Numéro ou nom [feat] : ← proposé d'après la branche feat/panier
◇ 2/5 Scope (optionnel)
Scope (« - » pour aucun) [panier] :
◇ 3/5 Changement incompatible ?
Incompatible ? [o/N] :
◇ 4/5 Description
À l'impératif, sans majuscule initiale ni point final ; 58 caractères au plus.
feat(panier): ajoute le panier
◇ 5/5 Détails (optionnels)
> Le client garde ses articles entre deux visites.
>
Références (ex. Closes #12 ; Entrée pour aucune) : Closes #12
┌─ Message ───────────────────────────────────────────────
│ feat(panier): ajoute le panier
│
│ Le client garde ses articles entre deux visites.
│
│ Closes #12
└─────────────────────────────────────────────────────────
Commiter ? [O/n] :
| Étape | Obligatoire | Aide |
|---|---|---|
| Type | oui | menu (numéro ou nom), proposé d'après la branche ; rien n'est proposé sur une branche hors convention (wip/…) : le type doit être choisi |
| Scope | non | proposé d'après la branche ; un scope invalide est corrigé et proposé (« doc test » → doc-test) |
| Changement incompatible | non | ajoute ! et le pied BREAKING CHANGE: …, décrit aussitôt (10 caractères au moins) ; question sautée au premier commit du dépôt |
| Description | oui | longueur de l'en-tête contrôlée (72 caractères) ; point final retiré |
| Corps | non | plusieurs lignes : le pourquoi ; une ligne vide (ou seulement ;, .) termine |
| Références | non | exemple adapté à la plateforme : Closes #12, !34 (GitLab), PROJ-42 (Bitbucket) |
Sur une branche protégée (main…), le commit serait refusé : l'assistant le dit dès l'étape 2 et propose une branche <type>/<scope> (Entrée pour la créer, tes modifications suivent ; « n » pour abandonner). Une réponse incomplète est complétée (feat → feat/<scope>), un nom approximatif corrigé (Mon Essai → feat/mon-essai).
Saisie robuste : flèches et effacement dans un terminal, touches parasites ignorées ; une réponse oui/non invalide est redemandée ; Ctrl+D abandonne. Si un hook refuse le commit, le message est conservé (git commit -F .git/repowarden-message après correction).
Les options de git commit sont transmises (git cc --no-verify…) ; git cc --dry-run affiche le message sans commiter. Réponses fournies par un script (une par ligne sur l'entrée standard) : git cc --strict, pour qu'une réponse refusée arrête tout au lieu de lire la ligne suivante comme une nouvelle réponse. Sans install.sh : git config --global alias.cc '!bash /chemin/vers/repowarden/bin/commit'.
Sans question (scripts, agents, CI) : les réponses passent en options, avec les mêmes contrôles, et toute valeur refusée arrête tout sans rien commiter. Le type et le scope omis sont déduits de la branche, comme avec Entrée ; sur une branche protégée, aucune branche n'est créée.
git cc -m "ajoute le panier" # sur feat/panier → feat(panier): ajoute le panier
git cc --type fix --scope - -m "corrige le total" \
--body "Le total ignorait la remise." --refs "Closes #12"
git cc --type feat --breaking "le total est en centimes" -m "change l'API du panier"
| Option | Rôle |
|---|---|
-m, --message |
description (obligatoire sans question) |
--type |
type (nom ou numéro du menu) |
--scope |
scope ; - pour aucun |
--breaking |
changement incompatible : ! et pied BREAKING CHANGE: <texte> |
--body |
corps (plusieurs lignes possibles) |
--refs |
références (Closes #12) |
Les autres options sont transmises à git commit ; -- termine les options de l'assistant.
Nommage des branches¶
Format <type>/<sujet> (sujet en a-z0-9._-, / pour sous-découper) : feat/inscription, fix/user/login, hotfix/timeout-db.
- Averti à la création, refusé au commit et au push, avec la commande de renommage à copier.
- Exceptions par défaut :
main,master,develop,release/*et les branches des bots (release-please--*,dependabot/*,renovate/*) ; réglageallowedBranches. - Le type devient le préfixe du commit, le sujet son scope (omis au-delà de 20 caractères).
- Alias :
feature/→feat,bugfix/ethotfix/→fix. - Un message déjà conforme n'est jamais modifié ; merge, squash et amend sont ignorés.
Git n'a pas de hook à la création de branche
Le nom est donc vérifié au premier commit et au push. Pour l'imposer côté serveur, voir les règles serveur.