mcpField
P
prisma-next-migration-review

prisma-next-migration-review

github.com/prisma数据与数据库4112.1k 次安装9 周前更新
代码仓库

关于 prisma-next-migration-review

用于在部署和并行分支变更时审查 Prisma Next 迁移的指导技能。它讲解迁移状态、图导航、引用和诊断信息,不负责编写迁移。

主要功能

  1. 01讲解起点、目标与迁移图
  2. 02检查已应用、待处理和不可达迁移
  3. 03解读结构化迁移诊断
  4. 04审查并行迁移冲突
  5. 05管理环境引用

适用场景

  1. 01预览部署到 staging 的迁移
  2. 02检查多个环境的迁移状态
  3. 03在并行分支变基后处理过期计划

安装

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

$npx skills add https://github.com/prisma/prisma-next --skill prisma-next-migration-review

安装后在 Claude Code 中输入/prisma-next-migration-review确认已加载。

详细介绍

Prisma Next — 迁移审查(部署 + 并发)

编辑数据契约,其余交给 Prisma 处理。

本技能用于审查迁移,而不是编写迁移。它涵盖部署时以及多位开发者同时提交迁移时会遇到的问题。

本技能讲解系统的心智模型——什么是 ref、什么是标记、什么是迁移图——并演示如何查询系统状态。它不规定僵化的逐步流程:大多数“审查”问题,只要理解模型并查询正确的信息就能解答。只有在确实仅有一条安全路径的罕见情况下,才会规定严格流程。

适用场景

  • 用户询问*“合并这个之后会运行哪些迁移?”或“部署时即将运行哪些迁移?”*。
  • 用户遇到并发迁移冲突(其分支尚未合并时,main 已有新提交)。
  • 用户想配置 staging / production ref,以便 CI 针对其部署。
  • 用户想要对非本地开发数据库的环境运行迁移。
  • 用户询问迁移的 CI 集成。

不适用场景

  • 用户想要编写迁移 → prisma-next-migrations。
  • 用户想要修复单个环境中的哈希不匹配 / 漂移 → prisma-next-migrations(重新规划路径)或 prisma-next-debug(由信封驱动)。
  • 用户想要编辑契约 → prisma-next-contract。

核心概念——导航模型

**每个迁移问题都是从起点导航到目标。**理解这个模型后,本技能剩下的内容就是“用哪个命令查询系统中的哪种导航”。

起点

起点是数据库的当前契约哈希。数据库在 PN 的标记表中有一条记录,记载*“此数据库当前处于哈希 X”*。CLI 在线运行时(提供了 --db <url>,或设置了 prisma-next.config.ts 中的 db.connection),PN 会读取标记,并将该哈希作为起点。离线运行时(没有数据库连接),起点未知——许多命令会退化为列出磁盘上的迁移,并跳过逐边的已应用 / 待处理状态。

因此,实时数据库是起点的权威来源。其他制品中的“已记录标记”(refs、本地缓存、你的假设)都只是可能发生漂移的工作副本;实时数据库不会漂移。

目标

目标是你希望数据库达到的契约哈希。指定目标有两种方式:

  • --to <name>——指向某个哈希的命名指针,存储在 migrations/app/refs/<name> 下。按照惯例,refs 以环境命名(staging、production),用于表达*“这是预期的 production 状态”*。ref 本身只是一个哈希,以及一组可选的必需不变量;它与连接到哪个数据库无关。
  • 当前契约头——未传入 --to 时隐式使用。它是磁盘上当前 contract.json 的哈希。

--to staging 不表示“连接到 staging 数据库”。它表示“让已连接的数据库(通过 --db 或配置指定)朝此 ref 指向的哈希迁移”。数据库选择是独立的:传入 --db $STAGING_DATABASE_URL 才会实际指向 staging。

迁移图

