ci中vendor软链被删是因为composer每次install/update都会rm -rf vendor,手动软链被清除;应改用path仓库+@dev版本,由composer自动维护软链并确保ci稳定识别。

CI 中 vendor 软链被删,是因为 Composer 默认清空 vendor 目录
每次 composer install 或 composer update 都会先 rm -rf vendor,所有手动创建的软链接(比如 ln -s ../my-local-package vendor/my-vendor/my-package)都会被连根拔掉。这不是 bug,是 Composer 的设计前提:vendor/ 必须完全由它管理。
常见现象:ls -l vendor/my-package 显示链接还在,但 CI 流水线跑完就变成真实目录;或者链接指向的源路径在 CI 工作区里根本不存在,报错 No such file or directory。
- 别把软链接当“持久化方案”——它只是本地调试的权宜之计,在 CI 里极不可靠
- 如果必须用本地包,改用
path类型仓库 +dev-main版本,让 Composer 自己生成并维护软链 - 若坚持手动 ln,必须绑定到
post-install-cmd脚本钩子中,且确保钩子在 CI 环境下能执行(比如不依赖交互终端)
用 path 仓库替代手动软链,CI 才能稳定识别
path 仓库是 Composer 官方支持的、唯一能在 CI 中安全使用本地依赖的方式。它不是简单复制文件,而是在满足条件时自动生成软链接,并在后续 install 中保留。
关键配置有三点:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 在
composer.json的repositories里声明type: "path",url必须是相对于项目根目录的路径(如"../my-utils"),不能是绝对路径或~ - 被引用的本地包目录里必须有合法的
composer.json,且name字段要和主项目require中的包名一致 - 主项目
require中版本号必须显式写成"@dev"或"dev-main",否则 Composer 会跳过 symlink,走 dist 下载逻辑
示例片段:
"repositories": [
{
"type": "path",
"url": "../my-utils"
}
],
"require": {
"my-vendor/my-utils": "@dev"
}
CI 环境下 vendor 软链失效的真正原因常是路径映射错位
Docker 或 runner 工作目录与宿主机路径不一致时,__DIR__ 解析出的绝对路径就会错,导致 autoload 里硬编码的 $vendorDir 指向不存在的位置。报错通常是 require(): failed to open stream,但实际路径是软链展开后的目标路径,不是你 ls -l vendor 看到的源路径。
- 检查 CI 日志里
composer install输出的当前工作目录是否为项目根(含composer.json那层) - 确认
path仓库的url在 CI 容器内真实可访问——比如 Dockervolumes是否正确挂载了本地包目录 - 避免在 CI 脚本里用
cd切换到子目录再运行composer install,否则../my-utils会解析错位 - CI 中不要设
COMPOSER_VENDOR_DIR和软链共存,二者冲突会导致 autoload 生成失败
CI 流水线里该禁用 --no-scripts 吗?
禁用 --no-scripts 是必须的。Composer 的 autoload 文件(如 vendor/autoload.php)是在 post-install-cmd 钩子里生成的,不是安装包时自动写死的。CI 中若加了这个参数,autoload 就不会重建,哪怕 vendor 目录存在,也会报 Class not found。
- CI 脚本中明确去掉
--no-scripts,或显式加上--scripts(Composer 2.2+ 支持) - 如果用了自定义 autoload 生成逻辑(比如 TP 的
think\facade\Facade初始化),更要确保对应脚本被执行 - 某些私有包的 post-install-cmd 依赖外部命令(如
phpstan),CI 环境需提前装好,否则脚本失败会中断 autoload 生成
软链问题背后其实是路径信任模型的冲突:Composer 基于 __DIR__ 构建 autoload,而 CI 环境的文件系统抽象层(Docker volume、runner workspace)会让这个假设失效。最稳的解法不是绕过它,而是让 Composer 自己控制链接生命周期——也就是用 path 仓库 + @dev 版本,其他都是临时补丁。










