ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Nx migrations.json 运行时契约:深入解析 `nx migrate` 如何消费迁移配置

Nx migrations.json 运行时契约:深入解析 `nx migrate` 如何消费迁移配置 Nx migrations.json 运行时契约深入解析nx migrate如何消费迁移配置【免费下载链接】nxThe Monorepo Platform that amplifies both developers and AI agents. Nx optimizes your builds, scales your CI, and fixes failed PRs automatically. Ship in half the time.项目地址: https://gitcode.com/GitHub_Trending/nx/nx本指南以 Nx 仓库中migrations.json的运行时契约为核心系统讲解nx migrate在收集、门控与执行迁移条目时对generators、packageJsonUpdates及包级配置的实际消费方式。读完本文你将掌握为 Nx 插件编写迁移条目的每个键的精确语义理解返回值如何驱动 AI Agent 流程并能避免常见的路径、门控与幂等性陷阱。概述nx migrate的消费入口nx migrate对迁移元数据的消费逻辑集中在三个源文件中它们是本文所有结论的权威出处migrate.tsMigrator类与runMigrations负责版本门控、依赖收集与执行prompt-files.tsprompt 文件的校验、解析与工作区落地misc-interfaces.tsMigrationsJsonEntry、MigrationReturnObject、PackageJsonUpdates等核心类型定义。源码注释中的一句提示值得所有插件作者记住line references rot, symbol names do not——行号会过时符号名不会。阅读时请以符号名为准与本仓库当前实现对照验证。migrations.json的两个 sectiongenerators与schematics新条目永远放在generators下。schematics下的条目会走 Angular Devkit 适配器在运行时已安装包的migrations.json会被不合并地重新读取由条目所在 section 决定采用哪个 runner。收集阶段fetch phase虽然会把两个 section 合并进同一张映射但该合并结果只用于门控gating不参与 runner 的选择。这一点意味着如果你想利用 Angular schematics 生态条目必须留在schematicssection而 Nx 原生的 generator 条目则必须放在generatorssection二者不能混用。generators条目每个键的运行时语义以下是Migrator在收集与执行阶段对每个键的真实行为与 misc-interfaces.ts 中的MigrationsJsonEntry类型一一对应键运行时行为version门控条件gt(version, installed) lte(version, target)比较前先经normalizeVersion归一化。预发布遵循beta.N rc.N stable的排序。已安装侧采用严格gt用户恰好处于某个预发布版本时该条目永远不会运行。description显示在运行列表与文档页中并渲染进 Agent 化流程提示词的migration块。implementation/factory等价别名两者同时存在时implementation胜出也是推荐编写的一方。路径用require.resolve相对已安装包内 migrations.json 所在目录解析因此必须匹配发布后的目录布局dist 前缀。#symbol选中命名导出否则取默认导出。调用方式固定为await fn(tree, {})。requires包名到 semver range 的映射以includePrerelease: true对本轮运行中该包将要落到的版本求值优先使用待定packageJsonUpdates否则回退到已安装版本。包在两处都不存在 门控失败。被跳过的条目在默认流程中不会重跑补跑路径是--from配合--exclude-applied-migrations。该条件仅在收集时求值一次执行阶段绝不复查生成的 migrations 文件虽携带完整条目但运行路径从不重新评估requires。prompt指向同目录 .md 的相对路径校验必须落在 migrations 目录内。生成migrate 生成迁移文件时内容被提取到tools/ai-migrations/package/targetVersion/basename.md字段被改写为这个工作区路径。运行时纯 prompt 条目只在 Agent 化流程下执行会拉起 agent CLI并把提取出的工作区路径通过instructions_file交给 agent从不内联内容否则它们只作为 next steps 呈现。混合条目implementation prompt总是先跑 generator 半边当该半边返回skipAgentic: true时完全跳过 prompt 半边。prompt 按路径跨条目去重。implementation/factory/prompt三者至少需要一个——这在收集阶段就会校验见 prompt-files.ts。documentation指向同目录 .md 的相对路径解析方式与implementation相同。迁移时--run-migrations只在 Agent 化运行中读取它并交给运行 prompt 或校验环节的 agent作为migration_documentation标记为参考而非指令--run-migration也会把它打印进提示块供用户查看。内容从不内联进提示词。路径失效时记录警告并跳过。文档站点在同一键的 .md 上渲染插件的迁移页不会从 implementation 的文件名推断任何东西。一个容易踩的坑是implementation路径的弱校验没有任何机制把路径与条目绑定。一个错误但存在的路径在运行时仍会被解析并执行getImplementationPath只是调用require.resolve能通过assertValidMigrationPaths因为它直接 require 源文件也能通过nx/nx-plugin-checks其resolveImplementation甚至会猜测源码布局。因此发布前必须人工核对路径确实指向发布包中的文件。不要编写的键以下键是明确的禁区cli自按 section 选 runner的改动起就已失效schema 中标记为 No longer usedschema虽然在 JSON schema 中有文档但运行时从不读取x-repair-skip除非你的迁移是 nx-core 迁移且必须在nx repair下不重跑repair 会无视版本重跑所有nx-core 迁移。集合范围以 node resolution 为准已安装版本的解析通过 node resolution 从工作区根目录进行createInstalledPackageVersionsResolver→readModulePackageJson而不是看 package.json 的条目。一个 package-group 成员只要能从根目录被 node 解析到例如被提升的传递依赖其迁移就会被收集并参与门控解析不到的则被跳过——即使工作区代码 import 了它。这意味着 pnpm 式隔离布局下传递包虽然在磁盘上存在却因无法从根目录解析而被排除。返回值契约驱动人机协作迁移函数的类型签名见 misc-interfaces.ts为Migration (tree) void | string[] | MigrationReturnObject | Promise...返回形式语义string[]是nextSteps的简写。nextSteps显示在运行结束摘要与失败回顾中被 Nx Console 持久化从不进入 agent 提示词。这是需要人类手工处理的事项的唯一通道。agentContext在 Agent 化运行中注入到 agent 提示词内作为advisory_context包括 generator-only 迁移之后的校验环节当nx migrate自身运行在外部 agent 内部时改为以agent_context块打印到 stdout 供该 agent 使用。普通人类运行中会被丢弃因此需要人类看到的内容必须同时复制进nextSteps。skipAgentic显式 opt-in 的true告诉 runner 确定性运行已处理完一切、无需 AI 步骤从而跳过本会运行的步骤混合条目的 prompt 阶段或 generator-only 迁移之后的校验步骤。它还阻止向用户提示一个无人需要执行的 prompt--run-migrations下被跳过的混合 prompt 不会产生 deferred/next-steps 条目--run-migration工作进程也不会为它打印提示块。结束回顾会计为N AI step(s) not needed仅--run-migrations下。判定严格为 truetruthy 的非布尔值不会触发。与agentContext同返自相矛盾waiver 生效处 runner 丢弃agentContext只在--verbose下记录。对混合条目它与标记 prompt 阶段完成的确认一并记录migrate UI 以AI step not needed标签展示。其他一切含GeneratorCallback被静默丢弃。关于安装runner 通过 diff package.json 来安装——默认流程在整个运行结束后安装一次--create-commits与 Agent 化运行则每个迁移各装一次。绝不要在迁移里返回安装任务也绝不要调用installPackagesTask。执行模型顺序、失败与 Agent 校验磁盘一致性Tree 的变更只在迁移函数返回后才刷到磁盘。迁移内派生的子进程看到的是迁移前pre-migration的磁盘状态。失败即中止第一个抛错的迁移会中止整个--run-migrations运行没有可恢复的断点状态。fail open。幂等性硬约束nx repair会重跑所有 nx-core 迁移无视版本仅排除x-repair-skip因此 nx-core 迁移必须幂等。Agent 校验环节Agent 化运行会校验 generator 输出——除非用户传--no-validate或迁移返回skipAgentic: true否则一个产生变更的 generator-only 迁移会追加一个 agent 校验步骤。agent 会收到条目描述、documentation路径、捕获的 generator 输出devkit logger 与 consolegenerator_output、变更文件列表以及返回的agentContext它负责验证结果并允许做小幅的范围内修复。校验失败时变更保持未提交状态。schematics 无返回值schematicssection 的条目走 Angular Devkit 适配器其返回值被整体丢弃没有nextSteps也没有agentContext。packageJsonUpdates依赖升级的分组与门控结构见 misc-interfaces.ts 的PackageJsonUpdates与PackageJsonUpdateForPackage{ key: { version: X.Y.Z, packages: { pkg: { version: X.Y.Z, alwaysAddToPackageJson: true, addToPackageJson: false, ifPackageInstalled: other-pkg, ignorePackageGroup: true, ignoreMigrations: true } }, requires: { pkg: ^1.0.0 }, incompatibleWith: { pkg: ^2.0.0 }, x-prompt: ... } }门控与生效规则分组在installed group.version target时生效下界是包含的与迁移条目的严格gt不同。只有已在 dependencies/devDependencies 中的包才会被改动除非设置addToPackageJson/alwaysAddToPackageJsontrue dependencies字符串 指定 sectionalwaysAddToPackageJson优先。跨分组比较时每个包取最高版本降级在写入时被过滤。分组按 key 顺序求值每个被接受的分组写入待定更新集供后续门控检查读取。被requires/incompatibleWith拦住的分组不会被丢弃首轮之后被拦分组会反复重估直到没有更多分组可生效——因此由更晚求值的分组包括其他插件的分组满足的门控仍然能落地。每个分组最多生效一次。多主版本multi-major链需要把 ladder 分组按最老的源主版本在前排序。incompatibleWith是requires的反转当任一列出包的落地版本满足该 range 时分组被跳过。ifPackageInstalled只门控单个包的更新是否落地条件是该包已安装目前没有任何一方插件使用它用requires做分组门控即可。x-prompt只在--interactive且非 CI 时触发且已在 Nx v24 移除计划中——不要新增使用。单个包上的ignorePackageGroup: trueignoreMigrations: true组合可以在升级该包时不带入它自己的 package group 与迁移angular/cli就是这么用的。version--PackageGroup这类 key 是运行时从插件packageGroup合成的绝不要手写。分组 key 对用户可见交互提示页脚中的文档锚点X.Y.Z或针对独立门控的第三方升级使用X.Y.Z-topic。package.json 中的迁移配置readNxMigrateConfig见 package-json.ts按优先级递增的顺序读取三个位置ng-update→nx-migrations→ 顶层裸字段。一方插件first-party plugins的声明方式是{ nx-migrations: { migrations: ./migrations.json, supportsOptionalMigrations: true } }ng-update仅为了 Angular CLI 互操作ng update会读它而保留。packageGroup成员身份packages/nx/package.json写在nx-migrations下packages/workspace/package.json写在ng-update下同时决定了合成分组升级以及--include的 required/optional 划分中 required 一侧的成员不存在逐条目的 optionality 标记。插件作者检查清单新条目一律放generatorsimplementation与factory同时存在时确保implementation是你要发布的那个。implementation/prompt/documentation的路径必须匹配发布后的包布局且 prompt/documentation 必须落在 migrations 目录内。需要人类跟进的内容放nextSteps它是任何场景都可靠的人类通道只有给 AI 的上下文才放agentContext。确定性流程已完备时返回skipAgentic: true严格布尔值避免无谓的 AI 步骤。nx-core 迁移必须幂等因为nx repair会无视版本重跑它们需要豁免时才能用x-repair-skip。不要在迁移里触发安装让 runner 通过 package.json diff 统一处理。发布前人工核对实现路径真实存在不要依赖assertValidMigrationPaths或插件检查做兜底。把握住这份运行时契约你编写的每个迁移条目都能在nx migrate、nx repair与 Agent 化流程中表现出可预期的行为同时避免版本门控、路径解析与幂等性三类最常见的事故。【免费下载链接】nxThe Monorepo Platform that amplifies both developers and AI agents. Nx optimizes your builds, scales your CI, and fixes failed PRs automatically. Ship in half the time.项目地址: https://gitcode.com/GitHub_Trending/nx/nx创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进