磁盘上的迁移构成一个有向图:**节点是契约哈希;边是迁移。**每个迁移都声明一个 from 哈希和一个 to 哈希。只有当数据库当前标记与迁移的 from 哈希匹配时,迁移才会应用;运行迁移后,标记会更新为其 to 哈希。

migration status 会查询从起点到目标的图路径,并报告每条边的状态:

  • applied — 位于从 EMPTY_CONTRACT_HASH 到标记的路径上(历史记录)。
  • pending — 位于从标记到目标的路径上(即将运行的内容)。
  • unreachable — 位于从 EMPTY_CONTRACT_HASH 到目标的路径上,但标记处于另一分支;若不先重新规划路径,就无法到达目标。
诊断代码

migration status 会在结果封装中输出结构化诊断(diagnostics[].code),让 Agent 可以根据代码分支,而不必解析概要文本。每条诊断还包含 severity(warn 或 info)、面向用户的 message,以及 hints——与 CLI 在概要行下方打印的提示相同。

代码严重程度在导航模型中的含义后续操作
MIGRATION.UP_TO_DATEinfo标记 = 目标位置;没有待遍历的边。无需操作。
MIGRATION.DATABASE_BEHINDinfo标记是目标位置的祖先;两者之间有 N 条待处理边。执行 migrate --to <name> --db $URL。
MIGRATION.MISSING_INVARIANTSinfo从结构上看,标记已到达目标位置,但缺少该 ref 声明的必需不变量。执行 migrate --to <name> --db $URL,选择一条涵盖这些不变量的路径。
MIGRATION.NO_MARKERwarn数据库在线,但没有标记行——从未初始化。执行 migrate --db $URL(首次应用时会写入标记)。
MIGRATION.MARKER_NOT_IN_HISTORYwarn数据库在线;标记哈希不是图中的节点。数据库已在迁移系统之外被更改。决定哪一方为准:db sign(接受数据库为准)、db update(将合约推送到数据库)、contract infer(根据数据库重新推导合约),或 db verify(先检查)。这与 MIGRATION.MARKER_MISMATCH 不同:MARKER_NOT_IN_HISTORY 在运行器遍历图时发出,此时当前标记不在正在遍历的路径上;MARKER_MISMATCH 则更早触发,在 CLI 执行 DDL 前的关卡中发出,此时标记哈希根本不是图中的节点。
MIGRATION.DIVERGEDwarn存在多个有效叶节点;目标位置不明确。传入 --to <name>,或使用 ref set <name> <hash> 创建一个目标位置。
CONTRACT.AHEADwarn合约头不在图中——合约已编辑,但未重新规划。执行 migration plan 扩展图。
CONTRACT.UNREADABLEwarn无法读取 contract.json。执行 contract emit 重新生成。
图树输出

migration status(以及 migration list)会在终端中将迁移图渲染为带颜色的通道树。有两个标志控制渲染方式:

  • --legend — 在树之前打印树形符号和通道颜色的说明。
  • --ascii — 将框线符号替换为兼容管道的 ASCII 字符(适用于 CI 日志或不支持 Unicode 的环境)。

migration list 和 migration graph 也支持这两个标志。migration log 仅支持 --ascii(它会渲染为按时间顺序排列的平面表格,而不是树)。

计划与应用时的诊断

这些代码会出现在 migration plan、ref set 和 migrate 中,而不会出现在 migration status 中。参见 Migration System § Recovery affordances 和 ADR 218。

