mcpField
U
upgrade-advisor

upgrade-advisor

github.com/vtmocanu开发3287 次安装1 天前更新
代码仓库

关于 upgrade-advisor

upgrade-advisor 是一项评估软件升级的技能,会核对版本、变更记录与项目实际用法,并给出决策和检查清单。它也支持已完成升级后的运行状况审查,默认只调查、不直接应用更改。

主要功能

  1. 01发现当前及目标版本
  2. 02检查完整升级变更记录
  3. 03将变更对照项目实际用法
  4. 04核查下游兼容性
  5. 05审查升级后的运行诊断

适用场景

  1. 01判断依赖升级是否影响项目
  2. 02检查安全修复所需的最小版本
  3. 03验证升级后的服务运行状况

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/vtmocanu/skills --skill upgrade-advisor

安装后在 Claude Code 中输入/upgrade-advisor确认已加载。

详细介绍

升级顾问

文档位置

本文档位于:~/stuff/gitrepos/gh/vtmocanu/skills/upgrade-advisor/SKILL.md(公开仓库:github.com/vtmocanu/skills)

注意:这是唯一可信来源。通过 npx skills 包管理器安装的副本 ~/.claude/skills/upgrade-advisor/SKILL.md 由此文件生成;请在此处编辑,然后运行 npx skills update 重新拉取。切勿编辑已安装的副本。

升级前先评估:有哪些变化、其中哪些会实际影响此项目,以及哪些值得采用。输出应是一个决策加一份检查清单,而不是盲目提升版本。默认只做调查,除非用户要求你应用更改。

两种模式——先阅读请求。“我应该升级 X 吗?”属于下文的评估模式。但“我已经升级了 X”属于验证请求:决策已定,问题在于升级破坏了什么。在这种模式下,交付内容是第 7 步(审查运行时);第 3 至第 4 步仅用于解释你的发现。对于已经完成的升级,切勿只根据变更日志给出结论——运行中的系统就在眼前,所以要检查它。

工作流

按顺序执行以下步骤。第 1 至第 2 步与第 3 步中的变更日志获取相互独立——并行发起这些工具调用。

1. 找出当前版本——不要想当然

查明版本实际固定在哪里。它很少只出现在一个显而易见的位置。已发布的版本 ≠ 此项目正在使用的版本。检查项目中的以下位置:

  • 语言/工具管理器:devbox.json/devbox.lock、.tool-versions(asdf/mise)、.nvmrc、runtime.txt、flake.nix。
  • 包清单与锁文件:package.json + package-lock.json/yarn.lock/pnpm-lock.yaml、go.mod/go.sum、pyproject.toml/requirements.txt/uv.lock、Cargo.toml/Cargo.lock、Gemfile.lock、pom.xml、build.gradle。
  • 容器/CI:Dockerfile 的 FROM、.github/.forgejo/.gitlab-ci 工作流中的版本固定项、Helm 的 Chart.yaml/values.yaml、操作中的 uses: SHA/标签。
  • 运行中的服务/设备不会在仓库中固定版本——版本位于运行时中,因此要向它查询(ha core info、/api/config、kubectl version、SELECT version())。重启期间读取要格外小心:新进程启动前,它会返回旧版本;如果读到的版本看起来过时,请从两个来源确认。

报告准确的当前版本以及固定该版本的每个文件——同一依赖常常在多个位置固定(Dockerfile 的 FROM + 包清单 + CI 的 uses:),这些位置可能悄然不一致;请全部列出并标记任何偏差。在单体仓库中,注明彼此不同的各个包固定版本,因为它们可能需要一起调整。如果仓库关联了远程仓库,请确认本地检出与远程仓库的版本固定项一致(本地分支可能落后)。锁文件的权威性高于包清单中的版本范围。

2. 找到最新版本——以及最新的 可安装版本

