Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
e9208c7
スキルを更新
ryuring Jun 20, 2026
0fa1d56
スキルを更新
ryuring Jun 20, 2026
fdc0bfa
bc-mcpプラグインを追加
ryuring Jun 20, 2026
962dfa9
ユニットテストへの影響を調整
ryuring Jun 21, 2026
68b4c65
コアプラグインコンバートスキルを更新
ryuring Jun 21, 2026
cae7231
Merge branch '5.4.x' into dev-agentic
ryuring Jun 21, 2026
37638c6
全体テストで BcMcp のテーブルが消失する問題を修正
ryuring Jun 21, 2026
0fde04e
MCPプロキシ統合テストをサーバー起動不可環境でスキップ
ryuring Jun 21, 2026
56c36db
MCP統合テスト: プロセス存在でなく実ポート到達を待つ
ryuring Jun 21, 2026
e182604
MCP統合テスト: 到達不可時は skip でなく失敗させる
ryuring Jun 21, 2026
d7661cb
指示書に外部プロセス依存テストの方針を明記
ryuring Jun 21, 2026
fdab6b5
MCP統合テスト: 到達不可時にサーバー起動ログを失敗メッセージへ出力
ryuring Jun 21, 2026
d09245b
MCP統合テスト: テスト内で BcMcp を有効化してサーバーを起動可能にする
ryuring Jun 21, 2026
2b33d7c
Merge branch '5.3.x' into dev-agentic
ryuring Jun 22, 2026
f3796b7
BcMcp: PHP8.1互換のまま非推奨を解消(抑制なし)
ryuring Jun 23, 2026
e8feb58
スキル更新: 非推奨対応の知見を追記
ryuring Jun 23, 2026
323f353
MCP統合テスト: 子プロセスを test 接続で起動しコマンド未登録を解消
ryuring Jun 23, 2026
85c3e68
MCP統合テスト: 常駐サーバーのリークによるCIハングを解消
ryuring Jun 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -87,24 +87,41 @@ baserCMS は `webroot/<plugin_underscored>` → `plugins/<bc-name>/webroot` の

## 4. テストを「全体実行」に載せ替える

### 4-1. ルート `phpunit.xml.dist` に testsuite を追加
### 4-1. ルート `phpunit.xml.dist` に testsuite を追加(⚠️ 配置順が重要)
(プラグイン側 phpunit.xml.dist は 2. で削除済み。**追加するのはルート側**。)
```xml
<testsuite name="BcMcp">
<directory>plugins/bc-mcp/tests/TestCase</directory>
</testsuite>
```

### 4-2. ルート `tests/bootstrap.php` の Migrator にプラグインを追加
プラグインが DB マイグレーション(`config/Migrations`)を持つ場合、全体 bootstrap の `runMany` に追加しないとテスト用 DB にテーブルが作られず失敗する。
```php
(new Migrator())->runMany([
['plugin' => 'BaserCore'],
...
['plugin' => 'BcMcp'], // 追加
...
]);
```
- **⚠️ DB テーブルを持つが `defaultInstallCorePlugins` に入れないプラグインは、`BcInstaller` の testsuite より「前」に置く**。`BcInstaller` の `InstallationsControllerTest::testStep3`(`mode=createDb`)は**実際のインストール処理**で全テーブルを drop し **defaultInstall のプラグインのみ**再作成する。後ろに置くと、自プラグインのテーブルが作り直されないまま自テストが走り全アクション 500 になる(既存の非 default コア=BcContentLink/BcCustomContent 等もすべて BcInstaller より前に並んでいる)。
- 例: `... BcSeo` の直後・`BcInstaller` の直前に `BcMcp` を置く。
- defaultInstall に入れる方針なら BcInstaller の後でも可(createDb が作り直すため)。