CodeWhenMeaningNext move
MIGRATION.HASH_NOT_IN_GRAPHmigration plan(图非空时)或 ref set解析出的哈希不是磁盘迁移图中的节点——通常是默认 db 引用在仅用于开发的 db update 周期后指向了图的末端之外。使用 migration plan --from <reachable-ref>(例如 --from production);或使用 ref set db <graph-node-hash> 使引用重新对齐。
MIGRATION.SNAPSHOT_MISSINGmigration plan某个命名引用没有指针文件(<name>.json),且正在解析的哈希也不是迁移图中的节点。使用 ref set <name> <hash> 创建引用,使用 db update --advance-ref <name> 推进引用,或传入一个图节点哈希。
MIGRATION.MARKER_MISMATCHmigrate(执行 DDL 前、运行器启动前)实时数据库标记哈希不是图节点——这是离线规划器无法察觉的漂移。如果标记是规范值,使用 migration plan --from <graph-tip>;如果磁盘图是规范值,使用 ref set db <marker-hash>;调查在系统之外执行的应用操作。
MIGRATION.PATH_UNREACHABLEmigrate(路径解析时)从当前标记到已解析目标在磁盘图中不存在迁移路径。查看改进后的 fix 负载——其中列出了 fromHash / targetHash,并建议使用 migration plan --from <from> --to <target>;运行 migration list 检查图。

CI 门禁应读取 --json 输出中的 diagnostics,并根据 severity 和 code 作出判断;结构见下文 工作流 — CI。

工作流 — “部署时即将运行什么?”

用户问:“我准备合并这个 PR。部署到 staging 时会运行哪些迁移?”

这是关于导航的问题:起点 = staging 的实时标记;终点 = staging 引用(如果尚未设置,则为契约头)。向系统询问:

pnpm prisma-next migration status --to staging --db "$STAGING_DATABASE_URL"

该命令会:

  1. 读取 staging 数据库的标记(起点)。
  2. 将 staging 解析为契约哈希(终点)。
  3. 将两者之间的路径呈现为有序迁移列表,并标明每条边的 applied / pending / unreachable 状态,还会明确输出一条摘要,例如 “距引用 'staging' 落后 N 个迁移”。
  4. 输出一个标头,其中列出配置、迁移目录、当前活动引用和数据库连接(已屏蔽),以便在输出中清楚呈现上下文。

如果省略 --db,命令会离线运行:它会列出磁盘上的迁移,但无法判断哪些已应用,因为没有起点。对于 “这个分支上有什么?”,这没问题;但对于 “部署到 staging 时即将运行什么?”,则不行——要回答这个问题,需要 staging 的实时标记。

如果省略 --to,终点默认为契约头——这回答的是 “这个分支的契约能否从数据库到达,以及如何到达?”,而不是 “部署时会运行什么?”。如果问题涉及特定环境,请明确传入引用。

migration status 会按类别(additive、widening、data、destructive)汇总每个待处理迁移的操作,并在存在破坏性操作时报告其数量。在用户合并或部署前,应向用户展示该数量——破坏性操作最需要人工审核。

工作流 — “各环境处于什么状态?”

对每个环境的数据库运行 migration status --db $URL 即可。起点标记由数据库本身返回;摘要会说明环境是否处于契约头、某个命名引用、领先于契约头,或位于分叉分支上。

概念 — 在同一分支点上并发迁移

在一些 PN 文档中,这曾被称为 菱形汇合;无论名称如何,这种情况都相同。

发生了什么。 两个主题分支都基于同一个父合约哈希创建了迁移。第一个分支合并到 main;目标引用(例如 production)前进到该分支的 to 哈希。你的分支迁移仍然有一个指向旧父级的 from 哈希。变基后,迁移图中已没有经过你这项迁移的干净路径:

  • 你的迁移的 from 不再是新头的祖先。
  • 或者,你的迁移的 from 仍然可达,但经过你的迁移到达的哈希并非两个分支更改的并集。

无论哪种情况,磁盘上的计划都已过时。

解决方案。 磁盘上的计划已过时,因为它的 from 哈希已不再是图的头;针对变基后的状态,执行集群标准的 编辑 → 计划 → 应用 循环,规划器便会生成一项新的迁移,其 from 与新头一致。

规划器唯一无法替你做的事是将已废弃的 migration.ts 中自定义的数据转换逻辑移植到新文件中——架构差异会根据合约推导,但任何手写的 data 操作都需要你在应用前自行移植。没有单独的“重新验证”步骤,也没有特殊的“菱形应用”流程。

