ランサーズ(Lancers)エンジニアブログ > PHP > CakePHP > PHP, CakePHPバージョンアップに向けてCIで品質を担保・向上していく

PHP, CakePHPバージョンアップに向けてCIで品質を担保・向上していく

上野諒一|2017年06月27日
CakePHP

こんにちは、エンジニアの上野です。

今回はソース例や実際のサンプルソースを交えながら 「PHPバージョンアップに向けてCIで品質を担保・向上していく」と題してlancers.jp本体に導入しているCircleCIでの取り組みについてご紹介します。

導入背景

PHPバージョンアップに向けて現状のソースの品質を担保・向上していく目的で

  1. コーディング規約の遵守
  2. syntaxの先取り修正
  3. 複雑度悪化への歯止め
  4. UTの継続実施

の4つを継続的に実施していこうとなったためCircleCIを用いて順次整えていっています。
UTについては、テスト量が多く(なんと10000超!!)継続的に実施するためには時間的な制約が残っているためCIではなく毎日一回のチェックを行っています

それぞれの設定について

1. コーディング規約の遵守

cakephpのバージョンを上げていくとPSRへの適用が徐々に行われています。(直近のCakePHP3.4でもPSR-7への準拠が行われました)
そのため自分たちのソースもできるだけそこに近づけていくためにPHP-CS-Fixerを用いて規約のチェックと自動修正をできるようにしました

cd CAKE

# composer.jsonにPHP-CS-Fixerの記述を追加
vi composer.json

# .php_csを追加(幾つか方法はありますがランサーズではapp配下においています)
vi app/.php_cs
{
  "require-dev": {
    "phpmd/phpmd" : "^2.4",
    "friendsofphp/php-cs-fixer": "^2.1"
  }
}
<?php
// on cakephp1.3 APP_DIR
$finder = PhpCsFixer\Finder::create()
    ->notName('README.md')
    ->notName('.php_cs')
    ->notName('composer.*')
    ->notName('phpunit.xml*')
    ->notName('*.xml')
    ->exclude('vendor')
    ->exclude('plugin')
    ->exclude('tmp')
    ->in(__DIR__);
return PhpCsFixer\Config::create()
    ->setRules(['@PSR2' => true])  
    ->setUsingCache(false)
    ->setFinder($finder);

php_cs_fixerを起動するshellを作成
ちょっとワンライナーが細かいですが、commitのdiffを取って差分実行させています

IFS=$'\n'; COMMIT_SCA_FILES=($(git diff --name-only --diff-filter=ACMRTUXB origin/master )); unset IFS
./app/vendors/composers/friendsofphp/php-cs-fixer/php-cs-fixer fix --config=app/.php_cs -v --dry-run --diff --path-mode=intersection "${COMMIT_SCA_FILES[@]}"

2. syntaxの先取り修正

circle.ci を7.0環境でビルドしてsyntaxチェッカーを回すことで、非推奨関数を使った場合などエラーになるようにしています。
ここでも差分実行させています。(coreのソースは準拠していないものが多いので、万が一coreソースに手をいれるとなると必ずエラーになります)

machine:
  php:
    version: 7.0.4
git diff --name-status origin/master -- | grep -E '^[AUM].*\.php$'| cut -c3- | xargs -n1 php -l

3. 複雑度悪化への歯止め

PHPの静的解析ツールであるPHPMDの差分実行シェルを作りました。
また、レガシーなソースも多くあるのでPHPMDでの警告は参考に出力してリファクタ対象としてCircleCIの終了ステータスには影響を及ぼさないようにexitは0で返しています

FILESTRING=`git diff --name-status origin/master -- | grep -E '^[AUM].*\.php$'| cut -c3- | tr '\n' ',' | sed -e 's/,$//g'`

if test "${FILESTRING}"; then
  vendor/bin/phpmd $FILESTRING text codesize,controversial,design,naming,unusedcode
fi
exit 0

3つのチェッカーをtestフェーズで実行

machine:
  php:
    version: 7.0.4
test:
  orverride:
    - app/tests/php_cs_fixcer.sh
    - app/tests/php_syntax_checker.sh
    - app/tests/phpmd_checker.sh

ランサーズでは今回作成したスクリプトを流用して、app配下全ファイルに対して適用して、数日で

  • 修正が必要な数十個程度の記述を洗い出し
  • 主に改行や空白、アクセス修飾子などソースには影響しない6万行程を自動修正

を行うことができました。改善したソースを日々CircleCIがチェックしてくれています。
特にコーディング規約はルールの統一ができ余分なレビュー時間の削減にもつながっていておすすめです。

この他、pre-commitで事前にソースを自動修正させたり、新しくCakePHP3.4で作っているプロジェクトではphpunitの自動実行なども実施しています。
それらはまた追ってお伝えできればいいなと思っています。

ソースのサンプルはgithubからも閲覧できます。参考になれば嬉しいです。