### 4-2. マイグレーション・プラグインリストへ追加(⚠️ 複数箇所ある)
プラグインが DB マイグレーション(`config/Migrations`)を持つ場合、**テスト用 DB にテーブルを作る/再構築するプラグインリストすべて**に追加する。1 箇所でも漏れると、全体実行時にそのプラグインのテーブルだけ欠落し `Could not describe columns on <table>`(→ コントローラ初期化失敗で当該プラグインの全アクション 500)になる。**単独 testsuite では通り、全体実行でのみ落ちる**のが特徴(切り分けは `basercms-plugin-migration` のテスト基盤節も参照)。

1. **ルート `tests/bootstrap.php` の `Migrator::runMany`**(初期スキーマ構築)
```php
(new Migrator())->runMany([
['plugin' => 'BaserCore'],
...
['plugin' => 'BcMcp'], // 追加
]);
```
2. **「全テーブル drop → 再マイグレーション」をするテストの $plugins 配列(複数あり)**。これらは `deleteTables()`/`deleteAllTables()` で**全テーブルを drop** した後、ハードコードされたリストで再マイグレーションする。ここに無いとテーブルが復活せず、テスト順で先頭側に位置するため**以降の全テストで欠落したまま**になる(実際に bc-mcp 追加時に `oauth2_clients` がこれで消え、OAuth2 全テストが 500 になった)。**判明している箇所(両方必須)**:
- `plugins/baser-core/tests/TestCase/Service/BcDatabaseServiceTest.php` → `test_deleteTablesForMigrations()` の `$plugins`
- `plugins/bc-installer/tests/TestCase/Service/Admin/InstallationsAdminServiceTest.php` → `test_deleteAllTables()` の `$plugins`
```php
$plugins = [ 'BaserCore', ..., 'BcMail', 'BcMcp', /* 追加 */ 'BcSearchIndex', ... ];
```
- **抜け漏れ確認(重要)**: この種の再構築リストは複数ファイルに散在する。**必ず grep で全部洗う**:
```bash
grep -rn "'BcWidgetArea'," plugins --include="*.php" # 末尾要素で「コア列挙リスト」を検出
```
ヒットした各リストに新プラグインが入っているか確認する(1 つでも漏れると全体実行のみで落ちる)。
- **確実な検出法**: `BcTestCase::setUp` 冒頭に「対象テーブルの存在を各テストで記録」する一時計測を仕込み、**全 suite を実行**して `OK→MISSING` 転移点を洗い出す(転移直前の OK テストが drop 元)。全 dropper を一度に特定できる。確認後に計測は除去する。
- 切り分け診断(どのテストでテーブルが消えるか): `BcTestCase::setUp` 冒頭に一時計測(`ConnectionManager::get('test')->getSchemaCollection()->listTables()` に対象テーブルが在るか各テストで記録)を仕込み、最初に MISSING になる直前の OK テストが drop 元。確認後に必ず除去する。