工作流 — 设置、列出、获取和删除引用

引用是小型制品。它们没有按环境区分的生命周期;你只需将一个名称指向某个哈希。

pnpm prisma-next ref set production <contract-hash>
pnpm prisma-next ref list
# `ref get` was removed — use `ref list` and filter by name
pnpm prisma-next ref list | grep production
pnpm prisma-next ref delete production

ref set 会在 migrations/app/refs/<name> 写入一个文件,其中包含哈希和任何必需的不变量。引用是便于提交的制品——请将它们保存在 git 中;团队对 production 指向何处达成共识的方式,与对 main 指向何处达成共识的方式相同。

工作流 — 针对环境应用迁移

pnpm prisma-next migrate --to production --db "$PRODUCTION_DATABASE_URL"

目标是引用的哈希;起点是生产数据库的实时标记。该命令会计算两者之间的路径,并按顺序应用每项待处理的迁移,同时推进标记。

--db 用于选择环境。--to 用于指定目标哈希。两者相互独立。

概念 — CI / 部署中的引用不匹配

CI 报告:“记录的引用 production 位于哈希 X;实时数据库位于哈希 Y。”

不匹配反映的是两项状态彼此不一致这一事实。无论哪一项有误,调查方式都相同:

  • 数据库领先于引用。 有人在 CI 之外应用了迁移,却没有在 git 中更新引用。使用 prisma-next ref set <ref-name> <db-marker-hash> 重新记录引用(提交并推送);然后审查这次非计划内应用是如何发生的。
  • 数据库落后于引用。 之前的部署已回滚,或数据库从较旧的备份恢复。可以使用 prisma-next migrate --to <ref-name> --db $URL 向前重新应用,也可以使用 prisma-next ref set <ref-name> <db-marker-hash> 将引用重新指向后方,以匹配实际部署的状态。由用户选择——请同时说明这两个选项。
  • 数据库位于不同分支上。 非计划内的架构更改(手动 SQL、临时迁移)写入了迁移图未建模的内容。运行 prisma-next db verify 检查漂移,然后运行 prisma-next contract infer 从数据库重新推导合约,或编辑合约并运行 prisma-next migration plan,让数据库最终达到目标状态。

使用 ref set 默默地将引用对齐到数据库当前所在位置,几乎从来不是正确做法。这样只是掩盖了漂移,而你之后终将为此付出代价。

工作流 — CI:验证分支能否推进目标环境

检查门槛是 migration status --to <env> --db $URL:它会计算从当前标记到指定引用的路径并报告结果,不会修改任何内容。migrate 没有 --dry-run 标志;检查/门槛步骤是 migration status。

若要在应用前以人类可读的形式预览有序迁移路径,请使用 migrate --show --db $URL。部署后若要查看已应用的历史记录,请使用 migration log --db $URL(按时间顺序排列的平面表格)。

- name: Verify staging is reachable
  run: |
    pnpm prisma-next migration status \
      --to staging --db "$STAGING_DATABASE_URL" --json > status.json
    node -e '
      const s = JSON.parse(require("fs").readFileSync("status.json", "utf8"));
      const warns = (s.diagnostics ?? []).filter(d => d.severity === "warn");
      if (warns.length) {
        console.error("Blocking diagnostics:", warns);
        process.exit(1);
      }
    '
- name: Apply
  run: pnpm prisma-next migrate --to staging --db "$STAGING_DATABASE_URL"

migration status 仅在遇到硬错误时以非零状态退出(迁移目录不可读、约束无法满足、历史记录无法重建)。诸如 MIGRATION.MARKER_NOT_IN_HISTORY、MIGRATION.DIVERGED、CONTRACT.AHEAD 和 MIGRATION.NO_MARKER 这样的诊断会在结果封装中以 severity: 'warn' 报告,但进程仍以 0 退出——Agent(或 CI 检查门槛)必须检查 diagnostics[] 并自行判定构建失败。使用 --json,让检查门槛解析结构化数据,而不是人类可读的摘要。

