UnoPim Verify 是 UnoPim 项目中的完成验证门禁技能,定位为“完成门槛”:任何变更在被宣布完成之前,必须按顺序通过全部六项门禁。所有命令应优先通过 unopim-exec 解析,以处理容器与宿主机的包装差异、端口、数据库与 Elasticsearch 覆盖参数。
六项门禁(按顺序)
-
Pint:运行 vendor/bin/pint --test,预设为 laravel,要求零问题;可先运行 vendor/bin/pint 自动修复。
-
Pest:运行 composer test,要求所有测试通过。CI 还会在 PostgreSQL 上运行测试套件(phpunit.pgsql.xml);涉及数据库的变更不得使用仅 MySQL 支持的 SQL。
-
Larastan:运行 composer phpstan,要求零错误。
-
Rector:运行 composer rector-dry,要求零待处理重构;若有报告则用 composer rector 应用。
-
Playwright:在 tests/e2e-pw 目录下运行 npx playwright test;当视图、JS 或翻译发生变更时必须运行。否则需明确声明跳过(例如“无视图/JS/翻译变更——已跳过 Playwright”),绝不能静默跳过。
-
翻译:运行 php artisan unopim:translations:check,要求全部 33 个语言区域完整且零错误。
使用方式
verify.sh 按上述顺序运行全部六项,并跳过本次变更未触及的门禁,最后在摘要中报告每项门禁的结果。示例:
mapfile -t CHANGED < <(git -C "$PROJECT_ROOT" diff --name-only HEAD) skills/unopim-verify/verify.sh "$PROJECT_ROOT" --changed "${CHANGED[@]}"
脚本调用 composer 脚本所包装的二进制文件——vendor/bin/pest 与 vendor/bin/phpstan analyse --memory-limit=2G——以便每次调用时应用 PEST_ENV 覆盖;Rector 仍通过 composer rector-dry 执行。
展开变量时需加引号,因为包含空格的路径应被视为一个路径而非两个。若不传 --changed 列表,则所有门禁都适用。退出码为 0 表示所有适用门禁均通过;随后脚本会写入 $PROJECT_ROOT/.verify-stamp(Unix 秒数),Stop 钩子读取该文件以区分新鲜验证与过期验证。Rector 是运行器中唯一的建议性门禁:仓库范围的 dry run 会报告本次变更未引入的既有技术债,因此会醒目报告但不影响退出状态;但非空的 rector 报告仍需在合并前清除。
规则
有两项要求没有 diff 级别的检查,通过不同方式强制执行,详见 strict-mode.md:在测试环境中通过 Model::preventLazyLoading() 检查 N+1 问题;通过按包设置 Larastan 级别和忽略列表棘轮来要求显式类型。
必须修复每个失败的根本原因。严禁抑制:不得在 phpstan.neon 中添加 ignoreErrors 或基线条目,不得在 rector.php 中添加 withSkip(),不得使用内联 @phpstan-ignore,不得跳过或删除测试以求变绿。
需明确报告每项门禁的结果。未运行的门禁即视为失败。
切勿自行写入 .verify-stamp。该文件由 verify.sh 在所有适用门禁返回 0 后才写入。手写它会使得 Stop 钩子在没有实际验证的情况下变绿,这属于伪造验证记录,而非通过验证。
Rector 在运行器中是建议性的,但在本列表中具有阻塞性,这种差异是真实存在的:composer rector-dry 是仓库范围的,仅将其限定到变更文件也无法解决,因为 Rector 是按文件报告的——向遗留文件添加一行也会因本次变更未引入的技术债而失败。因此 packages/Webkul/Admin 和 packages/Webkul/AdminApi(两者在 rector.php 中均被跳过)中的提升与返回类型仅为审查项。请在合并前自行清除 rector 报告。
若 unopim-exec 不可用,请自行检查 .env 和 docker-compose.yml,说明所选择的包装方式,然后继续;绝不能因为解析器技能缺失而跳过任何门禁。