研发协作
升级 Pulumi Provider…
当你需要升级任意 Pulumi provider 到新版本,并希望升级后预览不产生任何基础设施变更(零 diff)时使用。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 49/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 85/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
升级 Pulumi Provider 版通用
解决思路
- 把 provider 升级视为一次翻译而非变更请求:用户意图和真实云资源不变,只需让代码(第 2 层)和 Pulumi state(第 3 层)继续正确表达它们;正确的翻译应产生零 diff。
- 按核心循环操作:1) 升级依赖版本;2) 带必需 CLI 参数运行 preview;3) 做 Diff Checkpoint,对每个非 same 资源分类;4) 修复 Category A;5) 调查 Category B;6) 重复直到干净或所有剩余 diff 均已充分调查;7) 创建 PR 并附升级摘要。
- 每次 preview 后执行 Diff Checkpoint:对每个非 same 资源问『我的代码改动是否直接或间接影响了这个资源?』直接=编辑了该资源块;间接=改了共享变量、其他资源的输出、辅助函数、默认值或它依赖的资源。
- Category A(我改了该资源代码):若显示 same 则翻译正确;若显示 update,说明改动改变了语义而非仅语法,需找出新旧代码的语义差异(属性名映射到不同底层字段、值形状转换丢失/增加信息、新版本默认值变化需显式设置旧值、新版本开始跟踪之前未跟踪的字段需显式设置以匹配当前状态);不要假设这些属性变更是 no-op,pulumi up 会把它们发给云 API。
- Category A 中新增资源块显示 create:升级时新增资源块通常代表云上已存在的基础设施(旧 provider 隐式管理,新 provider 需要显式资源),应使用 import 而非 create 来收养已有云资源,import ID 格式因资源类型而异。
- Category A 中删除资源块显示 delete:delete 意味着 pulumi up 会调用 provider 的 Delete API 真正销毁或取消配置云资源,这与 pulumi state delete(仅从 Pulumi 跟踪中移除、不调用 API)不同;正确做法是 1) pulumi state delete '<urn>' 手动从跟踪中移除,2) 用 import 添加替代资源收养云状态,3) 用 preview 验证;不要把 delete 留在预览中直接创建 PR。
- Category B(我没改该资源代码):diff 来自 provider 版本变化本身(不同默认值、状态表示变化或行为差异),阅读 references/diagnostic-toolbox.md 调查;可能可用代码修复(显式设置变化的默认值、加 alias)、可能是需引用升级指南或 provider 文档佐证的有记录 no-op、可能需要手动步骤(state 移除+重新 import)、或未知(向用户呈现发现并请求指导)。
- Category C:pulumi:providers:{name} 上仅显示版本变化的 update 是唯一预期 diff,需确认 provider 资源上没有其他属性变化。
- 分类后做完整性检查:预览中每个显示非 same 状态的资源都必须出现在 checkpoint 中,包括带 [diff: ...] 注解但没有显式 create/update/delete 标记的资源;漏掉则 checkpoint 不完整,需回去补分类。
- 接受任何 diff 为 OK 都需要证据:升级指南有记录、GitHub issue 确认或 provider 文档解释该行为;『我认为 API 视它们等价』或『这看起来像状态协调』不算证据;找不到证据就修复它或向用户标记。
- 排序:先修复所有 Category A 问题再调查 Category B,因为代码修正会改变预览输出,先调查 B 会浪费精力;先修自己的错误、重新 preview,再看剩余项。
- 最终预览中不得有 delete 或 replace:delete 意味着 pulumi up 会销毁云基础设施,replace 意味着销毁并重建;它们绝不能作为『剩余 diff』,必须通过代码修复、alias 或记录的手动步骤解决后才能继续。
- 运行 preview 时必须使用 pulumi preview --refresh --run-program:--refresh 在 diff 前刷新真实云状态,--run-program 在刷新期间运行 Pulumi 程序;不带这些参数的预览可能显示虚假 diff(幻影标签移除、区域添加),不要解读未带这些参数的预览。
- 不要追逐 deprecation:已弃用但仍可用的东西不要动,迁移到替代品会带来无收益的风险;弃用警告可接受,diff 不可接受;只修复真正的错误,保留可工作的代码。
- 保持最小侵入:每一行改动都可能引入回归,优先选择能起作用的最小改动。
- 不要运行 pulumi up:provider 升级修改源代码,需要代码审查后再部署,流程是 PR -> review -> merge -> 通过 CI/CD 部署。
- 获取版本信息:从用户请求、Pulumi Registry、包管理器元数据或仓库现有依赖约束确定目标版本;用户未指定时默认最新稳定版;若用户问哪些 stack 或项目受影响,先用 skill package-usage 或最佳可用的包清单工具再改动。
- 更新依赖:TypeScript/JavaScript 用 npm install @pulumi/{provider}@^{version} 或 yarn add @pulumi/{provider}@^{version};Python 在 pyproject.toml 或 requirements.txt 中写 pulumi_{provider}>={version}(下划线而非连字符)再安装;Go 用 go get github.com/pulumi/pulumi-{provider}/sdk/v{major}@latest,更新所有 import 路径(如 v6 -> v7),运行 go mod tidy;.NET 用 dotnet add package Pulumi.{Provider} --version {version};Java 更新 pom.xml 或 build.gradle 依赖版本;YAML 在资源选项或 provider 配置中更新 provider 版本。
- 安装后从 lockfile(package-lock.json、go.sum 等)检查实际安装版本,用这些确切版本做 schema-tools 比较。
- 更新依赖后立即运行 pulumi preview --refresh --run-program,不要先研究破坏性变更——很多升级(尤其小版本)直接就能工作;若预览干净(只有 provider 版本升级)则创建 PR。
- 理解预览进度:预览可能在第一个错误处失败并隐藏其他错误,修好一个常会暴露新错误,这是正常进展而非修复让情况变糟;出现新的或不同的错误=进展,错误集缩小=进展,同一错误持续=修复无效需换方法,无错误但有 diff=运行 diff checkpoint。
- 预览干净(或尽可能干净)后呈现升级摘要,包含:代码变更表(文件、变更、为何保持意图)、预览结果、剩余 diff 表(资源、操作、pulumi up 时会怎样、风险、来源)、所需手动步骤、未采取行动的弃用警告;每个剩余 diff 必须引用权威来源(升级指南、provider 文档、上游 GitHub issue),『我认为这是预期的』不算来源。
- 若预览干净(或所有剩余 diff 都是有引用来源的有记录 no-op),创建 pull request;若仍有未解决 diff,把摘要作为异常报告呈现,并在创建 PR 前询问用户如何处理。
- 调查 Category B diff 时阅读 references/diagnostic-toolbox.md,其中包含升级指南、schema-tools(安装、运行、解读输出)、stack 状态检查、SDK 类型、GitHub issues。
适用边界 · 注意事项
- 不要用于查询哪些 stack 使用了哪些包版本;跨 stack 审计请使用 skill package-usage。
- 不要用于一般基础设施任务。