composer outdated 默认不适用于监控,必须加参数才能用于自动化:它仅检查直接依赖、仅显示版本约束内更新、无结构化输出且退出码不可靠;可靠监控需用 --direct --minor-only --format=json 配合 jq 判断,并额外通过 composer show -l 检查插件。

composer outdated 默认不监控,必须加参数才可用
直接跑 composer outdated 不是监控,只是手动查一次。它默认只看 require 和 require-dev 里直写的包,跳过所有间接依赖;只显示当前版本约束内允许升级的项(比如 "monolog/monolog": "^2.8" 就不会标出 3.5.0);而且不区分安全更新、主版本变更或补丁修复——全混在一起。
想让它进 CI 或定时任务,得靠结构化输出 + 明确退出码。否则脚本无法判断“有没有要处理的更新”。
-
--direct:锁定只查你亲手写进composer.json的包,排除传递依赖干扰 -
--minor-only:只报小版本更新(如 2.1 → 2.2),跳过主版本跃迁和补丁,适合日常巡检 -
--format=json:输出 JSON,字段含latest-status(值为major/minor/patch),方便jq解析 -
2>/dev/null:屏蔽警告和网络错误日志,避免干扰判断逻辑
监控命令要能返回明确退出码
CI 流水线依赖命令退出码做分支判断:0 表示无待更新项,非 0 才触发告警或阻断。但 composer outdated 默认有输出就返回 0,没输出也返回 0——这完全没法用。
可靠做法是用 jq 检查 JSON 输出是否为空数组:
composer outdated --direct --minor-only --format=json 2>/dev/null | jq 'if .packages | length == 0 then exit(0) else exit(1) end'
这个命令在无小版本更新时返回 0,有则返回 1,可直接用于 if 判断或 GitHub Actions 的 if: ${{ steps.check.outcome == 'failure' }}。
- 别用
composer update --dry-run做监控:它会解析整个依赖图,慢、不稳定、退出码不可靠 - 别依赖颜色或终端输出:CI 环境通常没颜色,且文本格式易被空格、换行、ANSI 序列破坏解析
- 如果项目没配镜像源,海外网络波动会导致命令卡住或超时,建议加
--no-plugins(除非你真需要插件参与元数据检查)
插件更新容易被漏掉,得单独查
Composer 插件(type: composer-plugin)不会出现在 composer outdated 默认结果里,尤其轻量插件可能不走 autoload、也不发版到 Packagist。它们只在 composer show -l 里显式列出,并带 [plugin] 标记。
所以监控不能只跑一个命令。插件更新需额外覆盖:
- 运行
composer show -l,grep 出含[plugin]的行,再对每个插件名执行composer show vendor/plugin-name查最新稳定版 - 注意有些插件(如
phpstan/extension-installer)本身不提供新功能,只适配新版 PHPStan,更新时机应与主工具对齐,而非单独盯版本号 - 如果插件在
composer.json中声明了,但show -l不显示,说明没激活——常见于未执行composer install,或插件类注册失败(比如命名空间错、autoload配置缺失)
真正影响上线的不是“过时”,而是 lock 文件差异
composer outdated 再准,也不代表实际构建会出问题。真正决定运行时行为的是 composer.lock:它锁死了每个包的精确版本、dist hash、source 类型(git vs package)、甚至 PHP 平台约束。
所以监控依赖健康度,最终要落到 diff composer.lock 上:
- CI 中每次构建前,用
git diff --no-color HEAD~1 composer.lock | grep -E '^\+ {4}"(name|version|dist)"'快速抓出新增/变更的包 - 特别注意
"source": {"type": "git"}的包:它们指向特定 commit,一旦远程仓库删了分支或重写了历史,下次 install 就会失败 -
"content-hash"字段变了,说明依赖树真实不同;没变,大概率只是重生成(比如换 PHP 版本后composer install)
别把 outdated 当成唯一依据。它告诉你“能升”,lock diff 告诉你“已经升了什么”。两者结合,才算看清依赖变更全貌。


