latest released 和 latest this project can actually pull 是两个不同的版本号。两者都要查明:

  • 最新发布版本:GitHub releases API(/repos/OWNER/REPO/releases/latest),或生态系统注册表(npm registry.npmjs.org/PKG、PyPI pypi.org/pypi/PKG/json、crates.io、Docker 标签、Maven Central)。
  • 通过本项目的包管理器可安装的最新版本:nixpkgs/devbox 锁定版本可能比上游落后几天到几周;企业注册表可能只镜像了部分版本;Docker 基础镜像可能只发布了某些标签。推荐之前,先确认目标版本确实可以解析(例如,devbox:search.devbox.sh/v2/resolve?name=X&version=Y;nixpkgs:nixhub;npm:注册表的 versions 映射)。如果目标版本尚不可安装,就明确说明:升级受阻于打包方,而不是代码,这就是全部结论。

有两个因素会影响目标版本的选择:

  • 由安全问题/CVE 驱动:先根据公告确定修复版本(GitHub Security Advisories / osv.dev,或生态系统扫描器:npm audit / pip-audit / govulncheck / cargo audit)。目标应为能修复该 CVE 的最低版本——优先选择补丁版本/回移补丁,而非大版本升级;同时提高紧迫性,因此可以接受更大的影响范围。
  • 由停止维护驱动:检查当前锁定版本是否已停止生命周期支持 / 不再受支持(endoflife.date)——在没有必需功能的情况下,不再维护本身就是升级理由;并确认目标属于 LTS / 仍受维护的版本线,而非生命周期短暂的版本。说明目标版本的支持期限。
3. 阅读涵盖整个版本差异范围的变更日志

不要只读最新版本的发布说明。遍历当前版本与目标版本之间的每个中间版本——任何一个版本都可能引入破坏性变更。获取官方变更日志 / 发布说明,以及项目自己的迁移/升级指南(如果有)。优先采用权威来源:项目的发布说明和迁移文档;可用时,用 context7 等文档 MCP 查阅库 API;以及源代码仓库中的 CHANGELOG/BREAKING 文件。逐字引用破坏性变更和弃用项——改写会丢失需要通过 grep 查找的确切符号/标志/配置键。

4. 将每项变更与实际用法交叉核对——这是核心价值

不涉及当前用法的破坏性变更就是 N/A。对于每项破坏性变更和弃用项,都要在代码库中 grep 受影响的符号、配置键、CLI 标志、API 或组件。逐项分类:

类别含义操作
破坏性变更——影响我们我们使用了已移除/变更的内容升级前必须修复;指出具体位置
破坏性变更——行为变更API 相同,但默认值/语义变了(例如,默认超时从 30s→5s)grep 无法捕获——符号未变;阅读变更日志中的默认值/行为变更说明,并逐一人工检查调用位置
破坏性变更——N/A任何地方都不存在(grep 无匹配)标记为已检查且无影响——但 grep 无匹配只是高置信度,并非证明;对于通过动态方式引用、经重新导出、使用字符串键配置或来自传递依赖的内容,标记为“很可能 N/A,需核实”
弃用仍可使用,但会发出警告;有移除期限找机会迁移;记录移除版本
功能 / 改进新能力或性能/安全修复如果能让我们删除变通方案或免费获益,就标出来
随附的告警规则 / 健康检查——新增或刚修复升级会启用默认开启的 PrometheusRules / /health 检查 / 合成监控,或修复之前失效的规则(指标已重命名、选择器错误)发布前,针对实时信号逐条试运行——一条此前不存在或失效的规则,一旦激活,就会对任何已有潜在问题立即触发;不要将其视为“监控净收益”而直接放行
重构机会新版本使我们的代码可以简化提出建议,不要自动应用

明确列出 N/A 项很重要:这正是“我已检查,没有任何内容影响我们”和“我只扫了一眼标题”之间的区别。

5. 检查下游/传递兼容性