migrate 无需交互,也不会提示确认破坏性操作——针对破坏性变更的安全措施位于 db update 中(参见 prisma-next-migrations 技能)。规划器在迁移图中安排的内容,就是 migrate 会执行的内容;审查发生在应用步骤之前的 migration plan 和 migration status 阶段。

常见陷阱

  1. 针对部署问题,在不带 --to 的情况下读取 migration status。 这回答的是 “此分支的契约能否到达当前头部?”,而不是 “即将在 staging 上运行什么?”。如果问题涉及特定环境,务必传入引用。
  2. 针对部署问题,在不带 --db 的情况下读取 migration status。 没有实时数据库,就没有起点。输出会列出磁盘上的内容,但无法说明环境中已应用的内容。对于任何高风险问题,都要传入 --db $URL。
  3. 将引用与数据库连接混淆。 --to staging 选择的是目标哈希,而不是数据库。务必同时显式传入 --to 和 --db。
  4. 把菱形收敛当作特殊流程。 它不是特殊流程,而是将常规的 编辑 → 规划 → 应用 循环用于变基后的状态。唯一额外的步骤是 “将旧 migration.ts 中的任何数据转换逻辑移植过来。”
  5. 不明原因就运行 ref set 来消除 CI 不匹配。 这可能会掩盖越权变更或回滚偏差。先调查原因。

Prisma Next 目前尚不支持的功能

  • 超出默认链的按环境迁移排序。 如果你需要 staging 跳过 production 必须执行的迁移(反之亦然),受支持的做法是将各环境的分歧编写为独立迁移,并在部署脚本中为其设置门槛。如果你希望支持一流的按环境路由,请通过 prisma-next-feedback 技能提交功能请求。
  • 内置的并排“分支差异”视图。 有完整的图形渲染(migration graph)可显示分支,但没有类似 git diff 的视图来比较两个分支的迁移集。替代方案:在每个分支上运行 migration status,然后对输出运行 diff。如果你希望内置分支比较视图,请通过 prisma-next-feedback 技能提交功能请求。

参考文件

此技能有意仅包含正文;底层 CLI 参考(prisma-next migration status --help、migrate --help、ref --help)是标志级详细信息的权威来源。如有疑问,请运行 --help 并阅读实际命令的说明,而不要根据此技能猜测。

检查清单

  • 针对用户提出的问题,同时指出了来源(实时数据库标记)和目标(引用或合约头)。
  • 问题涉及特定环境时,传入了 --db $URL。
  • 问题涉及部署到指定环境(而不只是从当前分支的头部部署)时,传入了 --to <name>。
  • 阅读逐边列表前,先查看了 migration status 标头(其中列出了配置、引用、数据库)和摘要行(其中列出了来源与目标之间的距离)。
  • 对于并发迁移冲突:重新应用了核心工作流(编辑 → 规划 → 应用),而不是遵循记忆中的“菱形收敛”流程。将任何数据转换逻辑从已弃用的 migration.ts 移植过来。
  • 对于引用不匹配:调查了哪部分状态有误(数据库超前、数据库落后、数据库位于分叉分支)。没有使用 ref set 来掩盖不匹配。
  • 在用户合并或部署之前,指出了 migration status 中的破坏性操作数量(这是唯一需要在部署前人工审核的操作类别)。
  • 在 CI 中:解析了 migration status --json 的 diagnostics[],并在 severity === 'warn' 时进行拦截;没有依赖 migrate 的 --dry-run 标志(该标志不存在)。
  • 没有混淆 --to 和数据库选择(--to 选择目标哈希;--db 选择数据库)。
  • 没有使用 --ref(已移除;请使用 --to)。
  • 没有臆造“分支差异” CLI 子命令、migration revalidate 步骤,或上述技能未提及的其他 API。

评论

支持 Markdown