prisma-next-migration-review
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePrisma Next — Migration Review (Deployment + Concurrency)
Prisma Next — 迁移审核(部署与并发)
Edit your data contract. Prisma handles the rest.
This skill is about reviewing migrations, not authoring them. It covers the questions that come up at deploy time and when multiple developers are landing migrations concurrently.
The skill teaches the system's mental model — what a ref is, what a marker is, what the migration graph is — and shows how to ask the system for its state. It does not prescribe rigid step-by-step procedures: most "review" questions are answered by understanding the model and querying the right thing. Rigid procedures are reserved for the rare case where there's literally one safe path.
编辑你的数据契约,其余工作由Prisma处理。
本技能聚焦于迁移的审核,而非迁移的编写。它涵盖了部署阶段以及多名开发者同时提交迁移时会遇到的各类问题。
本技能会教授系统的心智模型——什么是ref、什么是marker、什么是迁移图谱,并展示如何查询系统状态。它不会规定僵化的分步流程:大多数“审核”问题都可以通过理解模型并执行正确的查询来解决。只有在极少数存在唯一安全路径的情况下,才会使用固定流程。
When to Use
适用场景
- User asks "what migrations will run when I merge this?" or "what's about to run on deploy?".
- User hit a concurrent-migration conflict (advanced while their branch was open).
main - User wants to wire up a /
stagingref so CI can deploy against it.production - User wants to run a migration against an environment that isn't the local dev DB.
- User asks about CI integration for migrations.
- 用户询问“合并此分支后会运行哪些迁移?”或“部署时将要运行什么?”
- 用户遇到并发迁移冲突(分支在其分支开发期间已更新)
main - 用户希望配置/
stagingref,以便CI可以针对其进行部署production - 用户希望针对非本地开发数据库的环境运行迁移
- 用户询问迁移的CI集成相关问题
When Not to Use
不适用场景
- User wants to author a migration → .
prisma-next-migrations - User wants to fix a hash-mismatch / drift in a single env → (re-plan path) or
prisma-next-migrations(envelope-driven).prisma-next-debug - User wants to edit the contract → .
prisma-next-contract
- 用户想要编写迁移 → 使用
prisma-next-migrations - 用户想要修复单个环境中的哈希不匹配/漂移 → 使用(重新规划路径)或
prisma-next-migrations(信封驱动)prisma-next-debug - 用户想要编辑契约 → 使用
prisma-next-contract
Key Concepts — the navigation model
核心概念——导航模型
Every migration question is a navigation from an origin to a destination. Once you have this model, the rest of the skill is just "which command asks the system about which navigation."
**所有迁移问题本质上都是从一个起点到终点的导航问题。**理解这个模型后,本技能的其余内容就只是“使用哪个命令查询系统的哪类导航信息”。
Origin
起点(Origin)
The origin is the database's current contract hash. The database carries a row in PN's marker table that records "this database is at hash X". When the CLI runs online (a is provided, or is set in ), PN reads the marker and that hash is the origin. Offline (no DB connection), the origin is unknown — many commands degrade to listing the on-disk migrations and skip the per-edge applied/pending status.
--db <url>db.connectionprisma-next.config.tsA live DB is therefore the authoritative source of origin. The "recorded marker" in any other artifact (refs, local cache, your assumptions) is a working copy that can drift; the live DB never does.
起点是数据库当前的契约哈希值。数据库在PN的marker表中存储了一行记录,标记着“此数据库处于哈希X状态”。当CLI在线运行(提供或在中设置)时,PN会读取该marker,对应的哈希值即为起点。离线运行(无数据库连接)时,起点未知——许多命令会退化为列出磁盘上的迁移,并跳过每个迁移的已应用/待处理状态。
--db <url>prisma-next.config.tsdb.connection因此,实时数据库是起点的权威来源。其他任何工件(refs、本地缓存、你的假设)中的“记录marker”都是可能发生漂移的副本,而实时数据库永远不会漂移。
Destination
终点(Destination)
The destination is the contract hash you want the database to be at. Two ways to name a destination:
- A — a named pointer to a hash, stored under
--ref <name>. Refs are named after environments by convention (migrations/app/refs/<name>,staging) to communicate "this is where production is expected to be". The ref itself is just a hash + an optional set of required invariants; it has nothing to do with which database you connect to.production - The current contract head — implicit when no is passed. This is the hash of the current
--refon disk.contract.json
--ref staging--db--db $STAGING_DATABASE_URL终点是你希望数据库达到的契约哈希值。有两种方式指定终点:
- ——指向哈希值的命名指针,存储在
--ref <name>下。按照惯例,refs以环境命名(migrations/app/refs/<name>、staging),用于传达“这是生产环境预期的状态”。ref本身只是一个哈希值加上一组可选的必需约束,与你连接的数据库无关。production - 当前契约头——未传递时默认使用,即磁盘上当前
--ref的哈希值。contract.json
--ref staging--db--db $STAGING_DATABASE_URLThe migration graph
迁移图谱
The on-disk migrations form a directed graph: nodes are contract hashes; edges are migrations. Each migration declares a hash and a hash. A migration applies only when the database's current marker matches its hash; running it advances the marker to its hash.
fromtofromtomigration status- applied — on the path from to the marker (history).
EMPTY_CONTRACT_HASH - pending — on the path from the marker to the destination (what would run).
- unreachable — on the path from to the destination, but the marker is on a different branch and won't reach it without first re-routing.
EMPTY_CONTRACT_HASH
磁盘上的迁移构成一个有向图:节点是契约哈希值;边是迁移。每个迁移都声明了哈希值和哈希值。只有当数据库当前的marker与迁移的哈希值匹配时,该迁移才能被应用;运行迁移后,marker会更新为其哈希值。
fromtofromtomigration status- applied(已应用)——位于从到marker的路径上(历史记录)
EMPTY_CONTRACT_HASH - pending(待处理)——位于从marker到终点的路径上(即将运行的内容)
- unreachable(不可达)——位于从到终点的路径上,但marker位于不同分支,若不重新路由则无法到达终点
EMPTY_CONTRACT_HASH
Diagnostic codes
诊断代码
migration statusdiagnostics[].codeseveritywarninfomessagehints| Code | Severity | Meaning in the navigation model | Next move |
|---|---|---|---|
| info | Marker = destination; no edges to walk. | Nothing to do. |
| info | Marker is an ancestor of the destination; N pending edges in between. | |
| info | Marker reached destination structurally but missing required invariants the ref declares. | |
| warn | Online, but the database has no marker row — never initialised. | |
| warn | Online; marker hash is not a node in the graph. The database was changed outside the migration system. | Decide which side is truth: |
| warn | Multiple valid leaves; the destination is ambiguous. | Pass |
| warn | Contract head is not in the graph — the contract was edited without re-planning. | |
| warn | | |
A CI gate should read from output and decide based on plus ; see Workflow — CI below for the structure.
diagnostics--jsonseveritycodemigration statusdiagnostics[].codeseveritywarninfomessagehints| 代码 | 级别 | 导航模型中的含义 | 下一步操作 |
|---|---|---|---|
| info | Marker与终点一致;无需执行任何迁移 | 无需操作 |
| info | Marker是终点的祖先;两者之间有N个待处理迁移 | 执行 |
| info | Marker在结构上已到达终点,但缺少ref声明的必需约束 | 执行 |
| warn | 在线状态,但数据库无marker行——从未初始化 | 执行 |
| warn | 在线状态;marker哈希值不在图谱节点中。数据库在迁移系统外被修改 | 确定哪一方为真相: |
| warn | 存在多个有效分支;终点不明确 | 传递 |
| warn | 契约头不在图谱中——契约已被编辑但未重新规划 | 执行 |
| warn | 无法读取 | 执行 |
CI网关应读取输出中的,并根据和做出决策;请参阅下方“工作流——CI”的结构。
--jsondiagnosticsseveritycodeWorkflow — "What's about to run on deploy?"
工作流——“部署时将要运行什么?”
The user asks: "I'm about to merge this PR. What migrations are going to run when I deploy to staging?"
This is the navigation question: origin = staging's live marker; destination = the ref (or the contract head if you haven't set one). Ask the system:
stagingbash
pnpm prisma-next migration status --to staging --db "$STAGING_DATABASE_URL"The command:
- Reads the staging DB's marker (the origin).
- Resolves to a contract hash (the destination).
staging - Renders the path between them as an ordered list of migrations, with per-edge /
applied/pendingstatus, and an explicit summary line of the form "N migration(s) behind ref 'staging'".unreachable - Prints a header that names the config, migrations directory, the active ref, and the database connection (masked) — so the framing is visible in the output.
If you omit , the command runs offline: it lists the migrations on disk but cannot tell you what's applied, because it has no origin. That's fine for "what's on this branch?"; it's not fine for "what's about to run on staging?" — for that you need staging's live marker.
--dbIf you omit , the destination defaults to the contract head — which answers "is this branch's contract reachable from the database, and how?", not "what runs on deploy". Pass the ref explicitly when the question is about a specific environment.
--refmigration statusadditivewideningdatadestructive用户询问:“我即将合并此PR。部署到预发布环境时会运行哪些迁移?”
这是一个导航问题:起点=预发布环境的实时marker;终点=ref (若未设置则为契约头)。向系统查询:
stagingbash
pnpm prisma-next migration status --to staging --db "$STAGING_DATABASE_URL"该命令:
- 读取预发布数据库的marker(起点)
- 将解析为契约哈希值(终点)
staging - 将两者之间的路径渲染为有序迁移列表,每条边标记/
applied/pending状态,并输出明确的摘要行,格式为“落后于ref 'staging' N个迁移”unreachable - 打印包含配置、迁移目录、活动ref和数据库连接(已掩码)的头部信息——以便在输出中清晰看到上下文
如果省略,命令将离线运行:它会列出磁盘上的迁移,但无法告知哪些已应用,因为没有起点。这适用于“此分支上有什么迁移?”的问题,但不适用于“预发布环境即将运行什么?”——后者需要预发布环境的实时marker。
--db如果省略,终点默认是契约头——这回答的是“此分支的契约是否可从数据库到达,以及如何到达?”,而非“部署时会运行什么”。当问题涉及特定环境时,请显式传递ref。
--refmigration statusadditivewideningdatadestructiveWorkflow — "What state is each environment at?"
工作流——“每个环境处于什么状态?”
Just for each environment's DB. The marker (origin) comes back from the DB itself; the summary line tells you whether the environment is at the contract head, at a named ref, ahead of head, or on a divergent branch.
migration status --db $URL只需对每个环境的数据库执行即可。marker(起点)直接来自数据库本身;摘要行会告知你该环境是处于契约头、命名ref、超前于契约头还是处于分歧分支。
migration status --db $URLConcept — concurrent migrations on the same branch point
概念——同一分支点上的并发迁移
This used to be called diamond convergence in some PN docs; the situation is the same regardless of the label.
What's happening. Two topic branches each authored a migration off the same parent contract hash. The first branch merges to ; the destination ref (e.g. ) advances to that branch's hash. Your branch's migration still has its hash pointing at the old parent. The migration graph, after rebase, no longer has a clean path through your migration:
mainproductiontofrom- Your migration's is no longer an ancestor of the new head.
from - Or your migration's is reachable, but the path through your migration arrives at a hash that's not the union of both branches' changes.
from
Either way, the on-disk plan is stale.
Resolution. The on-disk plan is stale because its hash is no longer the head of the graph; apply the cluster's standard edit → plan → apply loop to the post-rebase state and the planner produces a fresh migration whose matches the new head.
fromfromThe one thing the planner can't do for you is port custom data-transform logic from the abandoned into the new one — schema deltas are derived from the contract, but any hand-written operations are yours to carry across before applying. There is no separate "revalidate" step, no special "diamond apply" flow.
migration.tsdata在某些PN文档中,这曾被称为菱形收敛;无论标签如何,场景都是相同的。
发生的情况:两个主题分支均基于同一个父契约哈希值编写了迁移。第一个分支合并到;目标ref(如)更新为该分支的哈希值。你的分支的迁移仍将哈希值指向旧的父节点。重新基址后,迁移图谱不再有通过你的迁移的清晰路径:
mainproductiontofrom- 你的迁移的不再是新分支头的祖先
from - 或者你的迁移的可达,但通过你的迁移到达的哈希值并非两个分支变更的并集
from
无论哪种情况,磁盘上的规划都已过时。
解决方案:磁盘上的规划过时是因为其哈希值不再是图谱的分支头;对重新基址后的状态应用集群标准的编辑→规划→应用循环,规划器会生成一个新的迁移,其与新分支头匹配。
fromfrom规划器无法为你完成的一件事是将废弃的中的自定义数据转换逻辑移植到新迁移中——模式差异是从契约推导而来,但任何手写的操作都需要你在应用前自行迁移。没有单独的“重新验证”步骤,也没有特殊的“菱形应用”流程。
migration.tsdataWorkflow — set, list, get, delete refs
工作流——设置、列出、获取、删除refs
Refs are small artifacts. There's no per-environment lifecycle; you just point a name at a hash.
bash
pnpm prisma-next ref set production <contract-hash>
pnpm prisma-next ref listrefs是小型工件。没有每个环境的生命周期;只需将名称指向哈希值即可。
bash
pnpm prisma-next ref set production <contract-hash>
pnpm prisma-next ref listref get
was removed — use ref list
and filter by name
ref getref listref get
已被移除——使用ref list
并按名称过滤
ref getref listpnpm prisma-next ref list | grep production
pnpm prisma-next ref delete production
`ref set` writes a file at `migrations/app/refs/<name>` carrying the hash and any required invariants. Refs are commit-friendly artifacts — keep them in git; the team agrees on what `production` points at the same way they agree on what `main` is.pnpm prisma-next ref list | grep production
pnpm prisma-next ref delete production
`ref set`会在`migrations/app/refs/<name>`写入一个包含哈希值和任何必需约束的文件。refs是适合提交的工件——将其保存在git中;团队就`production`指向的内容达成一致,就像他们就`main`分支的内容达成一致一样。Workflow — apply a migration against an environment
工作流——针对环境应用迁移
bash
pnpm prisma-next migrate --to production --db "$PRODUCTION_DATABASE_URL"The destination is the ref's hash; the origin is the production DB's live marker. The command computes the path between them and applies each pending migration in order, advancing the marker.
--db--refbash
pnpm prisma-next migrate --to production --db "$PRODUCTION_DATABASE_URL"终点是ref的哈希值;起点是生产数据库的实时marker。该命令会计算两者之间的路径,并按顺序应用每个待处理迁移,更新marker。
--db--refConcept — ref-mismatch on CI / deploy
概念——CI/部署时的ref不匹配
CI reports: "the recorded ref is at hash X; the live DB is at hash Y."
productionThe mismatch is a fact about two pieces of state that disagree. The investigation is the same regardless of which piece is wrong:
- DB ahead of the ref. Someone applied a migration outside CI without updating the ref in git. Re-record the ref with (commit + push); then audit how the out-of-band apply happened.
prisma-next ref set <ref-name> <db-marker-hash> - DB behind the ref. A previous deploy was rolled back, or the DB was restored from an older backup. Either re-apply forward with , or re-route the ref backward to match what's actually deployed with
prisma-next migrate --to <ref-name> --db $URL. The choice is the user's — name both options.prisma-next ref set <ref-name> <db-marker-hash> - DB on a different branch. An out-of-band schema change (manual SQL, ad-hoc migration) wrote something the migration graph doesn't model. Run to inspect the drift, then either
prisma-next db verifyto re-derive the contract from the database, or edit the contract and runprisma-next contract inferso the database is the eventual destination.prisma-next migration plan
ref setCI报告:“记录的ref 处于哈希X;实时数据库处于哈希Y。”
production不匹配是两种状态不一致的事实。无论哪一方出错,调查流程都是相同的:
- 数据库超前于ref:有人在CI外应用了迁移,但未更新git中的ref。使用重新记录ref(提交并推送);然后审核该非预期应用是如何发生的。
prisma-next ref set <ref-name> <db-marker-hash> - 数据库落后于ref:之前的部署被回滚,或者数据库从旧备份恢复。可以选择执行向前重新应用,或者执行
prisma-next migrate --to <ref-name> --db $URL将ref重新路由到实际部署的状态。选择权在用户手中——请列出这两个选项。prisma-next ref set <ref-name> <db-marker-hash> - 数据库位于不同分支:非预期的模式变更(手动SQL、临时迁移)写入了迁移图谱未建模的内容。运行检查漂移,然后选择执行
prisma-next db verify从数据库重新推导契约,或编辑契约并运行prisma-next contract infer使数据库最终到达目标状态。prisma-next migration plan
使用静默对齐ref与当前数据库状态几乎永远不是正确的做法。这会掩盖你以后需要付出代价的漂移问题。
ref setWorkflow — CI: verify a branch can advance the target environment
工作流——CI:验证分支能否推进目标环境
The gate is : it computes the path from the live marker to the ref and reports it, without mutating anything. There is no flag on ; the inspect / gate step is .
migration status --to <env> --db $URL--dry-runmigratemigration statusyaml
- 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 statusMIGRATION.MARKER_NOT_IN_HISTORYMIGRATION.DIVERGEDCONTRACT.AHEADMIGRATION.NO_MARKERseverity: 'warn'0diagnostics[]--jsonmigratedb updateprisma-next-migrationsmigratemigration planmigration status网关是:它计算从实时marker到ref的路径并报告,不会修改任何内容。没有标志;检查/网关步骤是。
migration status --to <env> --db $URLmigrate--dry-runmigration statusyaml
- name: 验证预发布环境可达
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("阻塞性诊断信息:", warns);
process.exit(1);
}
'
- name: 应用迁移
run: pnpm prisma-next migrate --to staging --db "$STAGING_DATABASE_URL"migration statusMIGRATION.MARKER_NOT_IN_HISTORYMIGRATION.DIVERGEDCONTRACT.AHEADMIGRATION.NO_MARKERseverity: 'warn'0diagnostics[]--jsonmigratedb updateprisma-next-migrationsmigratemigration planmigration statusCommon Pitfalls
常见陷阱
- Reading without
migration statusfor a deploy question. That asks "can this branch's contract reach the head?", not "what's about to run on staging?". Always pass the ref when the question is about a specific environment.--ref - Reading without
migration statusfor a deploy question. Without a live DB, you have no origin. The output lists what's on disk; it can't say what's applied on the environment. Pass--dbfor any high-stakes question.--db $URL - Confusing the ref with a DB connection. selects the destination hash, not the database. Pass both
--ref stagingand--refexplicitly.--db - Treating diamond convergence as a special procedure. It's not. It's the normal edit → plan → apply loop applied to the post-rebase state. The only extra step is "port any data-transform logic from your old over."
migration.ts - Running to silence a CI mismatch without understanding the cause. That can mask out-of-band changes or rollback drift. Investigate first.
ref set
- 针对部署问题读取时未传递
migration status:这询问的是“此分支的契约能否到达分支头?”,而非“预发布环境即将运行什么?”。当问题涉及特定环境时,请始终传递ref。--ref - 针对部署问题读取时未传递
migration status:没有实时数据库,就没有起点。输出仅列出磁盘上的内容;无法说明环境中已应用的迁移。对于任何高风险问题,请传递--db。--db $URL - 混淆ref与数据库连接:选择的是终点哈希值,而非数据库。请显式传递
--ref staging和--ref。--db - 将菱形收敛视为特殊流程:它不是。这只是对重新基址后的状态应用常规的编辑→规划→应用循环。唯一的额外步骤是“将旧中的任何数据转换逻辑移植过来”。
migration.ts - 在未理解原因的情况下运行以消除CI不匹配:这可能掩盖非预期变更或回滚漂移。请先调查原因。
ref set
What Prisma Next doesn't do yet
Prisma Next目前尚未支持的功能
- Per-environment migration ordering beyond the default chain. If you need staging to skip a migration that production requires (or vice versa), the supported path is to author the per-env divergence as separate migrations and gate them in your deploy script. If you want first-class per-env routing, file a feature request via the skill.
prisma-next-feedback - A built-in side-by-side "branch diff" view. There is a full-graph render () that shows branches, but no
migration graph-style comparison between two branches' migration sets. Workaround: rungit diffon each branch andmigration statusthe output. If you want a built-in branch-comparison view, file a feature request via thediffskill.prisma-next-feedback
- 默认链之外的每个环境迁移排序:如果需要预发布环境跳过生产环境需要的迁移(反之亦然),支持的方式是将每个环境的差异编写为单独的迁移,并在部署脚本中进行控制。如果需要一流的每个环境路由,请通过技能提交功能请求。
prisma-next-feedback - 内置的并排“分支差异”视图:有完整的图谱渲染()显示分支,但没有类似
migration graph的两个分支迁移集比较视图。解决方法:在每个分支上运行git diff并对比输出。如果需要内置的分支比较视图,请通过migration status技能提交功能请求。prisma-next-feedback
Reference Files
参考文件
This skill is intentionally body-only; the underlying CLI reference (, , ) is the authoritative surface for flag-level detail. When in doubt, run and read the actual command's description rather than guessing from this skill.
prisma-next migration status --helpmigrate --helpref --help--help本技能仅包含主体内容;底层CLI参考(、、)是标志级细节的权威来源。如有疑问,请运行并阅读实际命令的描述,而非根据本技能猜测。
prisma-next migration status --helpmigrate --helpref --help--helpChecklist
检查清单
- Named both the origin (live DB marker) and the destination (ref or contract head) for the question the user asked.
- Passed whenever the question involves a specific environment.
--db $URL - Passed whenever the question is about deploying to a named environment, not just from the current branch's head.
--ref <name> - Read the header (it names config, ref, database) and the summary line (it names the origin/destination distance) before reading the per-edge list.
migration status - For concurrent-migration conflicts: re-applied the core workflow (edit → plan → apply) rather than following a memorised "diamond convergence" procedure. Ported any data-transform logic from the abandoned over.
migration.ts - For a ref-mismatch: investigated which piece of state is wrong (DB ahead, DB behind, DB on a divergent branch). Did NOT to silence the mismatch.
ref set - Surfaced the destructive-op count from (the only operation class that warrants manual review pre-deploy) before the user merges or deploys.
migration status - In CI: parsed
migration status --jsonand gated ondiagnostics[]; did NOT rely on aseverity === 'warn'flag on--dry-run(no such flag exists).migrate - Did NOT confuse with database selection.
--ref - Did NOT confabulate a "branch diff" CLI subcommand, a step, or any other API the skill above doesn't reference.
migration revalidate
- 为用户的问题明确了起点(实时数据库marker)和终点(ref或契约头)
- 每当问题涉及特定环境时,都传递了
--db $URL - 每当问题是关于部署到命名环境(而非仅从当前分支头部署)时,都传递了
--ref <name> - 在读取每条边的列表之前,先读取的头部(它会命名配置、ref、数据库)和摘要行(它会命名起点/终点的差距)
migration status - 对于并发迁移冲突:重新应用核心工作流(编辑→规划→应用),而非遵循记忆中的“菱形收敛”流程。将旧中的任何数据转换逻辑移植过来
migration.ts - 对于ref不匹配:调查哪一方状态出错(数据库超前、数据库落后、数据库位于分歧分支)。未使用消除不匹配
ref set - 在用户合并或部署前,展示了中的破坏性操作数量(这是部署前需要手动审核的唯一操作类别)
migration status - 在CI中:解析的
migration status --json并根据diagnostics[]进行控制;未依赖severity === 'warn'的migrate标志(不存在该标志)--dry-run - 未混淆与数据库选择
--ref - 未虚构“分支差异”CLI子命令、步骤或本技能未提及的任何其他API
migration revalidate