### 4-3. プラグイン `composer.json` をコアプラグイン形式へ簡素化
`require-dev`(baser-core 等)・`scripts`・`config.allow-plugins`・`minimum-stability` は削除。`vendor-dir` を足す。**外部ランタイム依存がある場合は `require` に残す**(後で monorepo-builder merge がルートへ集約する)。
Expand Down Expand Up @@ -177,10 +194,24 @@ docker compose exec <container> sh -c "cd /var/www/html && vendor/bin/monorepo-b
docker compose exec <container> sh -c "cd /var/www/html && vendor/bin/phpunit --testsuite BcMcp"
```
- standalone 専用 bootstrap が用意していた前提(外部プロセス・環境変数・鍵等)が**全体 bootstrap には無い**ため、移行直後は失敗が出やすい。代表例:
- **外部プロセス依存**: プロキシ統合テスト等が**実サーバープロセス**を要する場合、standalone では bootstrap が起動していた。全体側では**該当テストの `setUp` で起動**する(起動済みなら再利用)。起動コマンドは `ROOT/bin/cake <command>`(アプリの cake と、コア登録済みのコマンド)を使う。
- **外部プロセス依存**: プロキシ統合テスト等が**実サーバープロセス**を要する場合、standalone では bootstrap が起動していた。全体側では**該当テストの先頭で起動**する(起動済みなら再利用)。起動コマンドは `ROOT/bin/cake <command>`(アプリの cake と、コア登録済みのコマンド)を使う。`setUp` 全体ではなく**サーバーが要る個別テストにだけ**ガードを入れる(他テストに起動待ちを波及させない)。
**⚠️ 起動判定は「プロセス存在(pidファイル)」だけでは不十分**。プロセスは起きてもポートの bind が間に合わず、プロキシ接続先(例 `127.0.0.1:{port}`)が接続拒否=500 になる(ローカルは通り CI でのみ落ちる典型)。**実際に接続できるまでポーリングで待つ**こと。
**到達できない場合は `markTestSkipped` で隠さず `assertTrue` 等で明示的に失敗させる**(スキップはサーバー起動不具合を握りつぶす)。本方針は `.github/instructions/basercms.instructions.md`「開発・テスト・ビルド」にも記載。
```php
$manager = new McpServerManger();
if (!$manager->isServerRunning()) { $manager->startMcpServer($manager->getServerConfig()); }
private function requireMcpServer(): void {
$m = new McpServerManger();
$cfg = $m->getServerConfig();
if (!$m->isServerRunning()) { $m->startMcpServer($cfg); }
$host = $cfg['host'] ?? '127.0.0.1'; $port = (int)($cfg['port'] ?? 3000);
$deadline = microtime(true) + 15.0; $reachable = false;
while (microtime(true) < $deadline) {
$c = @fsockopen($host, $port, $e, $s, 1);
if ($c) { fclose($c); $reachable = true; break; }
usleep(300000);
}
$this->assertTrue($reachable, "MCP サーバー({$host}:{$port})へ接続できませんでした");
}
// 実サーバーが要るテストの先頭で $this->requireMcpServer();
```
- **マイグレーション未実行**: 4-2 の追加漏れ → テーブル不在で失敗。
- **プラグイン未 bootstrap / サブプラグイン未ロード** 等は `basercms-plugin-migration` スキル(T-3〜T-5)参照。
Expand Down Expand Up @@ -214,7 +245,7 @@ gh repo view baserproject/bc-mcp --json name,url,visibility
2. [ ] `.git` / `vendor` / `bin` / `composer.lock` / `phpunit.xml.dist` / `tests/bootstrap.php` / `TestApp` / `VERSION.txt` / `CHANGELOG.md` 削除
3. [ ] ルート `.gitignore`: `!/plugins/<bc-name>` で追跡対象化 + `/webroot/<underscored>` を無視
4. [ ] ルート `phpunit.xml.dist` に testsuite 追加
5. [ ] ルート `tests/bootstrap.php` の Migrator に追加(マイグレーションがある場合)
5. [ ] マイグレーション・リスト全箇所に追加(マイグレーションがある場合): ルート `tests/bootstrap.php` の `runMany` + `BcDatabaseServiceTest::test_deleteTablesForMigrations` の `$plugins`
6. [ ] プラグイン `composer.json` をコア形式に簡素化(外部 require は残す)
7. [ ] `corePlugins` に追加 / `defaultInstallCorePlugins` は方針確認
8. [ ] ルート `composer.json` に集約(merge もしくは手動)+ `composer update`
Expand Down
1 change: 1 addition & 0 deletions .agents/skills/basercms-plugin-migration/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
name: basercms-plugin-migration
description: 'baserCMS プラグインを 5.2系 から 5.3系(PHP 8.5 / CakePHP 5.2.x ベース、開発中)へ移行する際の baserCMS 固有の破壊的変更・非推奨・テスト基盤対応のレシピ集。「プラグインを5.3に対応」「baserCMS 5.3 マイグレーション」「PluginCollection::create(): $config null given」「Plugin named X is already loaded(統合テスト)」「BcApp.testAppPluginsToLoad」「plugins.php の null → []」「Class BcCcFile\... not found(サブプラグイン未ロード)」「Cannot set a node''s parent as itself(TreeBehavior + Content フィクスチャ)」「validateUnique(): Argument #2 not passed(vendor の CakePHP 二重ロード)」「MissingTemplateException error500.php でテストの真因がマスクされる」「BcFile コンストラクタ/delete() パス指定の非推奨」等、プラグイン本体・テスト基盤の移行時に参照する。PHP本体起因は php-migration、CakePHP本体起因は cakephp-migration、テスト実行手順は basercms-unittest スキルを参照。新しい baserCMS バージョン対応時は本書にバージョン別追記する。'
license: MIT
---

# baserCMS プラグイン バージョン移行ガイド(5.2 → 5.3)
Expand Down
14 changes: 13 additions & 1 deletion .agents/skills/basercms-unittest/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
name: basercms-unittest
description: baserCMS(CakePHP5 / PHPUnit)のユニットテストをローカル Docker 環境で実行・調査する手順。「ユニットテストを実行して」「全テストを走らせて」「このテストだけ流して」「テスト失敗を調べて」等のときに参照する。コンテナ名・実行コマンド・権限自動承認のためのコマンド整形・失敗の集計と切り分け方を収録。
license: MIT
---

# baserCMS ユニットテスト実行ガイド(ローカル)
Expand All @@ -22,8 +23,19 @@ baserCMS のユニットテストは Docker コンテナ上で実行する。実

## 実行コマンド

### ⚠️ 最重要:phpunit の前に必ず `bin/cake setup test` を実行する
`vendor/bin/phpunit` を**直叩きしない**。先に `bin/cake setup test`(テスト DB の初期化)を実行すること。正規フローは `composer run-script test`(=`bin/cake setup test` → phpunit)で、CI(`test.yml`)もこれを使う。
- **省略すると何が起きるか**: テスト DB に前回実行や初期データが残り、`Fixture`/`Factory` の INSERT が **PK 重複(例: `Duplicate entry '1' for key 'content_folders.PRIMARY'`)** や `table doesn't exist` で大量に落ちる。**コードは正しいのにテストだけ失敗**するため、退行と誤認しやすい(実際にこの取り違えが発生した)。
- 単一テストでも、DB を使うものは事前に一度 `setup test` しておくと安全。
```
# 正規フロー(推奨): setup test 込み
docker exec basercms sh -c 'cd /var/www/html && composer run-script test 2>&1 | tail -45'
# 個別に phpunit を回す場合も、先に setup test を一度実行しておく
docker exec basercms sh -c 'cd /var/www/html && bin/cake setup test 2>&1 | tail -3'
```

