Skip to content

ci: 静的解析 (Rector / PHPStan / php-cs-fixer) の導入とキャッシュ残留フレークの修正 - #100

Merged
dotani1111 merged 2 commits into
EC-CUBE:4.4from
dotani1111:dev/4.4-static-analysis
Aug 12, 2026
Merged

ci: 静的解析 (Rector / PHPStan / php-cs-fixer) の導入とキャッシュ残留フレークの修正#100
dotani1111 merged 2 commits into
EC-CUBE:4.4from
dotani1111:dev/4.4-static-analysis

Conversation

@dotani1111

Copy link
Copy Markdown

概要(Overview・Refs Issue)

#95 のレビューでご提案いただいた静的解析(Rector / PHPStan / php-cs-fixer)を導入します。
あわせて、同レビュー対応中に見つかった CI のフレーク(プラグインルートが載らず PHPUnit が落ちる)を修正します。

方針(Policy)

  • 静的解析の構成は coupon-plugin (4.4) に揃える
  • 設定ファイルは配布パッケージに含めない(main.yml のパッケージングで除外)
  • フレーク修正は cache:clear の判定に頼らず、キャッシュディレクトリを直接削除する方式

実装に関する補足(Appendix)

静的解析ジョブの追加

  • Resource/rector.php … PHP 8.2 / Symfony 7.4 / Doctrine セット。パスは本プラグインの構成に合わせています
  • phpstan.neon.dist … level 6。objectManagerLoader がカーネルを起動するため、CI では本体 + SQLite をセットアップしてから実行します
  • Resource/.php-cs-fixer.dist.php … ライセンスヘッダの URL は本体 4.4 の .php-cs-fixer.dist.php に合わせ http:// としています(coupon-plugin は https:// のため、そのまま流用すると全ファイルにヘッダ差分が出ます)
  • ci.yml に static-analysis ジョブを追加(DB 種別に依存しないため SQLite 1 構成で一度だけ実行)

検出された差分は次の 2 点で、いずれも本 PR に含めています。

  • php-cs-fixer: コンストラクタ引数の整形 1 ファイル(挙動への影響なし)
  • PHPStan: doctrine.columnType 4 件 → ignoreErrors で抑止

後者は Entity のプロパティが ?string / ?int で DB カラムが not-null という不一致の指摘です。
Symfony のフォームはバリデーションの前にデータマッピングを行い、空白のみの入力が empty_data で null になるため、プロパティ・setter を非 nullable にすると保存時に TypeError で 500 になります(#95 の blocker 指摘と同じ経路)。
実行時は Doctrine が必ず値を入れるため実害はなく、coupon-plugin と同じ抑止を入れています。

CI フレークの修正

eccube:plugin:enable して cache:warmup したのに、プラグインのルートがコンテナに載らず PHPUnit が RouteNotFound で落ちる」というフレークです。
4.4 マージ後の run で発生しています(upstream: 1/8 失敗、fork: 5/8 失敗)。

原因は Symfony CacheClearCommand の「Cache is fresh」ショートカットです(vendor/symfony/framework-bundle/Command/CacheClearCommand.php:124)。

if ($_SERVER['REQUEST_TIME'] <= filemtime($containerFile) && filemtime($containerFile) <= time()) {
    // fresh とみなし、--no-warmup 時はコンテナを消さずに正常終了する

この比較が秒精度のため、次のシーケンスが同一秒に収まると発症します。

  1. eccube:plugin:enable が自身の kernel boot 時(DB が enabled=0 の時点)にプラグインルートなしのコンテナをダンプする(T 秒)
  2. enable 後のサブプロセス cache:clear --no-warmupPluginCommandTrait)が T 秒内に起動 → fresh 判定でコンテナを消さない
  3. 次ステップの cache:clear --no-warmup も T 秒内なら同様に素通り
  4. cache:warmup はコンテナをコンパイルせず既存ダンプを再利用 → ルートなしのまま [OK]

裏取りはコマンドの boot 時間で取れています(約 2 秒 = コンパイル / 約 0.2 秒 = ダンプ再利用)。
失敗した job はすべて Plugin Enabled 以降に一度もコンパイルが起きていませんでした。

修正は rm -rf var/cache/test での物理削除です。
コンテナが存在しなければ warmup の boot が必ず enable 後の DB を読んでコンパイルし直すため、タイミング依存が消えます。

なお同型の問題は本体の CacheUtil::forceClearCache()cache:clear を同一プロセスで実行するため fresh 判定が常に成立)にもあり、こちらは本体側で別途対応を検討します。

テスト(Test)

  • Rector: 差分なし
  • php-cs-fixer: 検出 1 件を適用済み、以後差分なし
  • PHPStan level 6: エラーなし
  • PHPUnit: 18 tests / 47 assertions すべて成功(ローカル PHP 8.3 / SQLite)
  • fork で全ジョブ緑を 2 run 確認(8 マトリクス + static-analysis): run 1 / run 2

マイナーバージョン互換性保持のための制限事項チェックリスト

  • 既存機能の仕様変更はありません
  • フックポイントの呼び出しタイミングの変更はありません
  • フックポイントのパラメータの削除・データ型の変更はありません
  • twigファイルに渡しているパラメータの削除・データ型の変更はありません
  • Serviceクラスの公開関数の、引数の削除・データ型の変更はありません
  • 入出力ファイル(CSVなど)のフォーマット変更はありません

※ PHP の変更は php-cs-fixer による整形 1 ファイルのみで、挙動の変更はありません。
※ 追加した設定ファイルはパッケージングで除外するため、配布物にも変更はありません。

レビュワー確認項目

  • 動作確認
  • コードレビュー
  • E2E/Unit テスト確認(テストの追加・変更が必要かどうか)
  • 互換性が保持されているか
  • セキュリティ上の問題がないか
    • 権限を超えた操作が可能にならないか
    • 不要なファイルアップロードがないか
    • 外部へ公開されるファイルや機能の追加ではないか
    • テンプレートでのエスケープ漏れがないか

🤖 Generated with Claude Code

dotani1111 and others added 2 commits August 10, 2026 11:06
- coupon-plugin ほか他プラグインと同じ構成に揃える
- phpstan は objectManagerLoader がカーネルを起動し EccubeExtension が dtb_plugin を
  読むため本体と DB が必要。DB 種別に依存しないので SQLite 1 構成で実行する
- Entity のプロパティは ?type だが該当カラムは DB 上 not-null。Symfony のフォームは
  バリデーションの前にデータマッピングを行い空文字が null になるため非 nullable に
  できず、doctrine.columnType を ignoreErrors に入れる
- php-cs-fixer が検出したコンストラクタ引数の整形を反映する
- 配布パッケージには静的解析の設定を含めない

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Symfony の CacheClearCommand は REQUEST_TIME と filemtime の秒精度比較で
  コンテナを fresh とみなし、削除せずに正常終了することがある
- eccube:plugin:enable が有効化前の boot でダンプしたコンテナ (プラグイン
  ルートなし) が同一秒内の cache:clear を素通りすると、cache:warmup は
  既存ダンプを再利用するためルートが欠けたまま phpunit に到達する
- cache:clear の判定に頼らず var/cache/test を直接削除する

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0970b4cb-2318-4054-a9f0-f9d323a6726a

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@dotani1111
dotani1111 merged commit f4c1444 into EC-CUBE:4.4 Aug 12, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants