关于 basercms-core-plugin-convert
这是一套将独立 baserCMS 插件并入核心 monorepo 的操作指南,面向维护者。内容涵盖目录与命名调整、根目录注册、迁移和测试配置及验证。
主要功能
- 01核心插件命名与目录规范
- 02清理独立构建和测试文件
- 03在 monorepo 中注册插件
- 04集成迁移与测试套件
- 05运行并诊断全量测试
适用场景
- 01将第三方插件升级为 baserCMS 核心插件
- 02为 monorepo 测试基础设施配置插件测试
- 03检查测试重建列表中的迁移注册
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ baserproject/ baser-skills --skill basercms-core-plugin-convert安装后在 Claude Code 中输入/basercms-core-plugin-convert确认已加载。
详细介绍
baserCMS 通常プラグイン → コアプラグイン 昇格手順
サードパーティ/単体配布の baserCMS プラグインを、baserCMS 本体(monorepo)のコアプラグインとして取り込む手順。
参照: plugins/bc-blog 等の既存コアプラグインが「正」の構成。
前提と役割分担
- バージョン移行(5.2→5.3 / PHP8.5)でのコード非推奨対応は
basercms-plugin-5x-updateスキル。- ユニットテストの実行・集計・切り分けは
basercms-unittestスキル。- 本書は「通常プラグイン構成 → コアプラグイン構成」への構造変換に絞る。
0. 大原則 / 完成形
- コアプラグインは
plugins/<bc-name>/に置かれ、自前の.git/vendor//bin//composer.lock/phpunit.xml.dist/tests/bootstrap.php/tests/TestApp/を持たない。テストはアプリ全体のテスト基盤で実行する。 - 依存・オートロード・テスト登録・CI 登録はルート側に集約する。
- 完成形の例(
plugins/bc-blog):README.md / composer.json / config/ / config.php / src/ / tests/ / webroot/(+必要ならwebpack.config.js)。
1. プラグイン名をコアプラグイン規約へ変更
既に規約準拠の名前なら本節はスキップ。命名規約の詳細リネーム作業自体は別途 namespace 一括置換が必要(本スキルは「コア化に伴う命名規約」のみ規定)。
- フォルダ名: ケバブケースにし、
bc-プレフィックスを付与する。- CamelCase はハイフン区切りへ。例:
CuMcp→bc-mcp、MyAwesomePlugin→bc-my-awesome-plugin。
- CamelCase はハイフン区切りへ。例:
- namespace / プラグインクラス: パスカルケースで
Bcプレフィックス。例:BcMcp、メインクラスBcMcpPlugin。 - composer パッケージ名:
baserproject/<bc-name>。例:baserproject/bc-mcp。 - フォルダ名(ケバブ)と namespace(パスカル)の対応:
bc-mcp⇔BcMcp。 - 命名に伴う
namespace/use/ 文字列リテラル('plugin' => 'Xxx'・URL スラッグ/xxx・コマンド名・設定キー)の一括置換、composer.jsonのname/autoload/extra.cakephp.plugin-name変更も行う(誤爆防止のため先頭トークンのみ置換し、Mcp/BcBlogのようなサブ階層名は温存)。
2. プラグイン側の standalone 成果物を削除
monorepo では不要・有害(vendor 二重化や nested git)なものを削除する。
plugins/<bc-name>/
.git ← nested リポジトリを削除(親 monorepo に取り込む)
vendor/ ← 自前 vendor を削除(ルート vendor を使う)
bin/ ← 自前 cake バイナリを削除(ROOT/bin/cake を使う)
composer.lock ← 削除
phpunit.xml.dist ← 削除(ルート phpunit.xml.dist に testsuite を登録する)
tests/bootstrap.php ← 削除(ルート tests/bootstrap.php を使う)
tests/TestApp/ ← 削除(ルート tests/TestApp を使う)
.github/ ← 単体 CI は不要(split 先リポジトリでも別管理)。既存コアに無ければ削除
.gitignore ← 既存コアに無ければ削除
VERSION.txt ← 削除(バージョンは本体 monorepo 管理になる)
CHANGELOG.md ← 削除(変更履歴も本体管理)
.phpunit.cache / .phpunit.result.cache / .DS_Store / .idea ← 削除
- 完成形は既存コア(
plugins/bc-blog)に合わせる:README.md / composer.json / config/ / config.php / src/ / tests/ / webroot/(+必要ならtemplates/・webpack.config.js)。 - ⚠️
.git削除は不可逆。nested git の独自履歴が必要なら事前に退避。
3. ルート .gitignore の調整(2 種類・向きが逆なので注意)
3-1. プラグイン本体を「追跡対象」にする(無視の除外 !)
ルート .gitignore は /plugins/* で全プラグインを無視し、コアプラグインだけ ! でホワイトリストしている。コア化したプラグインを !/plugins/<bc-name> で追跡対象に加える(これを忘れると git add されず取り込まれない)。
# plugins
/plugins/*
!/plugins/baser-core
...
!/plugins/bc-seo
!/plugins/bc-mcp ← 追加(無視の除外=追跡対象化)
/plugins/*/vendor
/plugins/*/composer.lock
- 確認:
git check-ignore -v plugins/<bc-name>/composer.json(何も返らなければ追跡対象)、git status --short plugins/<bc-name>。
3-2. webroot シンボリックリンクは「無視」する
baserCMS は webroot/<plugin_underscored> → plugins/<bc-name>/webroot のシンボリックリンクを生成する(例 webroot/bc_mcp)。実体は plugins/<bc-name>/webroot にあるため、リンク側はルート .gitignore で無視する(他コアと同じ並び)。
/webroot/bc_blog
/webroot/bc_custom_content
/webroot/bc_mcp ← 追加(アンダースコア表記)
向きに注意:
plugins/<bc-name>は追跡(!で除外)/webroot/<underscored>は無視。
4. テストを「全体実行」に載せ替える
4-1. ルート phpunit.xml.dist に testsuite を追加(⚠️ 配置順が重要)
(プラグイン側 phpunit.xml.dist は 2. で削除済み。追加するのはルート側。)
<testsuite name="BcMcp">
<directory>plugins/bc-mcp/tests/TestCase</directory>
</testsuite>
- ⚠️ 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-5x-update のテスト基盤節も参照)。
- ルート
tests/bootstrap.phpのMigrator::runMany(初期スキーマ構築)(new Migrator())->runMany([ ['plugin' => 'BaserCore'], ... ['plugin' => 'BcMcp'], // 追加 ]); - 「全テーブル drop → 再マイグレーション」をするテストの $plugins 配列(複数あり)。これらは
deleteTables()/deleteAllTables()で全テーブルを drop した後、ハードコードされたリストで再マイグレーションする。ここに無いとテーブルが復活せず、テスト順で先頭側に位置するため以降の全テストで欠落したままになる(実際に bc-mcp 追加時にoauth2_clientsがこれで消え、OAuth2 全テストが 500 になった)。判明している箇所(両方必須):plugins/baser-core/tests/TestCase/Service/BcDatabaseServiceTest.php→test_deleteTablesForMigrations()の$pluginsplugins/bc-installer/tests/TestCase/Service/Admin/InstallationsAdminServiceTest.php→test_deleteAllTables()の$plugins
$plugins = [ 'BaserCore', ..., 'BcMail', 'BcMcp', /* 追加 */ 'BcSearchIndex', ... ];
- 抜け漏れ確認(重要): この種の再構築リストは複数ファイルに散在する。必ず grep で全部洗う:
ヒットした各リストに新プラグインが入っているか確認する(1 つでも漏れると全体実行のみで落ちる)。grep -rn "'BcWidgetArea'," plugins --include="*.php" # 末尾要素で「コア列挙リスト」を検出 - 確実な検出法:
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 がルートへ集約する)。
{
"name": "baserproject/bc-mcp",
"description": "BcMcp plugin for baserCMS",
"homepage": "https://basercms.net",
"type": "cakephp-plugin",
"license": "MIT",
"vendor-dir": "../../vendor",
"require": { // 外部依存が無ければ require ごと省略可(bc-blog 等)
"php": "^8.1",
"league/oauth2-server": "^8.5"
// ...プラグイン固有の外部依存
},
"autoload": { "psr-4": { "BcMcp\\": "src/" } },
"autoload-dev": { "psr-4": { "BcMcp\\Test\\": "tests/" } }
}
- テストが他コアの Test 名前空間(
BcBlog\Test等)やApp\(TestApp)を使う場合、ルートcomposer.jsonの autoload-dev が供給するため、プラグイン側 autoload-dev は自分のTestのみでよい。
5. システム(baserCMS / monorepo)への認識
5-1. plugins/baser-core/config/setting.php の corePlugins に追加
'corePlugins' => [ ..., 'BcMail', 'BcMcp', 'BcSeo', ... ],
5-2. defaultInstallCorePlugins への追加可否を確認
baserCMS 新規インストール時に自動有効化するなら追加(BcBlog/BcMail 等と同様)。任意機能・オプトインなら追加しない(corePlugins のみ=管理画面から手動有効化)。 → プロジェクト方針をユーザーに確認する。
5-3. ルート composer.json への集約(autoload / autoload-dev / replace / require)
原則 vendor/bin/monorepo-builder merge で集約する(monorepo-builder.php の packageDirectories([... '/plugins']) が plugins/ 配下を自動走査し、各 composer.json をルートへマージ+replace を管理)。
docker compose exec <container> sh -c "cd /var/www/html && vendor/bin/monorepo-builder merge"
- ⚠️ merge は全パッケージのバージョン整合をガードする。monorepo 外のローカル専用プラグイン(例 EgaRyu / BcUpdateSupporter 等)に版差があると
Found conflicting package versionsでブロックされる。その場合は当該プラグインの版を揃えるか、ブロック時は merge と同等の編集を手動で行う(下記)。 - merge 相当の手動編集(ルート
composer.json):autoload.psr-4に"BcMcp\\": "plugins/bc-mcp/src/"autoload-dev.psr-4に"BcMcp\\Test\\": "plugins/bc-mcp/tests/"requireにプラグインの外部依存(league/oauth2-server等、ext-*含む)replaceに"baserproject/bc-mcp": "<monorepo版>"(他コアに合わせる)
- 反映後、依存取得とオートロード再生成:
docker compose exec <container> sh -c "cd /var/www/html && composer update <added-packages> --no-interaction"
5-4. phpdoc.dist.xml に src パスを追加
<path>plugins/bc-mail/src</path>
<path>plugins/bc-mcp/src</path>
<path>plugins/bc-search-index/src</path>
5-5. .github/workflows/split_monorepo.yml に split 対象を追加
- local_path: 'bc-mcp'
split_repository: 'bc-mcp'
6. 确认全量测试的执行情况
docker compose exec <container> sh -c "cd /var/www/html && vendor/bin/phpunit --testsuite BcMcp"
- standalone 专用 bootstrap 提供的前提条件(外部进程、环境变量、密钥等)在全量 bootstrap 中不存在,因此迁移后容易出现失败。典型示例:
- 依赖外部进程:代理集成测试等需要实际服务器进程时,standalone 中由 bootstrap 启动。全量测试中则应在相关测试开头启动(如果已启动则复用)。使用
ROOT/bin/cake <command>启动(应用的 cake 以及已在核心中注册的命令)。不要在整个setUp中添加守卫,而是仅在需要服务器的单个测试中添加(避免影响其他测试,导致其等待启动)。 ⚠️ 仅通过“进程存在(pid 文件)”判断是否已启动并不充分。即使进程已启动,端口也可能还未完成 bind,导致代理连接目标(例如127.0.0.1:{port})连接被拒绝=500(本地通过、仅 CI 失败的典型情况)。请轮询等待,直到实际可以连接。 无法连接时,不要用markTestSkipped隐藏问题,而应使用assertTrue等明确使测试失败(跳过会掩盖服务器启动故障)。本方针也记载于.github/instructions/basercms.instructions.md的“开发・测试・构建”部分。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-5x-update技能(T-3~T-5)。
- 依赖外部进程:代理集成测试等需要实际服务器进程时,standalone 中由 bootstrap 启动。全量测试中则应在相关测试开头启动(如果已启动则复用)。使用
- 最后也要确认全量测试没有回归问题。
7. 确认用于 monorepo split 的只读仓库
split_monorepo 会将各插件 push 到 baserproject/<split_repository> 下的只读仓库。如果目标仓库不存在,split 就会失败,因此请事先确认仓库是否已创建。
gh repo view baserproject/bc-mcp --json name,url,visibility
- 如果尚未创建,请创建(这是外部且不可逆的操作。执行前请向用户确认)。
- 先确认是否可以通过
gh创建:如果认证账号是目标组织(baserproject)的 admin,且令牌具有reposcope,就可以创建。gh auth status # ログイン/スコープ確認(repo が必要) gh api user/memberships/orgs/baserproject # role が "admin" か確認 - 创建时请遵循现有 split 仓库(例如
baserproject/bc-blog)的设置:public / 描述[READ-ONLY] <PascalName>/ homepagehttps://basercms.net。gh repo create baserproject/bc-mcp --public -d "[READ-ONLY] BcMcp" -h https://basercms.net - 如果没有权限,请委托 baserCMS 管理员创建(不要擅自创建到其他 owner 名下)。
检查清单
- 插件名称符合核心规范(
bc-前缀/kebab 格式/Bcnamespace/baserproject/bc-*) - 删除
.git/vendor/bin/composer.lock/phpunit.xml.dist/tests/bootstrap.php/TestApp/VERSION.txt/CHANGELOG.md - 根目录
.gitignore:通过!/plugins/<bc-name>将其纳入追踪 + 忽略/webroot/<underscored> - 在根目录
phpunit.xml.dist中添加 testsuite - 在迁移列表的所有位置添加(如果存在迁移):根目录
tests/bootstrap.php的runMany+BcDatabaseServiceTest::test_deleteTablesForMigrations的$plugins - 将插件
composer.json简化为核心格式(保留外部 require) - 添加到
corePlugins/ 确认defaultInstallCorePlugins的方针 - 汇总到根目录
composer.json(合并或手动处理)+composer update - 添加到
phpdoc.dist.xml/split_monorepo.yml - 全量测试中的 testsuite 正常(外部进程依赖在 setUp 中启动)
- 确认用于 split 的只读仓库存在
备注:添加或更新到
.claude/skills/的技能不会立即反映到当前会话中(会在启动时 discover)。重启 Claude Code 后,即可通过/basercms-core-plugin-convert调用。