工具升级并非孤立进行。请对照所有依赖它的内容验证目标版本:主题/插件的 min_version 和对等依赖范围、框架支持矩阵、工具链自身的最低版本要求,以及必须一起变更的同级固定版本。如果目标版本会破坏必需的插件,即使工具本身没有问题,也应阻止升级。

6. 推荐 apply 前,权衡影响范围

谨慎程度应与可逆性相匹配。难以恢复的目标(仅支持 OTA 的固件、生产数据库引擎、被许多下游构建复用的基础映像)应当先构建/编译/测试,再应用。容易回退的目标(开发用 CLI、由 CI 管理的锁文件升级)则可以直接变更。请说明适用哪种情况。

7. 审查运行时——变更日志无法告诉你哪些内容已经损坏

步骤 3-4 根据变更内容推导 grep 列表,因此变更内容限定了它们能发现问题的上限。你升级经过的某个版本中已移除的符号,它们无法发现,但该符号可能仍在你的代码中实际使用——因为只有当相关代码路径真正运行时,已移除的 API 才会导致失败,所以很少触发的路径(仅在黎明时运行的作业、错误分支、季节性任务)可能会悄然损坏数月。因此,即使针对变更内容的 grep 结果干净,也不代表系统可正常工作。

因此,要查看系统自身的错误信息,而不只是发行说明:

  • 结构化诊断优于日志尾部,而且通常只需调用一次:Home Assistant system_log/list、django-admin check、govulncheck ./...、npm ls、构建时的弃用警告,以及 /health 或诊断端点。日志尾部只显示一个时间窗口;错误信息则会显示所有不同故障及其数量。
  • 在有此功能时查看每个单元的执行状态——组件可能运行失败,但应用本身状态正常,且所有冒烟测试都通过(HA 自动化跟踪会显示 script_execution: error)。

只要条件允许,就在升级前建立基线,并在升级后重新查看。没有基线,你就无法区分这是升级导致的还是原本就已损坏,并会在两个方向上都错误归因。如果你只有日志,时间戳也能起到同样作用:将其与升级/重启时刻进行比较。

包含重启的日志时间窗口会虚构持续速率。 升级会重启进程,进程启动时会重新同步状态,这一突发日志就会落入你刚刚查询的时间窗口——因此,升级后立即执行 logs --since=15m,再除以 15 分钟,就会捏造出一个并不存在的稳定速率。在提出任何抑制措施(日志管道丢弃规则、提高日志级别、静默警报)之前,先了解变化形态,而不是平均值:按分钟分桶,并与变更前基线比较。突发后归于平静与真正持续的情况,在总量上看起来完全相同,却需要采取相反的决策——突发通常只是每次重启付出的一次性成本,不值得抑制;而永久性例外可能会在之后悄然吞掉真实错误。

实测示例:一次 cert-manager 1.20.3 → 1.21.0 审查报告称,某条已知无害警告“持续约 5 行/秒”,这个数值是通过 kubectl logs --since=15m 计算得出的——而该时间窗口恰好涵盖了 Pod 启动时间。按分钟统计的变化形态才揭示了真实情况:启动那一分钟有 4,746 行,下一分钟有 7 行,之后约为 0;升级前基线为 3,475 字节/10 分钟,升级后稳定状态为 4,515 字节/10 分钟。真实成本是每次重启约 3.3 MB,而非持续速率。“持续”的读数险些让人针对一个并不存在的问题添加永久丢弃规则。 实测示例:一次 HA 2026.6.4 → 2026.7.2 审计检查了整个差异,结果没有任何 grep 匹配项,Repairs 列表为空,所有仪表盘也都能正常渲染——结论是“干净升级”,这结论虽然属实,却毫无用处。一次 system_log/list 调用随后显示:extra keys not allowed @ data['kelvin']:light.turn_on 的 kelvin 参数早在 2026.3 就已移除,五处调用点已经失效约 3 个月。2026.7 的差异中不可能有任何内容能暴露这个问题。同一次调用还发现另外两个自动化也已损坏,因为它们引用的实体从未存在过。

