不能在 composer.json scripts 中强制运行测试作为质量门禁,因为 composer 的 scripts 执行上下文不可控、无失败阻断语义、与代码变更脱节;正确做法是在 ci 的 pre-merge 阶段(如 github actions pull_request 触发器)中执行 composer install --no-dev 和测试命令,并配置失败即停。

Composer 本身不提供发布能力,也没有原生的“生命周期钩子”来注入测试拦截逻辑——你试图在 composer install 或 composer update 阶段强制运行测试并阻断流程,本质上是误用了 Composer 的定位。
为什么不能直接在 composer.json 的 scripts 里 run test 并当作质量门禁?
Composer 的 scripts 是为依赖安装/卸载、自动加载优化等构建辅助任务设计的,不是 CI 流水线执行点。它有三个硬性限制:
- 执行上下文不可控:不保证工作目录、环境变量、PHP 版本与你的测试期望一致;
- 无失败阻断语义:即使
phpunit返回非零退出码,composer install默认仍会继续(除非显式加--no-scripts或手动检查返回值); - 与代码变更脱节:它响应的是依赖变动,而非源码提交或 PR 合并,无法覆盖“改了业务逻辑但没动
composer.json”的场景。
真正该拦截的位置:CI 流水线中的 pre-merge 阶段
质量门禁必须绑定到代码合入动作,而不是包管理动作。正确路径是:
- 在 GitHub Actions / GitLab CI 的
pull_request或merge_request触发器中定义 job; - 该 job 显式执行
composer install --no-dev(仅装生产依赖)+vendor/bin/phpunit(或php artisan test等封装命令); - 配置
continue-on-error: false(GitHub)或默认失败即停(GitLab),确保任一测试失败时整个 job 退出且 PR 被阻止合并。
示例关键片段(GitHub Actions):
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
name: Test on PR
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: composer install --no-dev
- name: Run tests
run: vendor/bin/phpunit
# 自动失败即中断,无需额外判断
如果坚持要和 Composer 绑定,唯一可行的折中方案
仅适用于本地开发阶段的自我约束,**不可用于 CI 或质量守门**:
- 在
composer.json的scripts中定义"test:ci": "vendor/bin/phpunit"; - 配合
husky+lint-staged在pre-commit钩子中调用它(需确保 PHP 环境就绪); - 或在团队文档中明确要求:PR 描述里必须包含
composer run test:ci的成功截图——但这只是协作约定,无技术强制力。
这种做法无法防止绕过、无法审计、无法集成覆盖率报告,更无法替代真正的 CI 门禁。
最易被忽略的一点:很多人把 composer.lock 提交当成“已验证依赖”,其实它只保证依赖树可复现,不保证这些依赖组合下业务逻辑仍正确。真正的质量拦截点永远在代码变更之后、合入之前,而不是在依赖安装那一刻。










