無駄なコードレビューで疲弊していませんか?
Linterを使わないと、実装とは無関係の差分が発生しがちです。
レビューの質にも関わってくるので、この辺はコードをコミットする前に自動で直しましょう。
- インデントの階層違い
-
if()
orif ()
-
!$bool
or! $bool
- その他諸々。。。
目標
Laravel PintとGit Hooks(pre-commit)を使って、コミット前にLintを走らせる。
実装とは関係ない差分をコードレビュー前に排除して、レビューをもっと楽にする。
前提条件
- Laravelプロジェクト作成済
- プロジェクトがGit管理されている
- PHPがローカル環境またはDockerコンテナ内にインストール済
- Composerがローカル環境またはDockerコンテナ内にインストール済
手順
1. Laravel Pintインストール
公式ドキュメント曰く、最近のLaravelだと標準でインストールされているそうです。
Composer.jsonの中を確認して、laravel/pint
の表記がある場合は、飛ばしてください。
composer require laravel/pint --dev
2. pre-commit用シェルスクリプト用意
.git/hooks
ディレクトリの中を見ると、以下のようにGit Hooksに関するサンプルスクリプトが用意されています。
今回使用したいのは、pre-commit.sample
です。
しかし、.git
ディレクトリはGit管理下に含めることができません。
つまり、このままではチームメンバーにpre-commit
のスクリプトを使用してもらうことができません。
そこで、Git管理できるように別ディレクトリを作成してその中にpre-commit
のスクリプトを作成します。
# プロジェクトのトップディレクトリにいる前提
#1. ディレクトリ作成(ディレクトリ名は何でもOK)
mkdir .githooks
#2. pre-commitシェルスクリプトをコピー
cp .git/hooks/pre-commit.sample .githooks/pre-commit
#3. 実行権限を付与
chmod +x .gihooks/pre-commit
#4. pre-commitの中身を変更
vim .githooks/pre-commit
中身は以下のように書き換えてください。
#!/bin/sh
fileList=$(git diff --diff-filter=d --cached --name-only)
phpFiles=$(echo "$fileList" | grep -E '\.(php)$')
if [ ${#phpFiles} -gt 0 ]; then
# Lintスタート
echo 'Start Linting with laravel/pint.'
docker exec app ./vendor/bin/pint ${phpFiles[*]} "$@"
# エラーがあれば、コミットさせない
if [ $? -gt 0 ]; then
exit 1
fi
# エラーがなければ、Linterが変更した差分を取り込んでコミット
git add ${phpFiles[@]}
fi
以下の部分に関しては、Laravel/Pintが走れば何でも大丈夫です。
私の場合は、Docker内にPHPがインストールされているので、dockerコマンドにて実行しています。
docker exec app ./vendor/bin/pint ${phpFiles[*]} "$@"
3. .githooksディレクトリをHooksのコアディレクトリに指定
手順2の段階では、コミットしてもまだpre-commitスクリプトは走りません。
なぜなら、デフォルトでは.git/hooks
ディレクトリ内のpre-commit
などを実行するからです。
なので、今回新規作成した.githooks
ディレクトリの中を見るように設定を変更しましょう。
git config --local core.hooksPath .githooks
↑このコマンドを打つだけです。
.githooks
の部分は、作成したディレクトリ名に合わせてください。
4. pre-commit実行確認
PHPファイルを適当に編集して、コミットしてみましょう。
//正常
public function handle(Admin $admin): ?bool
{
return DB::transaction(fn () => $admin->delete());
}
//↓↓↓ fn()部分を編集
//エラー
public function handle(Admin $admin): ?bool
{
return DB::transaction(fn() => $admin->delete());
}
# 1. 編集したファイルをステージングに上げる
git add {編集したPHPファイル名}
# 2. コミットする
git commit -m "commit with pre-commit"
# 3. Laravel/Pintが走ることを確認
Start Linting with laravel/pint.
✓
──────────────────────────────────────────────────────────────────── Laravel
FIXED ...................................... 1 file, 1 style issue fixed
✓ app/Actions/DeleteAdmin.php function_declaration
[feature/pint 86bda9c4] pre-commit
# 4. コミット履歴確認
git log
コミット履歴に、1つ新規コミットが追加されています。
加えて、編集したファイルを確認してみると正しい記述に自動で修正されています。
手順としては、以上となります。
よくある質問
1. Git Hooksのコアディレクトリ設定は毎回手動でコマンド入力が必要?
最初のcomposer install
時に自動でこのコマンドを走らせるようにしましょう。
Composer.json
内のscripts
の中にコマンドを追加します。
{
"scripts": {
"post-install-cmd": [
"git config --local core.hooksPath .githooks"
],
}
}
こうすることで、新しいメンバーがジョインした時にも手動入力なしで即座にpre-commit適用が可能です。
2. PHPファイル以外の差分しかない場合はどうなる?
Laravel/Pint
が走るのは、PHPファイルの差分がある時だけです。
.json
や.html
にのみ差分がある場合は、Lint無しでコミットされます。
3. Lint実行時にエラーが起こった場合はどうなる?
Lint実行時に、エラーが起こった場合はコミットされません。
エラー内容を確認して、エラー解消してから再度コミットしてください。
参考文献
https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks
https://efcl.info/2021/08/21/git-precommit-hook/
https://markus.oberlehner.net/blog/lint-only-files-with-changes-on-pre-commit/