はじめに
PHPのプロジェクトのコードフォーマットが安定しない&CIでやってみるということで、GitHub Actionsにphpcs(PHP_CodeSniffer)とreviewdogを組み合わせて設定します。
大規模な業務プロジェクトに対して設定してみたところ、ソースコードの多さによる影響があったので、対策をして組み込んでみたのでメモ代わりに。
環境
PHP 7.4
Composer 2.4
GitHub Actions
プロジェクトにphpcsを入れる
次のコマンドでCI適用するプロジェクトにphpcsをインストール。
composer --dev squizlabs/php_codesniffer
composer.json
のrequire-dev
に追加されます。
"require-dev": {
"squizlabs/php_codesniffer": "^3.7"
}
最初のYAML
など参考に、以下のようなYAML定義を作成。
適用するプロジェクトのPHPが7.4なのでバージョンを合わせてインストールするようにしました。
name: reviewdog
on:
pull_request:
jobs:
php-code-sniffer:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: reviewdog/action-setup@v1
with:
reviewdog_version: latest
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '7.4.33'
- name: composer install
run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
- name: run codesniffer with reviewdog
env:
REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: ./Vendor/bin/phpcs --report=emacs --standard=PSR12 ./ | reviewdog -reporter=github-pr-review -efm='%f:%l:%c:%m' -fail-on-error=true
プルリクエストでGitHub Actionsを動作させてみると、10分かかっているという。
全体で約900のPHPファイル、ソースコード行数30万行のプロジェクトでは仕方ないかもしれませんが、毎回プルリクエストで10分かかるのはちょっとつらいので工夫したいと思います。
変更後YAML
reviewdogがプルリクエストで変更のある箇所のみレポートしてくれるとはいえ、ソース規模が大きいと解析するphpcsで時間がかかるようです。
こちらを参考に、変更したファイルのみに限定してphpcsを実行するように変更してみました。
name: reviewdog
on:
pull_request:
paths:
- '**.php'
jobs:
php-code-sniffer:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.base.sha }}
- uses: actions/checkout@v3
- uses: reviewdog/action-setup@v1
with:
reviewdog_version: latest
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '7.4.33'
- name: composer install
run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
- name: Get changed files
id: get_changed_files
run: |
echo "changed_files=$(git diff --diff-filter=AM --name-only ${{ github.event.pull_request.base.sha }}.. | tr '\n' ' ' )" >> $GITHUB_OUTPUT
shell: bash
- name: Filter PHP files
id: filter_php_files
run: |
echo "php_files=$(echo ${{ steps.get_changed_files.outputs.changed_files }} | tr ' ' '\n' | grep '\.php$' | paste -sd ' ' -)" >> $GITHUB_OUTPUT
shell: bash
- name: run codesniffer with reviewdog
env:
REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: ./Vendor/bin/phpcs --report=emacs --standard=PSR12 ${{ steps.filter_php_files.outputs.php_files }} | reviewdog -reporter=github-pr-review -efm='%f:%l:%c:%m' -fail-on-error=true
git diff --diff-filter=AM --name-only ${{ github.event.pull_request.base.sha }}..
で、変更されたファイル名のみ列挙しています。
出力を次のステップで使用できるように$GITHUB_OUTPUT
を使いましたが、複数行の結果を返すとうまくいかないので、
echo "changed_files=$(git diff --diff-filter=AM --name-only ${{ github.event.pull_request.base.sha }}.. | tr '\n' ' ' )" >> $GITHUB_OUTPUT
の部分では、いったん複数行の結果をスペース区切りで1行にまとめてchanged_files
に変更ファイル名を列挙するようにしました。(複数行を$GITHUB_OUTPUT
に入れる方法はありますが、手っ取り早く1行にして出力しました。)
次のステップの
echo "php_files=$(echo ${{ steps.get_changed_files.outputs.changed_files }} | tr ' ' '\n' | grep '\.php$' | paste -sd ' ' -)" >> $GITHUB_OUTPUT
では改めてスペース区切りを改行に変更してphpファイルのみgrepし、再びスペース区切りで1行に連結しています。
プルリクエストでGitHub Actionsを動作させると、3秒で完了しています。
今回の例では、変更を加えた2ファイルのみをphpcsに渡して実行しています。
reviewdog: input data has violations
というエラーで赤×がついている(何とかしたい)のですが、やりたかったことはできた感じです。
おわりに
phpcs --report=emacs --standard=PSR12 ./ | reviewdog -reporter=github-pr-review -efm='%f:%l:%c:%m' -fail-on-error=true
で、phpcsから得られた指摘をreviewdogでプルリクエストに表示できましたが、大規模プロジェクトでは時間がかかりました。
しかし、変更したファイルに限定してphpcsを実行できれば、大規模プロジェクトでも実行時間は問題なさそうです。