### 全テスト(フルスイート)
出力が大きいのでコンテナ内のファイルに保存し、末尾だけ表示する。完走まで約10分強かかるため、必要に応じてバックグラウンド実行する。
出力が大きいのでコンテナ内のファイルに保存し、末尾だけ表示する。完走まで約10分強かかるため、必要に応じてバックグラウンド実行する。**事前に `bin/cake setup test` 済みであること**。
```
docker exec basercms sh -c 'cd /var/www/html && vendor/bin/phpunit --no-coverage > /tmp/phpunit_full.log 2>&1; tail -45 /tmp/phpunit_full.log'
```
Expand Down
1 change: 1 addition & 0 deletions .agents/skills/cakephp-migration/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
name: cakephp-migration
description: baserCMS の CakePHP バージョンアップ(5.0 → 5.1 → 5.2 ~)対応の非推奨・破壊的変更パターン集と修正レシピ。「Association alias already set」「A validation rule with the name already exists」「_Token not found」「headers already sent」「Plugin named X is already loaded」「ResultSet/PaginatedResultSet のエラー」「order()/group() 非推奨」「イベントリスナーの戻り値非推奨」「find('all', $options) 非推奨」「Table::get の配列 options 非推奨/名前付き引数」「配列条件の null 値で例外」「_cake_core_ キャッシュ設定」「pluginBootstrap で後続プラグインの setting.php が読まれず Configure が null(live イテレーション)」「_checkFilePath で .. テンプレートが MissingPluginException/500」「TreeBehavior でルートに parent_id=null を入れて lft/rght 破損」「Entity::set 配列一括の非推奨」「AbstractMigration/AbstractSeed 非推奨 → BaseMigration/BaseSeed(cakephp/migrations 4.5+)」「config/routes.php の fallbacks() でテストのみ 404」等、CakePHP本体・関連パッケージ起因の問題の調査・修正時に参照する。新しい CakePHP バージョン対応時は本書にバージョン別追記する。PHP本体起因の問題は php-migration スキルを参照。
license: MIT
---

