composer如何在CI中检测composer.json与.lock是否同步?(diff检查脚本)

1次阅读

composer install –dry-run 会报错说明 lock 文件过期:它校验 composer.json 与 composer.lock 是否一致,若缺失依赖、版本不匹配或 hash 错误则失败,且需在根目录执行、vendor 清空。

composer如何在CI中检测composer.json与.lock是否同步?(diff检查脚本)

composer install –dry-run 会报错说明 lock 文件过期

CI 中最直接的检测方式,就是用 composer install --dry-run。它不写文件、不下载包,只校验 composer.jsoncomposer.lock 是否一致:如果 lock 文件缺失依赖、版本不匹配或 hash 不对,命令会立即失败并输出类似 Your lock file does not contain the required package "monolog/monolog"The lock file is not up to date with the latest changes in composer.json 的错误。

这个命令本质是复现 install 流程但跳过写入,所以快、准、无副作用。

  • 必须在项目根目录执行,且确保 vendor/ 不存在或已清空(否则可能绕过校验)
  • CI 中建议加 --no-interaction --no-ansi --no-progress 避免干扰输出
  • 某些旧版 Composer(–dry-run 支持不稳定,推荐升级到 2.x

diff -q composer.json composer.lock 不可靠

单纯比对两个文件内容差异(比如用 diff -q)完全无效——composer.lock 是生成的二进制友好 JSON,含哈希、平台信息、依赖树结构,和 composer.json 的语义完全不对应。改一行 PHP 版本要求,lock 文件可能重排整个 packages 数组,diff 必然报不同,但实际没破同步关系。

  • composer.json 变更后必须运行 composer updatecomposer install 才能生成新 lock
  • 手动编辑 composer.lock 属于高危操作,CI 应该拒绝这种“伪同步”
  • 真正要检测的是“锁是否反映当前 json 声明”,不是“文本是否相似”

CI 脚本里怎么写才稳?

一个健壮的检查脚本核心就三步:清理环境 → 干跑安装 → 捕获退出码。不需要解析 JSON、不依赖外部 diff 工具。

rm -rf vendor composer.lock composer install --dry-run --no-interaction --no-ansi --no-progress

如果上一步返回非 0,说明 lock 缺失或过期;如果返回 0,说明当前 composer.json 理论上可被现有 lock 完全满足(注意:这不代表 lock 本身合法,只是和 json 同步)。

  • 务必先删 vendor/composer.lock,否则 --dry-run 可能误判(例如 lock 存在但 vendor 已删,它会尝试重建 lock)
  • 若项目允许 dev 依赖参与校验,加 --with-all-dependencies;否则默认只校验 require
  • Git CI 中常把 composer.lock 提交进仓库,所以检查前别用 git checkout -- composer.lock 这类操作覆盖本地 lock

为什么不用 composer validate?

composer validate 只检查 JSON 格式、schema 合法性、字段拼写等,完全不涉及 composer.jsoncomposer.lock 的同步关系。它可能对一个严重过期的 lock 文件返回 OK,因为 lock 本身格式没问题。

  • composer validate --strict 会检查 license 字段、homepage 等,仍不碰同步逻辑
  • 真正要问的是“我改了 json,lock 跟上了吗”,只有 --dry-run 能回答这个问题
  • 有些团队用 composer show --outdated 辅助判断,但它查的是远程包版本,不是本地 lock 同步状态

实际跑起来,最易忽略的是 vendor 目录残留和 Composer 版本差异——CI 镜像里装的 Composer 小版本不一致,可能导致 --dry-run 在本地通、CI 上挂,尤其跨 1.x / 2.x 时。

text=ZqhQzanResources