composer 的 archive 命令不生成变更对比包,它仅按 composer.json 打包当前项目源码与 vendor 目录,不记录、不比较、不输出任何 diff 信息;所谓“版本变更对比包”需在 ci 中手动拼装:先用 git diff 或 jq 解析 composer.lock 获取真实依赖变更,再将 archive 结果与 diff 文件合并打包。

archive 命令本身不生成变更对比包
Composer 的 archive 命令只打包当前 vendor/ 和项目文件(按 composer.json 配置),不记录、不比较、不输出任何 diff 信息。它本质是 zip/tar 工具的封装,和 Git diff 或版本比对毫无关系。
所谓“版本变更对比包”,实际是 CI 流程中需要自己拼装的产物:先获取上一版与当前版的依赖差异,再把 archive 结果和 diff 文件一起打包。
-
composer archive的--format=zip和--file参数控制输出路径和格式,但不会自动附加 changelog - 想让归档带 diff,必须在调用
composer archive前或后,用git diff、composer show --outdated或composer.lock比较工具生成文本文件 - CI 中建议用
git rev-parse HEAD^1获取前一个 commit,再用git diff HEAD^1...HEAD -- composer.lock提取 lock 文件变动行
如何从 composer.lock 提取真实依赖变更
直接 diff composer.lock 文件容易误报——比如时间戳、PHP 版本字段变化,或无关的排序调整。真正关心的是包名、版本号、source.url、dist.sha256 这几项的实际变动。
推荐用 jq 解析两版 composer.lock,只比对 packages 数组中的关键字段:
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
jq -S 'reduce (.packages[] | {name: .name, version: .version, source: .source.url, dist: .dist.shasum}) as $p ({}; .[$p.name] = $p)' old.lock > old.pkgs.json
jq -S 'reduce (.packages[] | {name: .name, version: .version, source: .source.url, dist: .dist.shasum}) as $p ({}; .[$p.name] = $p)' new.lock > new.pkgs.json
diff -u old.pkgs.json new.pkgs.json > deps.diff
- 避免用
composer show --outdated,它只反映当前环境能升级什么,不等于本次提交实际变更了哪些包 - 如果项目用了
platform或config.platform,需确保 diff 环境中 PHP 和扩展版本一致,否则composer install生成的 lock 会不同 - CI 中建议缓存
composer.lock上一版(例如从 tag 或 release 分支 checkout),而不是依赖HEAD^1—— merge commit 可能导致父 commit 不唯一
CI 中打包 archive + diff 的可靠顺序
顺序错会导致包里缺文件、diff 内容滞后或归档名混乱。典型失败场景:先 archive 再生成 diff,结果 diff 里包含尚未 commit 的本地修改。
- 第一步:确认当前工作区干净(
git status --porcelain应为空),防止意外纳入未提交变更 - 第二步:checkout 上一稳定版本(如
git checkout v1.2.3),生成旧版composer.lock快照;再切回当前分支,生成新版快照 - 第三步:运行
composer install --no-dev --prefer-dist确保 vendor 与 lock 严格一致,再执行composer archive - 第四步:把
deps.diff、changelog.md(如有)、composer.lock三者一起加入最终 zip,不要只放 archive 输出 - 归档名建议含语义化版本和 hash,例如
myapp-v1.3.0-7a2f4b8-diff.zip,避免仅用 timestamp
为什么不用 Composer 插件自动做这件事
目前没有主流 Composer 插件能可靠完成“归档 + 变更比对”闭环。插件如 hirak/prestissimo 或 roave/security-advisories 都不介入 archive 流程;自研插件反而增加 CI 复杂度和维护成本。
真正轻量可控的做法是:用 shell 脚本封装上述步骤,在 CI 的 before_script 或独立 job 中执行。
- 不要在
composer.json的scripts里塞 diff 逻辑——scripts 是为开发服务的,CI 需要更确定的输入源(如指定 tag) - 若项目用 GitHub Actions,注意
actions/checkout默认只 fetch depth=1,必须设fetch-depth: 0才能拿到历史 commit 用于 diff - diff 结果里出现大量
ext-*变动?检查 CI runner 的 PHP 版本是否与本地一致,composer.lock中的 platform 字段会直接影响依赖解析结果
归档本身很简单,难的是让 diff 精确反映生产环境实际变更——这取决于你比对的是哪两个 lock 文件、它们由什么 PHP 环境生成、以及是否排除了非功能性的字段扰动。










