LoginSignup
2
1

More than 1 year has passed since last update.

【PHP】gitのpre-commitフックを利用してコードチェックを自動化する

Last updated at Posted at 2022-05-05

前提

pre-commitフックで実現する内容

環境

Docker使用
Laravelプロジェクト

ディレクトリ構成

backendにLaravelが格納されています。
その一個上の階層がプロジェクトのルートディレクトリとなっていて、そこに.gitがあるイメージですね。
Dockerを使用していると、こういう感じになっているかと思います。
Laravelの1つ上の階層がルートディレクトリというのがpre-commitを書く上でも重要になってきます。

$ tree -L 1 -a
.
├── .DS_Store
├── .git // .git/hooks/pre-commitにスクリプトを書く
├── .gitignore
├── .php-cs-fixer.cache
├── .vscode
├── README.md
├── backend // ここがLaravelプロジェクトが入っているところ
├── docker-compose.yml
├── infra
└── test.txt
.gitのディレクトリ構成
.git
├── COMMIT_EDITMSG
├── HEAD
├── config
├── description
├── hooks
│   ├── applypatch-msg.sample
│   ├── commit-msg.sample
│   ├── fsmonitor-watchman.sample
│   ├── post-update.sample
│   ├── pre-applypatch.sample
│   ├── pre-commit
│   ├── pre-commit.sample
│   ├── pre-merge-commit.sample
│   ├── pre-push.sample
│   ├── pre-rebase.sample
│   ├── pre-receive.sample
│   ├── prepare-commit-msg.sample
│   ├── push-to-checkout.sample
│   └── update.sample
(以下略)

hooksの中にはpre-commit以外のsampleも色々入っていますね。
最初はpre-commitファイルはありません。作成する必要があります

pre-commitを書くまでの手順

インストールするライブラリ

  • phpstan
  • phpmd
  • php-cs-fixer

インストール方法

// PHPのコンテナ内のLaravelのプロジェクトのルートディレクトリで以下のコマンドを実行
composer require --dev friendsofphp/php-cs-fixer
composer require --dev phpmd/phpmd
composer require --dev phpstan/phpstan

ちなみに--devオプションで開発環境向けのインストールをします。
本番環境でcomposer installを実行する際に--no-devオプションをつけて実行することで、composer.jsonのrequire devオプションに記載されているライブラリ自体はvendorへインストールされません。

本番環境でのライブラリインストールのコマンド
composer install --no-dev

pre-commitの作成

Git管理のルートディレクトリから以下のコマンドを実行し、pre-commitを作成していく。

vi .git/hooks/pre-commit

そして以下の内容をpre-commitに記述して:wqで保存する。

#!/bin/bash
   
echo -e $'\e[1;45m ***** pre-commit hookを実行します ***** \e[m'
   
# プロジェクトディレクトリ
project_dir=backend
   
if git rev-parse --verify HEAD >/dev/null 2>&1
then
    against=HEAD
else
    # Initial commit: diff against an empty tree object
    against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi 
   
# Redirect output to stderr.
exec 1>&2
SYNTAX_CHECK=0
   
## 静的解析、及びフォーマッターの実行
# コミットされるファイルのうち、.phpで終わるもの
for FILE in `git diff-index --name-status $against -- | grep -E '^[AUM].*\.php$'| cut -c3-`; do
    # シンタックスのチェック
    echo -e $'\e[36mphp -l シンタックスチェック \e[m'
    if php -l $FILE; then
        # PSR準拠でコード書き換え
        echo -e $'\e[36m\nphp-cs-fixerを実行します \e[m'
        $project_dir/vendor/bin/php-cs-fixer fix $FILE
        git add $FILE
   
        # PHPMDで未使用変数などのチェック
        echo -e $'\e[36m\nphpmdを実行します \e[m'
        if ! $project_dir/vendor/bin/phpmd $FILE text backend/ruleset.xml; then
            SYNTAX_CHECK=1
            echo -e $'\e[31;43m phpmdのチェックエラーを直してください \e[m'
        fi
   
        # phpstanでコード静的解析
        echo -e $'\e[36m\nphpstanを実行します \e[m'
        if ! $project_dir/vendor/bin/phpstan analyse $FILE; then
          SYNTAX_CHECK=1
            echo -e $'\e[31;43mphpstanのチェックエラーを直してください \e[m'
        fi
    else
        SYNTAX_CHECK=1
    fi
done
   
   
## 最後の確認
if [ $SYNTAX_CHECK -eq 0 ]; then
    exit 0
else
    echo -e $'\e[31;43m 修正を行った上で再度コミットしてください \e[m'
    exit 1
fi 

phpmdチェックで引っ掛かるように、以下のコードを

  • backend/app/Http/Controllers/Controller.php
  • backend/app/Models/User.php
    に追記しています。
phpmdチェックに引っ掛かるコード
// メソッド名がキャメルケースになっていないコード
    public function test_test()
    {
    }

差分比較についての補足

for FILE in `git diff-index --name-status $against -- | grep -E '^[AUM].*\.php$'| cut -c3-`; do

[AUM]という部分について、そういう正規表現があるのかな?って思ったんですけど、そういうわけではなくて、
git diff-index --name-status HEADコマンドをを実行した時に表示される、ファイル名のリストの先頭に

$ git diff-index --name-status HEAD
M       backend/app/Http/Controllers/Controller.php
M       backend/app/Models/User.php

先頭にA or U or Mが表示されます。それぞれの意味は

  • A 追加
  • M 更新
  • U 競合

ということらしい。
参考にしたサイト
http://lost-waldo.blogspot.com/

注意点

いろいろ参考になる記事が世の中にありますが、ポイントとしては
Git管理のルートディレクトリがどこか
を意識しないと、pre-commit内で実行するコマンドのパスが変わってくるので重要なんですね。

今回はDockerを使用していて、Laravelプロジェクトの1つ上の階層がルートになり、そのディレクトリに.gitディレクトリが存在しています。

php-cs-fixerなどのライブラリを使用しているので、
backend/vendor/bin/phpmdと書く必要があるということです。
(すぐ気づかないといけませんが。。。)

表示例

ちょこちょこ色付けしてみました。
image.png

なんかいまいち見やすくならなかったかなぁ・・・

最後に

php-cs-fixerのコマンド実行のパス指定の注意点があったので、他につまづいている方がいましたら参考になればと思います。

また、他にもpre-commitフックに追加した方がいいチェックや
間違いなどがありましたらご指摘いただければと思います。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1