先运行df -T .,若输出含nfs、ntfs或9p即确认是底层文件系统不支持POSIX flock(),非网络或权限问题;WSL2用户应移至~/project等Linux原生路径,CI中禁用vendor缓存而改用~/.composer/cache。

CI里composer install报“Could not lock file”怎么快速定位
这不是网络或权限配置问题,而是底层文件系统不支持 POSIX flock()。常见于 NFS、WSL2 的 /mnt/c/、Git for Windows 的 MSYS2 环境,以及某些 Docker 挂载卷。运行 df -T . 查看挂载类型:输出含 nfs、ntfs 或 9p 就基本坐实。
临时绕过方法(仅限调试):flock .git -c 'composer install',前提是项目根目录下存在可写的 .git 目录。但别在 CI 脚本里长期依赖它——.git 在某些精简镜像中可能被删掉。
真正可靠的解法只有两个:
- 把项目移到 Linux 原生路径(如 WSL2 中的
~/project),避开/mnt/c/ - 改用 CI 平台原生并发控制:GitHub Actions 用
concurrency,GitLab CI 用interruptible: false+ job-level 锁
为什么缓存 vendor/ 在 GitHub Actions 里反而更慢
因为 vendor/ 目录体积大、跨 OS 权限混乱、且极易因 composer.json 微小变更而整体失效。GitHub Actions 的 cache 有 10GB 限制,vendor/ 动辄几百 MB,还容易因 UID/GID 不一致导致后续 chmod 失败。
该缓存的是 Composer 自身的下载缓存:~/.composer/cache。它复用率高、恢复快、不受项目结构影响。
正确写法示例:
uses: actions/cache@v3
with:
path: ~/.composer/cache
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
注意:hashFiles('**/composer.lock') 是关键——lock 文件变,缓存 key 就变,确保依赖更新后能自动重建。
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
生产构建必须加 --no-scripts 吗
必须。很多项目在 post-install-cmd 里写了生成密钥、清空缓存、暴露 .env、甚至调用 php artisan migrate 这类破坏性操作。这些脚本在 CI 或 Docker 构建阶段执行,轻则污染镜像,重则触发线上数据库变更。
--no-scripts 不是可选项,是安全底线。配合以下参数才构成完整生产安装链:
-
--no-dev:跳过 dev 包(但不会清理 autoload-dev 路径) -
--optimize-autoloader(或-o):生成autoload_classmap.php,避免运行时反复stat() -
--classmap-authoritative:告诉 autoloader “类只可能在这里”,彻底禁用 fallback 扫描 -
--no-interaction:防卡死,跳过所有交互提示 -
--prefer-dist:强制走 zip 包,比 git clone 更稳定
这条命令必须在与线上环境一致的干净构建环境中运行(CI 或 Docker),而不是部署时在生产机上补救。
Git 合并 composer.lock 冲突后 CI 还失败?检查 .gitattributes
CI 失败往往不是 Composer 的问题,而是 Git 默认把 composer.lock 当普通文本合并,产出非法 JSON。这不是人手误操作,是 Git 合并策略没配对。
解决方案很简单:在项目根目录加 .gitattributes 文件,写一行:
composer.lock merge=ours
表示发生冲突时无条件采用当前分支的版本(适合主干优先策略)。如果团队用 feature 分支合入,也可改用 merge=theirs,统一以 main 分支为准。
别信“手动合并 lock 文件”的教程——composer.lock 是快照,不是配置。真要同步依赖,应该在 feature 分支上跑 composer update --lock,再提交,让变更干净可读。

















