すべてのcommitにcommitlintを実行する

モチベ

これまで恥ずかしながらコミットメッセージは雰囲気で書いていた。
ただそろそろちゃんと書くようにしないとと思い、まずはコミットメッセージ用のlinterを入れてみようと検討した。

調べた感じ commitlint が良さそうだったので、今回はそれを入れてみる。

公式の手順だと、commitlintとhuskyをプロジェクトごとにインストールする形になっている。

https://commitlint.js.org/guides/local-setup.html

今回の場合、特定のプロジェクトやチームに導入したいというよりも、自分の習熟のために導入したかった。
そのため自分のローカルにおいてはどのプロジェクトに対しても、常にcommitlintを実行するように設定してみた。

設定

各種バージョン

 1[koh@Kohs-MacBook-Pro] ~
 2% sw_vers
 3ProductName:            macOS
 4ProductVersion:         15.1.1
 5BuildVersion:           24B91
 6[koh@Kohs-MacBook-Pro] ~
 7% node -v
 8v22.6.0
 9[koh@Kohs-MacBook-Pro] ~
10% commitlint -v
11@commitlint/cli@19.6.1
12[koh@Kohs-MacBook-Pro] ~
13%

設定は以下のようにした。

1mkdir ~/.config/git/hooks/ # ディレクトリは任意のパスでいい
2git config --global core.hooksPath \~/.config/git/hooks
3vi ~/.config/git/hooks/commit-msg
4chmod +x ~/.config/git/hooks/commit-msg

commit-msgファイルには以下のように記述する。

 1#!/usr/bin/env bash
 2
 3# install commitlint if not installed
 4if ! command -v commitlint &> /dev/null; then
 5    echo "commitlint not found, installing..."
 6    npm install -g @commitlint/cli @commitlint/config-conventional
 7fi
 8
 9# set config
10# SEE: https://github.com/conventional-changelog/commitlint/tree/master/@commitlint/config-conventional
11CONFIG="
12extends:
13  - '@commitlint/config-conventional'
14"
15
16# exec commitlint
17commitlint --edit "$1" --config <(echo "$CONFIG")

インストール

@commitlint/cli@commitlint/config-conventional をインストールする。
後者の方は設定したいルールによって変更する。

https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint

config-* の中から選ぶ。
今回はGetting startedで指定されていたconventionalを選択した。

具体的なルールは以下。

https://github.com/conventional-changelog/commitlint/tree/master/@commitlint/config-conventional

設定ファイル

commitlintは実行時に設定ファイルが必要になる。

https://commitlint.js.org/reference/configuration.html

現時点では設定がシンプルかつ、管理するファイルを減らしたかった。
そのためスクリプト内でプロセス置換する形で設定を渡している。

設定の読み込み時に cosmiconfig を使用しており、設定ファイルの拡張子がない場合はYAML形式でパースされる。
そのためプロセス置換で設定ファイルを作成する場合は、YAML形式で記述する。

hookでの実行

gitのcommit-msg hookを利用する。

https://git-scm.com/docs/githooks#_commit_msg

第一引数にコミットメッセージのファイルパスが渡されるので、それを利用する。
具体的には .git/COMMIT_EDITMSG が第一引数になる。

動作確認

これにより、ローカルのすべてのプロジェクトでcommitlintが実行される。

 1[koh@Kohs-MacBook-Pro] ~/work
 2% mkdir commit_test && cd commit_test
 3[koh@Kohs-MacBook-Pro] ~/work/commit_test
 4% git init .
 5Initialized empty Git repository in /Users/koh/work/commit_test/.git/
 6[koh@Kohs-MacBook-Pro] ~/work/commit_test
 7% echo foobar >> test.txt && git add test.txt && git commit -m "foobar"
 8⧗   input: foobar
 9✖   subject may not be empty [subject-empty]
10type may not be empty [type-empty]
11
12✖   found 2 problems, 0 warnings
13ⓘ   Get help: https://github.com/conventional-changelog/commitlint/#what-is-commitlint
14
15zsh: exit 1     git commit -m "foobar"
16[koh@Kohs-MacBook-Pro] ~/work/commit_test
17% git commit -m "feat: foobar"
18[main (root-commit) 9dd1ceb] feat: foobar
19 1 file changed, 1 insertion(+)
20 create mode 100644 test.txt
21[koh@Kohs-MacBook-Pro] ~/work/commit_test
22%

新規のプロジェクトでも、commitlintが実行されている。

まとめ

とりあえずはこの設定で試してみようと思う。
大リーグボール養成ギプスのように、常にlinter実行することで慣れると嬉しい。