# CakePHP バージョン移行ガイド(baserCMS)
Expand Down
15 changes: 14 additions & 1 deletion .agents/skills/php-migration/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
name: php-migration
description: baserCMS の PHP バージョンアップ(8.2/8.4/8.5 ~)対応の非推奨・破壊的変更パターン集と修正レシピ。「暗黙的nullableの非推奨警告」「Creation of dynamic property ... is deprecated」「fgetcsv の escape 警告」「ReflectionProperty::setValue の非推奨」「(integer)/(boolean) 等の非正規キャスト非推奨」「null を配列オフセットに使う非推奨」「curl_close/imagedestroy 等の自動解放関数非推奨」等、PHP本体起因のアップグレード警告/エラーの調査・修正時に参照する。新しい PHP バージョン対応時は本書にバージョン別追記する。CakePHP本体起因の問題は cakephp-migration スキルを参照。
license: MIT
---

# PHP バージョン移行ガイド(baserCMS)
Expand Down Expand Up @@ -170,7 +171,19 @@ $code = str_increment($code);
`__serialize()` / `__unserialize()` を使う(PHP7 互換が不要なら移行)。

### 6. `$http_response_header` の非推奨
スーパーグローバル `$http_response_header` が非推奨。`http_get_last_response_headers()` を使う。**※ `http_get_last_response_headers()` は 8.4+。8.1 維持中は `$http_response_header` のまま据え置く。**
スーパーグローバル `$http_response_header` が 8.5 で非推奨。`http_get_last_response_headers()` を使う。**※ `http_get_last_response_headers()` は 8.4+** なので、8.1 互換を維持するなら**素朴な置換は不可**(8.1〜8.3 で undefined function の fatal になる)。
- **8.1〜8.5 を一度に満たす互換パターン**(推奨): 関数があれば使い、無ければ従来のスーパーグローバルにフォールバックする。8.5 では関数経由になるので非推奨を回避でき、8.1〜8.3 では関数が無いので `if` を素通りし、その下の `isset($http_response_header)`(直前の `file_get_contents` 等が設定するスーパーグローバル)を読む——どのバージョンでも fatal にならない。
```php
// file_get_contents() 等の HTTP 取得直後
if (function_exists('http_get_last_response_headers')) { // 8.4+
$http_response_header = http_get_last_response_headers();
}
if (isset($http_response_header)) { // 8.1〜8.3 は従来のスーパーグローバルを参照
foreach ($http_response_header as $header) { /* Content-Type 抽出等 */ }
}
```
- **症状**: 8.5+テスト(`Error.errorLevel = E_ALL`)では、このスーパーグローバル参照の非推奨が顕在化し、ファイル取得系を通るテストが不安定化・失敗することがある(baserCMS 実績: `BcMcp\Mcp\BaseMcpTool` の URL 画像取得で Content-Type 判定に使用)。
- 単純に「8.1 維持中は据え置き」でも 8.5 では警告のみで動作はするが、テストを通すなら上記の互換パターンで解消する方が確実。

### 7. バッククォート演算子の非推奨
`` `command` ``(`shell_exec()` のエイリアス)が非推奨。`shell_exec()` を直接使う。
Expand Down
1 change: 1 addition & 0 deletions .claude/skills/basercms-core-plugin-convert
1 change: 1 addition & 0 deletions .claude/skills/basercms-plugin-migration
Loading
Loading