モノレポのプロジェクトでhuskyを設定してみた
フロントエンドの静的テストとして、huskyとlint-stagedを用いてeslintとprettierを実行しようとしたところ、.git
とpackage.json
のディレクトリが同一でないことで詰まったので備忘録。
ちなみに、ディレクトリの構造はこんな感じで、husky@9.0.11
、lint-staged@15.2.2
でのお話。
root/
|--.git <--
|--client
| |--src
| └--package.json <--
|--server
インストール
とにもかくにも、まずはインストール。
まずはhuskyのドキュメント通りやってみる。
npm i -D husky lint-staged
ついでに、lint-stagedもインストールしておく。
lint-stagedは、コミットしたいファイルにだけeslintとprettierをかけるのに必要。
huskyをインストールしたら初期化を行う。ドキュメント通りのコマンドを実行する。
npx husky init
はい。さっそく怒られる。
.git can't be found
huskyはプロジェクトのrootで使われる想定ぽい
.git
ディレクトリあるけどなんでなん?と調べ回ったところ、
どうやら.git
とpackage.json
が同一ディレクトリにないといけないぽい。
(けっこう前だったけど、同じ内容のissueが出ていたのを見たらプロジェクトのrootで使ってって書いてあった)
つまり、遠く離れた.git
を気を利かせて探しに行ってくれるわけではないらしい。
それなら探し方を教えてあげよう。
husky init
の実行でpackage.json
のscriptsに追加されたprepareを変更する。
"scripts": {
...,
...,
"prepare": "cd .. && husky client/.husky"
}
今回の筆者のケースだと、package.json
から見て.git
は親ディレクトリにいる。
だから、まずcd ..
をして親ディレクトリに行く。そんでhusky
を実行するのだけど、初期化を行う場所(client/.husky
)も渡してあげる。
本来というか公式ドキュメントだと、npx husky init
でセットアップ終了でprepareコマンドは叩く必要がない。今回は.gitが同一ディレクトリ内にいないから、prepareコマンドでセットアップ(準備)してもらう。
npm run prepare
ついに、サブディレクトリ内に.husky/_
が爆誕する。
この中にはhuskyの実行環境が置かれているぽいが、gitignore
されているし細かいことは置いておく。
ここまでで、huskyのセットアップは終了。
pre-commit
とcommit-msg
を設定していく。
lint-stagedとpre-commitを設定する
npx husky init
でpre-commit
ファイルができてるから、実行したいスクリプトを書けばいいだけ。
なんだけども、lint-stagedを使わないとcommit対象外のファイルにも実行されてしまうので、package.jsonに実行したい処理を含めたlinst-stagedを追加する。
"lint-staged": {
"*.ts": ["prettier --write", "eslint"]
}
とりあえず、prettierとeslintを入れてみる。eslintでフォーマットまでかけたい場合はeslint --fix
の方が良い。今回はちょっと怖いのでやめておく。
lint-stagedの設定ができたのでここで一度npm i
しておく。
そんで、pre-commit
ファイルにlint-staged
を実行するスクリプトを書く。
cd client
npx lint-staged
このファイル自体はサブディレクトリ内(今回で言うと/client)にあるが、呼び出し元はルートディレクトリの.git/hooks
になる。(そもそもhuskyはgitのhooksの実行内容をhuskyに向けるためのツールらしい)
だから、まずpackage.json
があるディレクトリまで移動してもらう。
移動を拒むとnode_module
がないから怒られる。
いざcommitの時!
いよいよcommitしてみる。
vscodeのgitの拡張機能のやつでcommitすると経過が出なくてちゃんとpre-commit実行されているか分かりにくいので、shellに叩き込む。
まずは、eslintでerrorが出ているファイルを準備してちゃんとcommitが弾かれるか確認する。
git commit -m "chore: fail commit"
お見事!無事にeslintで弾かれた!
次にerrorがないファイルはちゃんとcommitが通るか確認する。
git commit -m "chore: success commit"
無事にcommitされた😂
これでテストトロフィーの最下層、静的テストが自動で行える!
commit-msgも設定したけど、書くの疲れたからこの辺で終了。
参考記事だけ置いておきます。先人の皆様、超感謝してます。
おわり。
Discussion
分かりやすい記事あった