[PHP]Circle CIで変更箇所のファイルのみを静的解析(Lint)する②


概要

[JavaScript]Circle CIで変更箇所のファイルのみを静的解析(Lint)する① - QiitaのPHP版です。

今回導入する静的解析ツールはPHPStanです。
パッケージ管理ツールcomposerは設定済みとします。

結論はコチラなので、既に手順が分かる人は飛ばしてください。

手順

静的解析ツール(Linter)の設定

1. インストール

チームで開発するためPHPStanパッケージをローカルインストールします。

$ composer require --dev phpstan/phpstan

依存関係のエラーが起きた場合は以下を実行します。

$ composer require --dev phpstan/phpstan-shim

2. エイリアスの設定

パッケージをローカルインストールした時は、実行時のパス指定が面倒なためタスクランナーにエイリアスを登録します。
composer.jsonscriptsに以下のように追記します。

composer.json
{
    "scripts": {
        "phpstan": [
            "vendor/bin/phpstan"
        ]
   }
}

3. 動作確認

以下のコマンドでLintが実行できることを確認します。

$ composer phpstan analyze path/to/file

出力結果

> vendor/bin/phpstan 'analyze' 'xxx.php'
 1/1 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%

 [OK] No errors                                                                 

Cricle CIの設定

Circle CIとGitの連携は設定済みとします。

1. 設定ファイルを書く

.circleci/config.ymlを作成し、設定を記載します。

circleci/config.yml
version: 2
jobs:
  build:
    docker:
      - image: circleci/php:7.1-cli

    steps:
      - checkout

      # Linter含むパッケージをインストールする
      - run: composer install

      # 差分のあるphpファイルのみLintを実行する
      - run: 
          name: php lint
          command: git diff --name-only --diff-filter=ACMR origin/develop..origin/${CIRCLE_BRANCH} -- '*.php' | xargs -r composer phpstan analyze       

2. 動作確認

適当なxxx.phpを作成し、コミットしたのちにリモートにプッシュします。
ターミナルでも以下のコマンドを打ち、差分ファイルのみ表示されることを確認します。

git diff --name-only --diff-filter=ACMR origin/develop..origin/${CIRCLE_BRANCH} -- '*.php'

出力結果

#!/bin/bash -eo pipefail
git diff --name-only --diff-filter=ACMR origin/develop..origin/${CIRCLE_BRANCH} -- '*.php' | xargs -r composer phpstan analyze

> vendor/bin/phpstan 'analyze' 'xxx.php'
 1/1 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%

 [OK] No errors                                                                   

最後に、Circle CIの画面でプロジェクトのジョブを確認し、Successと表示されれば成功です。

コマンドの説明

.circleci/config.ymlの最後のコマンドについて解説します。

git diff --name-only --diff-filter=ACMR origin/develop..origin/${CIRCLE_BRANCH} -- '*.php' | xargs -r composer phpstan analyze    

git diff BRANCH1..BRANCH2:ブランチ同士の差分を取ります。
--name-only:ファイル名のみを取得します。
--diff-filter=ACMR:A(追加)/C(コピー)/M(変更)/R(名前変更)の操作があったファイルのみを取得します。
-- '*.php':対象ファイルであるphpファイルのみを取得します。
${CIRCLE_BRANCH}:現在の作業ブランチを取得します。
xargs:前のコマンドの結果を引数として後ろのコマンドに渡します。
-r:引数に何も結果がない場合にスキップします。(Linuxのみ)

以上です!

補足

私の環境の場合、composer installする際にphp gdがないというエラーが起きたので、以下をcomposer installする前のステップに追記しました。

      - run:
          name: install php extension gd
          command: |
            sudo apt-get install -y libpng-dev
            sudo docker-php-ext-install gd

Installing php7.1-gd on the php:7.1.4-apache container - Build Environment - CircleCI Discuss

参考

[PHP] 静的解析ツールPHPStanの機能概要 - Qiita
PHPStanで始めるPHPのための静的解析 #phperkaigi - Mercari Engineering Blog
ピクシブ百科事典に静的解析のCIを導入した話 - pixiv inside

最後に

Linterの設定をそれぞれPHPとJSに対して行ったので、個人的にはcomposerとnpmの対応する機能が理解できた気がします。
記事に間違いや不明な点があれば遠慮なくご指摘ください。