背景
ESLintやPrettierでファイルはちゃんとフォーマットしているのにコミットメッセージは人によってめちゃくちゃだったりします。
ルールも決まっていないと後から読み返したときに何をしたんだこれとなるのですが、とはいえ毎回「どんなルールだったっけ」とプロジェクトごとに見返すのもめんどくさいです。
あと、コミットしてから「あ、フォーマットするの忘れてた」となって再コミットするのもダサいです。
これらを全て解決する方法が求められていました。
Husky
huskyはgitで何らかの操作を行った際に割り込んで処理が行える仕組みを提供します。
例えば、コミットする際にはgit commit
が実行される前にyarn lint
やyarn test
を実行するなどといった操作ができるようになります。
こうすればコミットされた内容はCIでのテストをパスすることが保証されるようになります。
この仕組みの便利なところはESLintとPrettierの基準を満たすかどうかをチェックしているのではなく、実際にこの時点で整形してくれることにあります、とても便利。
とはいえテストが通らないコミットができないのは困るので、テスト自体は通らなくても良いですがESLintとPrettierの整形は通って欲しい感じになります。
Huskyはつい最近アップデートがあったようで、使い方が大きく変更されています。ネットで検索しても違うコマンドが載っていたりして困ります。
導入
プライベートレポジトリでないなら以下の二つをインストールします。
yarn add -D husky pinst
yarn husky init
プライベートの場合は
pinst
は不要のようです
yarn husky init
については不要かもしれませんが、一応実行しました。
これでpackage.json
のscripts
に"prepare": "husky"
が追加されていればOKです。
.
├── .husky/
│ ├── _/
│ └── pre-commit
└── package.json
この時点で上のような構成になっていると思います。
lint-staged
コミット前にESLintを実行させることができます。
yarn add -D lint-staged
としてパッケージを追加し.lintstagedrc.yaml
を作成します。
---
'**/*.ts':
- yarn lint
- yarn format
こう書くとコミット内容に.ts
のファイルがあればyarn lint
とyarn format
を実行してくれます。
最後にこの処理がgit commit
が実行される前に実行されてほしいので.husky/pre-commit
を編集します。
yarn test
yarn lint-staged
ここの
yarn test
は必ずしも必要ではない、大事なのはyarn lint-staged
が実行されること
.
├── .husky/
│ ├── _/
│ └── pre-commit
├── .lintstagedrc.yaml
└── package.json
するとこんな感じになると思います。
commitlint
commitlintはコミットメッセージが.commitlintrc.yaml
に設定されたルールに則っているかをチェックするパッケージです。
yarn add -D @commitlint/cli @commitlint/config-conventional
インストールができたら.commitlintrc.yaml
を作成します。
---
extends:
- '@commitlint/config-conventional'
今回は特に何も入れていませんが、ここにプロジェクトごとのルールを追記することができます。
最後にコミットメッセージを書き込んだ後にチェックを行うので.husky/commit-msg
のファイルを作成します。
yarn commitlint --edit ${1}
こうすれば最後のコミットメッセージを読み込んでcommitlint
が実行されます。
.
├── .husky/
│ ├── _/
│ ├── commit-msg
│ └── pre-commit
├── .commitlintrc.yaml
├── .lintstagedrc.yaml
└── package.json
するとここまでのファイル構成はこうなります。
実際にどんな挙動をするか確かめたい場合はcommit-msg
の最後にexit 1
を入れれば必ず失敗するので実際にコミットログが作成されません。
その状態でgit commit -m "testing pre-commit code"
みたいな感じで実行すればどうなるかがわかります。
正常に動作していればcommitlintがエラーを返すはずです。
もしcommitlintがちゃんと動いていないようであればHuskyがhookに失敗しているのでyarn install
でhusky
をインストールしてください。
cz-commitlint
cz-commitlintはcommitlintの拡張で、対話式でコミットメッセージが作成できるパッケージです。
commitlintと組み合わせて入力ミスを防ぎつつ、フォーマットに則ったコミットメッセージが書けます。
yarn add -D @commitlint/cz-commitlint commitizen
エラーが発生する場合は
inquirer@8
もインストールしてください
インストールが完了したらpackage.json
を編集して、
{
"scripts": {
"commit": "git-cz"
},
"config": {
"commitizen": {
"path": "@commitlint/cz-commitlint"
}
}
}
を追記します。こうするとyarn commit
で対話式のコミットメッセージが書けます。
git commit
とはいえgit commit
に慣れているので、このコマンドを実行したときにもyarn commit
と同様の効果が得られてほしいです。
そこで.husky/prepare-commit-msg
を作成して以下の内容を書き込みます。
exec < /dev/tty && yarn cz --hook || true
これはyarn cz
を実行してその結果がtrueであればexec 0
を返すコードです。
Huskyは0以外の値を返すとエラーとしてコミットがなかったことになります。
tty
を入れないと対話式にならない(何も入力できない)
├── .husky/
│ ├── _/
│ ├── prepare-commit-msg
│ ├── commit-msg
│ └── pre-commit
├── .commitlintrc.yaml
├── .lintstagedrc.yaml
└── package.json
最終的にファイルの構成は上のようになります。
これでコミットメッセージに悩まされる日々から無事に開放されました、やったね。
でもこのレポジトリにはこの機能を実装していないという矛盾(おい
記事は以上。