实测示例——监控层本身也是升级内容的一部分。 certmon(x509-certificate-exporter)从 4.1.0 → 4.2.0 升级时,新增了默认启用的 PrometheusRules,并修复了一条长期失效的告警(X509ExporterReadErrors 指向的是在 4.0.0 中已重命名的指标)。评估发现了这些新告警,认为它们“净收益为正,告警疲劳风险很低”,于是便发布了。几分钟内,18 条告警触发(SourceDown/SourceErrors/SourceErrorsSustained × 6 个 Pod)——并非由新故障引起,而是因为 hostPath 导出器在 4.1.0 上也一直持续报告 broken_symlink/out_of_scope_symlink 错误;旧规则只是失效了,所以之前从未触发过告警。证书没有问题(x509_cert_not_after 仍有值)——每一条都是误报的严重告警。如果差异新增或修复了告警规则,应在评估中使用当前指标运行每条规则的 PromQL(先检查原始表达式,再检查 count(ALERTS{...})):“我们获得了一条有效告警”和“我们刚刚因为一个一直存在的无害情况而触发了告警”是同一件事;只有实时检查才能区分二者。

输出

先给结论,再列证据:

  • 结论——以下选项之一:已经是最新版本 / 可安全升级 / 保持现状(可安装且无问题,不值得折腾) / 受阻(原因) / 需要处理(N 项) / 干净,但发现 N 个既存故障(步骤 7 发现了此次升级未导致的故障——请明确说明,别让“干净”听起来像是“正常运行”)。
  • 版本——当前版本(+ 源文件)→ 最新已发布版本 → 最新可安装版本。
  • 与我们用法相关的破坏性变更——步骤 4 的表格;凡是会影响我们的内容均须逐字引用,并列出 N/A 项。
  • 弃用项——注明移除前的缓冲时间。
  • 收益 / 重构——值得采用的功能、现在可以移除的变通方案。
  • 下游兼容性——已检查插件 / 主题 / 同级依赖约束。
  • 计划——提供具体检查清单(先编译还是直接升级、失败时的回退方案、需要调整的同级依赖固定版本、需要重新生成的文档 / 锁文件)。可提出创建跟踪问题或应用变更;未经明确要求,不要自行应用变更。

陷阱(不易察觉——上述步骤已涵盖其余情况)

  • grep-clean 代表高度可信,并非确凿无误。 动态访问、重新导出、以字符串为键的配置、封装层和传递依赖都可能隐藏符号 grep 看不到的用法。应将这些标记为“可能不适用,需核实”,而不是直接判定无影响。
  • 行为变更仍使用相同符号。 默认值或语义发生变化时,即使 grep 发现调用点未变,也仍会影响你,因此纯符号 grep 会漏掉它。请阅读变更日志中有关默认值/行为变更的说明,并手动检查调用点。
  • 不升级也是合理选择。 如果可以安装且 grep-clean,但没有你需要的修复、没有你会使用的功能,并且影响范围不小,则建议“保持现状”,并说明原因。不要为了升级而生造理由。
  • 变更日志简略不等于没有问题。 如果发布说明内容稀少,或项目发布了版本标签却没有发布说明,请改看比较视图(github.com/OWNER/REPO/compare/vA...vB)或提交日志——破坏性变更有时只会出现在提交中。
  • 弃用不等于移除。 这是一则预警,会留有过渡期——记录移除它的版本,按自己的计划迁移,无须惊慌地立即修复。
  • 新增或修复的告警会针对早已存在的问题触发。 升级附带默认启用的告警规则,或修复失效规则后,可能会因任何一直存在但未受监控的潜在问题而触发告警。在评估期间,应根据实时信号检查捆绑的规则;新增监控的“安全升级”不一定风平浪静。

评论

支持 Markdown