CI中必须用composer install而非update,因其严格按已提交的composer.lock还原精确版本、顺序与依赖树,确保构建可重现;update会重算依赖、生成新lock,绕过代码审查引发BC break或Fatal error。

CI/CD 中必须用 composer install,绝不能用 composer update —— 否则构建不可重现,线上行为随时漂移。
为什么 CI 里 composer install 是唯一安全选项
CI 不是开发机,它不参与“选版本”的决策。composer update 会重算整个依赖树、生成新 composer.lock,等于绕过代码审查偷偷升级包。昨天通过的流水线,今天可能因 monolog/monolog 的一个 patch 版本引入 BC break 或 Fatal error: Class 'PHPUnit\Framework\TestCase' not found。
composer install 则严格按已提交的 composer.lock 还原:版本、顺序、嵌套关系全部锁定。前提是 Git 仓库里必须有它——CI 不会帮你生成,没这个文件,命令直接报错退出。
- 常见错误现象:
Root package 'xxx' cannot be found,大概率是漏提composer.lock - 多包项目(monorepo)中,每个子包目录下都得有自己独立的
composer.lock,否则install会自动退化为update - GitLab / GitHub Actions 默认拉取 clean checkout,只靠
composer.lock启动安装
composer install 在 CI 中必须加的三个参数
漏掉任一个,轻则 autoload 慢 2–3 倍,重则运行时崩溃。它们不是可选项,是生产构建的底线:
-
--no-dev:跳过require-dev里的包。否则phpunit、symfony/debug-bundle会打进镜像,还可能触发class_exists('PHPUnit\Framework\TestCase')这类运行时 fatal -
--optimize-autoloader(或-o):生成vendor/composer/autoload_classmap.php,把 PSR-4 映射编译成静态数组,跳过每次 class 查找时的文件系统遍历 -
--classmap-authoritative:告诉 autoloader “classmap 里没有的类,就真的不存在”,彻底禁用file_exists()探测——既提速,又防因符号链接或大小写问题误加载
正确写法:composer install --no-dev --optimize-autoloader --classmap-authoritative --no-interaction
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
CI 中 post-install-cmd 默认不执行?原因和解法
CI 环境(如 GitHub Actions)通常以 COMPOSER_DEV_MODE=0 运行,此时 post-install-cmd 和 post-update-cmd 默认被禁用——不是 bug,是 Composer v2+ 的安全策略。
解决方式只有两种:
- 显式启用钩子:
composer install --no-dev --optimize-autoloader --classmap-authoritative --no-interaction后,再补一句composer run-script post-install-cmd --no-dev - 改用自定义脚本名(如
deploy:post-install),并在 CI 步骤中明确调用:composer run deploy:post-install—— 这样不受--no-dev影响,逻辑更可控
别依赖 post-install-cmd 自动触发,它在 CI 里基本等于“不可靠”。
如何验证 CI 构建产物可直接部署到目标机
CI 不该只负责“跑通”,还要产出能直接上线的干净包。关键动作不是 rsync 整个目录,而是构建 + 验证 + 打包三步闭环:
- 构建阶段:先
npm run build(如有前端),再composer install --no-dev --optimize-autoloader --classmap-authoritative - 验证阶段:运行
php -m | grep opcache确认 OPcache 可用;用php -r "include 'vendor/autoload.php'; echo 'OK';"快速验 autoload - 打包阶段:用
tar -czf release.tar.gz --exclude=.git --exclude=tests --exclude=phpunit.xml --exclude=.env*,确保不带敏感文件和开发残留
真正容易被忽略的是:composer.lock 必须随代码一起提交,且每个子目录(尤其 monorepo 下的子包)都要有自己的 lock 文件;否则 CI 会静默降级为 update,而你根本不会在日志里看到警告。

















