Que fait commitlint ?
Valide les messages de commit au format Conventional Commits à l'aide de la configuration et des règles commitlint.
Quand utiliser cette compétence
Utilisez cette compétence lorsque :
- Vous configurez commitlint pour un dépôt
- Vous configurez des règles commitlint et des configurations partageables
- Vous intégrez commitlint avec des hooks pre-commit ou des pipelines CI/CD
- Vous extrayez des règles de la configuration commitlint pour générer des invites LLM pour la génération de messages de commit
- Vous validez programmatiquement des messages de commit
- Vous résolvez des problèmes de configuration ou de validation commitlint
- Vous comprenez la syntaxe des règles commitlint et les niveaux de sévérité
- Vous détectez les fichiers de configuration commitlint dans un dépôt
Fonctionnalités principales
Détection de configuration
Commitlint utilise cosmiconfig pour trouver les fichiers de configuration dans cet ordre de priorité :
Fichiers de configuration dédiés :
.commitlintrc
.commitlintrc.json
.commitlintrc.yaml
.commitlintrc.yml
.commitlintrc.js
.commitlintrc.cjs
.commitlintrc.mjs
.commitlintrc.ts
.commitlintrc.cts
commitlint.config.js
commitlint.config.cjs
commitlint.config.mjs
commitlint.config.ts
commitlint.config.cts
Fichiers de package :
package.jsonavec le champcommitlintpackage.yaml(PNPM) avec le champcommitlint
Formats de configuration
JavaScript ES Modules (Recommandé) :
// commitlint.config.js ou commitlint.config.mjs
export default {
extends: ['@commitlint/config-conventional'],
};
TypeScript :
// commitlint.config.ts
import type { UserConfig } from '@commitlint/types';
import { RuleConfigSeverity } from '@commitlint/types';
const config: UserConfig = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [RuleConfigSeverity.Error, 'always', ['feat', 'fix', 'docs']],
},
};
export default config;
JSON :
{
"extends": ["@commitlint/config-conventional"]
}
YAML :
extends:
- "@commitlint/config-conventional"
Configuration des règles
Les règles sont configurées sous forme de tableaux : [niveau, applicabilité, valeur]
Niveaux de sévérité :
| Niveau | Signification | Enum TypeScript |
|---|---|---|
| 0 | Désactivée | RuleConfigSeverity.Disabled |
| 1 | Avertissement | RuleConfigSeverity.Warning |
| 2 | Erreur | RuleConfigSeverity.Error |
Applicabilité :
'always'- La règle doit correspondre'never'- La règle ne doit pas correspondre
Exemples de règles :
rules: {
// Erreur si le type n'est pas dans l'énumération
'type-enum': [2, 'always', ['feat', 'fix', 'docs', 'style', 'refactor', 'perf', 'test', 'build', 'ci', 'chore', 'revert']],
// Erreur si le type est vide
'type-empty': [2, 'never'],
// Erreur si le sujet est vide
'subject-empty': [2, 'never'],
// Erreur si l'en-tête dépasse 100 caractères
'header-max-length': [2, 'always', 100],
// Erreur si le sujet se termine par un point
'subject-full-stop': [2, 'never', '.'],
// Avertissement si le corps n'a pas de ligne vide initiale
'body-leading-blank': [1, 'always'],
}
Configurations courantes
@commitlint/config-conventional
La configuration partageable la plus utilisée. Règles par défaut avec niveau d'erreur :
| Règle | Configuration | Exemple réussi | Exemple échoué |
|---|---|---|---|
type-enum | ['build', 'chore', 'ci', 'docs', 'feat', 'fix', 'perf', 'refactor', 'revert', 'style', 'test'] | fix: message | foo: message |
type-case | 'lowerCase' | fix: message | FIX: message |
type-empty | never | fix: message | : message |
subject-case | never + ['sentence-case', 'start-case', 'pascal-case', 'upper-case'] | fix: some message | fix: Some Message |
subject-empty | never | fix: message | fix: |
subject-full-stop | never, '.' | fix: message | fix: message. |
header-max-length | 100 | En-tête court | En-tête > 100 car. |
body-leading-blank | always (avertissement) | Ligne vide avant le corps | Pas de ligne vide |
body-max-line-length | 100 | Lignes <= 100 car. | Ligne > 100 car. |
footer-leading-blank | always (avertissement) | Ligne vide avant le pied | Pas de ligne vide |
footer-max-line-length | 100 | Lignes <= 100 car. | Ligne > 100 car. |
Schéma de configuration complet
// commitlint.config.js
export default {
// Étendre les configurations partageables (résolues via la résolution de modules node)
extends: ['@commitlint/config-conventional'],
// Présélection d'analyseur pour analyser les messages de commit
parserPreset: 'conventional-changelog-atom',
// Formateur de sortie
formatter: '@commitlint/format',
// Règles personnalisées (remplacent les règles héritées)
rules: {
'type-enum': [2, 'always', ['feat', 'fix', 'docs', 'style', 'refactor', 'test', 'chore']],
},
// Fonctions qui renvoient true pour ignorer des commits spécifiques
// Fusionnées avec les ignorations par défaut (commits de fusion, retours, tags semver)
ignores: [(commit) => commit.includes('WIP')],
// Utiliser ou non les motifs d'ignorance par défaut
// Motifs par défaut : 'Merge pull request', 'Revert X', 'v1.2.3', etc.
defaultIgnores: true,
// URL d'aide personnalisée affichée en cas d'échec
helpUrl: 'https://example.com/commit-guidelines',
// Configuration de l'invite (pour @commitlint/cz-commitlint)
prompt: {
messages: {},
questions: {
type: {
description: 'Sélectionnez le type de changement :',
},
},
},
};
Utilisation en CLI
Installation
# npm
npm install -D @commitlint/cli @commitlint/config-conventional
# yarn
yarn add -D @commitlint/cli @commitlint/config-conventional
# pnpm
pnpm add -D @commitlint/cli @commitlint/config-conventional
Commandes courantes
# Analyser le dernier commit
npx commitlint --last
# Analyser une plage de commits
npx commitlint --from HEAD~5
# Analyser à partir d'un commit spécifique
npx commitlint --from abc1234
# Analyser un message depuis l'entrée standard
echo "feat: add feature" | npx commitlint
# Analyser un message depuis un fichier
npx commitlint < .git/COMMIT_EDITMSG
# Analyser avec le drapeau edit (lit .git/COMMIT_EDITMSG)
npx commitlint --edit
# Analyser avec un chemin de configuration personnalisé
npx commitlint --config ./custom-commitlint.config.js
# Afficher la configuration résolue
npx commitlint --print-config
# Mode strict (les avertissements deviennent un code de sortie 2)
npx commitlint --last --strict
Codes de sortie
| Code | Signification |
|---|---|
| 0 | Succès (aucune erreur) |
| 1 | Erreurs d'analyse trouvées |
| 2 | Avertissements trouvés (mode strict) |
| 3 | Erreurs trouvées (mode strict) |
| 9 | Fichier de configuration manquant (avec -g) |
Référence des règles
Règles de type
| Règle | Condition | Applicabilité par défaut |
|---|---|---|
type-enum | type se trouve dans la valeur | always |
type-case | type est en casse valeur | always, 'lower-case' |
type-empty | type est vide | never |
type-max-length | type a valeur ou moins de car. | always, Infinity |
type-min-length | type a valeur ou plus de car. | always, 0 |
Règles de sujet
| Règle | Condition | Applicabilité par défaut |
|---|---|---|
subject-case | subject est en casse valeur | always |
subject-empty | subject est vide | never |
subject-full-stop | subject se termine par valeur | never, '.' |
subject-max-length | subject a valeur ou moins de car. | always, Infinity |
subject-min-length | subject a valeur ou plus de car. | always, 0 |
subject-exclamation-mark | subject a un point d'exclamation avant : | never |
Règles de portée
| Règle | Condition | Applicabilité par défaut |
|---|---|---|
scope-enum | scope se trouve dans la valeur | always, [] |
scope-case | scope est en casse valeur | always, 'lower-case' |
scope-empty | scope est vide | never |
scope-max-length | scope a valeur ou moins de car. | always, Infinity |
scope-min-length | scope a valeur ou plus de car. | always, 0 |
Règles d'en-tête
| Règle | Condition | Applicabilité par défaut |
|---|---|---|
header-case | header est en casse valeur | always, 'lower-case' |
header-full-stop | header se termine par valeur | never, '.' |
header-max-length | header a valeur ou moins de car. | always, 72 |
header-min-length | header a valeur ou plus de car. | always, 0 |
header-trim | header n'a pas d'espace début/fin | always |
Règles de corps
| Règle | Condition | Applicabilité par défaut |
|---|---|---|
body-leading-blank | body commence par une ligne vide | always |
body-empty | body est vide | never |
body-max-length | body a valeur ou moins de car. | always, Infinity |
body-max-line-length | Les lignes de body ont valeur ou moins de car. (URL exclues) | always, Infinity |
body-min-length | body a valeur ou plus de car. | always, 0 |
body-case | body est en casse valeur | always, 'lower-case' |
body-full-stop | body se termine par valeur | never, '.' |
Règles de pied
| Règle | Condition | Applicabilité par défaut |
|---|---|---|
footer-leading-blank | footer commence par une ligne vide | always |
footer-empty | footer est vide | never |
footer-max-length | footer a valeur ou moins de car. | always, Infinity |
footer-max-line-length | Les lignes de footer ont valeur ou moins de car. | always, Infinity |
footer-min-length | footer a valeur ou plus de car. | always, 0 |
Valeurs de casse
Pour les règles qui vérifient la casse (*-case) :
[
'lower-case', // minuscules
'upper-case', // MAJUSCULES
'camel-case', // camelCase
'kebab-case', // kebab-case
'pascal-case', // PascalCase
'sentence-case', // Phrase
'snake-case', // snake_case
'start-case', // Commencer Par Maj
]
Utilisation programmatique
Chargement de la configuration
import load from '@commitlint/load';
async function getCommitlintConfig() {
const config = await load();
console.log(config.rules);
return config;
}
Validation d'un message
import load from '@commitlint/load';
import lint from '@commitlint/lint';
async function validateMessage(message) {
const config = await load();
const result = await lint(message, config.rules);
return {
valid: result.valid,
errors: result.errors,
warnings: result.warnings,
};
}
Modèles d'intégration LLM
Extraire les règles pour la génération d'invite
Générer des contraintes adaptées aux LLM à partir de la configuration commitlint :
def extract_rules_for_prompt(config: dict) -> str:
"""Extrait les règles commitlint dans un format adapté aux LLM."""
rules = config.get("rules", {})
prompt_parts = []
# Extraire type-enum s'il est présent
if "type-enum" in rules:
level, applicability, types = rules["type-enum"]
if level > 0 and applicability == "always":
prompt_parts.append(f"Types de commit autorisés : {', '.join(types)}")
# Extraire scope-enum s'il est présent
if "scope-enum" in rules:
level, applicability, scopes = rules["scope-enum"]
if level > 0 and applicability == "always":
prompt_parts.append(f"Portées autorisées : {', '.join(scopes)}")
# Extraire les limites de longueur
if "header-max-length" in rules:
level, applicability, max_len = rules["header-max-length"]
if level > 0 and applicability == "always":
prompt_parts.append(f"Longueur maximale de l'en-tête : {max_len} caractères")
# Extraire les vérifications de contenu
if "subject-empty" in rules:
level, applicability = rules["subject-empty"]
if level > 0 and applicability == "never":
prompt_parts.append("Le sujet ne doit pas être vide")
if "type-empty" in rules:
level, applicability = rules["type-empty"]
if level > 0 and applicability == "never":
prompt_parts.append("Le type ne doit pas être vide")
return "\n".join(prompt_parts)
Construire une invite LLM pour la génération de messages de commit
def build_commit_prompt(config: dict, diff_context: str) -> str:
"""Construit une invite pour un LLM afin de générer un message de commit valide."""
rules_text = extract_rules_for_prompt(config)
return f"""Générer un message de commit au format Conventional Commits.
Règles :
{rules_text}
Contexte du diff :
{diff_context}
Format attendu :
<type>(<portée>): <sujet>
<corps optionnel>
<pied optionnel>
"""
Intégration CI/CD
Intégration avec Husky et lint-staged
# Installer Husky
npx husky init
# Ajouter un hook pre-commit
npx husky add .husky/pre-commit "npx lint-staged"
package.json :
{
"lint-staged": {
"*.{js,ts,tsx}": ["eslint --fix", "prettier --write"],
"*.{md,json,yaml}": ["prettier --write"]
}
}
Hook commit-msg
# .husky/commit-msg
echo "${1}" | npx commitlint --edit "${1}"
Utilisation avec GitHub Actions
name: Valider les messages de commit
on: [pull_request]
jobs:
commitlint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/setup-node@v3
with:
node-version: 18
- run: npm ci
- name: Analyser la plage de commits
run: npx commitlint --from ${{ github.event.pull_request.base.sha }} --to ${{ github.event.pull_request.head.sha }} --verbose
Utilisation avec GitLab CI
stages:
- validation
commitlint:
stage: validation
image: node:18
script:
- npm ci
- npx commitlint --from $CI_MERGE_REQUEST_DIFF_BASE_SHA --to $CI_MERGE_REQUEST_DIFF_HEAD_SHA
only:
- merge_requests
Dépannage
Problèmes courants
-
Fichier de configuration non trouvé
- Vérifier que le fichier de configuration existe dans le répertoire racine
- Utiliser
npx commitlint --print-configpour voir la configuration résolue
-
Règles non appliquées
- Vérifier l'ordre de résolution des fichiers de configuration
- Utiliser le paramètre
extendscorrectement
-
Erreurs de commutation de version
- Exécuter
npx commitlint --versionpour vérifier la version installée - Mettre à jour
@commitlint/cliet les configurations partagées
- Exécuter
-
Problèmes de hook
- Vérifier que les hooks sont installés :
npx husky install - Vérifier les permissions des hooks :
chmod +x .husky/*
- Vérifier que les hooks sont installés :
Obtenir de l'aide
- Vérifier la configuration :
npx commitlint --print-config - Exécuter avec sortie verbeuse pour plus de détails :
npx commitlint --last --verbose - Consulter la documentation du projet : https://commitlint.js.org