mcpField
P
prisma-next-migration-review

prisma-next-migration-review

github.com/prismaデータ・データベース4112.1k 回インストール9 週間前に更新
リポジトリ

prisma-next-migration-review について

デプロイ時やブランチ間の変更が競合する際に、Prisma Next のマイグレーションをレビューするためのスキルです。状態、グラフ上の経路、ref、診断情報を解説し、マイグレーションの作成は扱いません。

主な機能

  1. 01起点、到達先、マイグレーショングラフの解説
  2. 02適用済み・保留・到達不能の確認
  3. 03構造化された診断情報の解釈
  4. 04並行マイグレーション競合のレビュー
  5. 05環境 ref の管理

活用シーン

  1. 01staging デプロイ時のマイグレーション確認
  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 が進んだ場合)。
  • CI からデプロイできるように、staging / production の ref を設定したいとき。
  • ローカルの開発用 DB 以外の環境に対してマイグレーションを実行したいとき。
  • マイグレーションの 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 はマーカーを読み取り、そのハッシュが起点になります。オフライン(DB 接続がない場合)では、起点は不明です。そのため、多くのコマンドはディスク上のマイグレーションの一覧表示にとどまり、エッジごとの適用済み/保留中のステータスを省略します。

したがって、稼働中の DB が起点の信頼できる情報源です。他のアーティファクト(refs、ローカルキャッシュ、ユーザーの想定)にある「記録されたマーカー」は作業用コピーであり、実際の状態からずれることがあります。稼働中の DB の状態がずれることはありません。

到達先

到達先は、データベースをその状態にしたいコントラクトハッシュです。到達先の指定方法は 2 通りあります。

  • --to <name> — migrations/app/refs/<name> に保存された、ハッシュを指す名前付きポインターです。ref は慣例として環境名(staging、production)を付け、*「ここが本番環境の想定される状態です」*と示します。ref 自体はハッシュと、任意で設定される必須不変条件のセットにすぎず、どの DB に接続するかとは関係ありません。
  • 現在のコントラクトヘッド — --to を指定しない場合に暗黙的に使われます。これは、ディスク上の現在の contract.json のハッシュです。

--to staging は「staging データベースに接続する」という意味ではありません。「接続したデータベース(--db または設定経由)を、この ref が指すハッシュに向けてナビゲートする」という意味です。データベースの選択は独立しているため、実際に staging を指定するには --db $STAGING_DATABASE_URL を渡します。

マイグレーショングラフ

ディスク上のマイグレーションは有向グラフを形成します。ノードはコントラクトハッシュ、エッジはマイグレーションです。 各マイグレーションには from ハッシュと to ハッシュが宣言されています。データベースの現在のマーカーがその from ハッシュと一致する場合にのみマイグレーションが適用され、実行されるとマーカーはその to ハッシュに進みます。

migration status は、起点から到達先までの経路をグラフに問い合わせ、エッジごとのステータスを報告します。

  • applied — EMPTY_CONTRACT_HASH からマーカーまでの経路上にあるもの(履歴)。
  • pending — マーカーから到達先までの経路上にあるもの(実行されるマイグレーション)。
  • unreachable — EMPTY_CONTRACT_HASH から到達先までの経路上にあるものの、マーカーは別のブランチにあり、先に経路を変更しない限り到達しません。
診断コード

migration status は、結果エンベロープ(diagnostics[].code)に構造化された診断情報を出力します。これにより、エージェントは概要文を解析するのではなく、コードに基づいて処理を分岐できます。各診断には、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 を正として受け入れる)、db update(コントラクトを DB に反映する)、contract infer(DB からコントラクトを再導出する)、または db verify(まず状態を確認する)を実行します。MIGRATION.MARKER_MISMATCH とは異なります。MARKER_NOT_IN_HISTORY は、ライブマーカーがたどっている経路から外れている場合にランナーのグラフ探索中に出力されます。一方、MARKER_MISMATCH は、マーカーハッシュがグラフ内のどのノードでもない場合に、CLI の DDL 前ゲートでそれより先に出力されます。
MIGRATION.DIVERGEDwarn有効なリーフが複数あるため、移行先があいまいです。--to <name> を渡すか、ref set <name> <hash> を実行して 1 つ作成します。
CONTRACT.AHEADwarnコントラクトのヘッドがグラフ内にありません。再計画せずにコントラクトが編集されています。migration plan を実行してグラフを拡張します。
CONTRACT.UNREADABLEwarncontract.json を読み取れませんでした。contract emit を実行して再生成します。
グラフツリーの出力

migration status(および migration list)は、移行グラフをターミナル上に色分けされたレーンツリーとして表示します。表示方法は 2 つのフラグで制御できます。

  • --legend — ツリーの前に、ツリー記号とレーンの色を示す凡例を表示します。
  • --ascii — 枠線用の記号をパイプで扱える ASCII 文字に置き換えます(CI ログや Unicode に対応していない環境で便利です)。

どちらのフラグも migration list と migration graph で使用できます。migration log がサポートするのは --ascii のみです(ツリーではなく、時系列順のフラットなテーブルを表示します)。

Plan および apply 時の診断

これらのコードは migration plan、ref set、migrate で表示されます。migration status では表示されません。Migration System § Recovery affordances と ADR 218 を参照してください。

コード発生時意味次の手順
MIGRATION.HASH_NOT_IN_GRAPHmigration plan(グラフが空でない場合)または ref set解決されたハッシュがディスク上の移行グラフのノードではありません。通常は、開発時のみの db update サイクルの後、デフォルトの db ref がグラフの先端より先を指している場合に発生します。migration plan --from <reachable-ref>(例:--from production)を実行するか、ref set db <graph-node-hash> で ref を再調整します。
MIGRATION.SNAPSHOT_MISSINGmigration plan名前付き ref にポインターファイル(<name>.json)がなく、解決対象のハッシュも移行グラフのノードではありません。ref set <name> <hash> で ref を作成するか、db update --advance-ref <name> で ref を進めるか、グラフのノードであるハッシュを渡します。
MIGRATION.MARKER_MISMATCHmigrate(ランナー実行前、DDL 前)ライブ DB のマーカーハッシュがグラフのノードではありません。オフラインプランナーでは検知できないドリフトです。マーカーが正規のものであれば 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 に基づいて判断してください。構造については、後述の Workflow — CI を参照してください。

ワークフロー — 「デプロイ時に実行される内容は?」

ユーザーからの質問:「この PR をマージしようとしています。ステージングにデプロイすると、どの移行が実行されますか?」

これはナビゲーションに関する質問です。起点 =ステージングのライブマーカー、宛先 =ref staging(設定していない場合はコントラクトヘッド)です。システムに問い合わせます。

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

このコマンドは次の処理を行います。

  1. ステージング DB のマーカー(起点)を読み取ります。
  2. staging をコントラクトハッシュ(宛先)に解決します。
  3. その間のパスを移行の順序付きリストとして表示し、各エッジの状態を applied/pending/unreachable で示します。また、「ref 'staging' より N 件の移行が遅れています」 という形式の明示的なサマリー行も表示します。
  4. 設定、移行ディレクトリ、アクティブな ref、データベース接続(マスク済み)を示すヘッダーを表示するため、出力から状況を確認できます。

--db を省略すると、コマンドはオフラインで実行されます。ディスク上の移行を一覧表示しますが、起点がないため適用済みかどうかはわかりません。「このブランチには何がありますか?」 という質問にはこれで問題ありませんが、「ステージングで実行される内容は?」 という質問には不十分です。その場合は、ステージングのライブマーカーが必要です。

--to を省略すると、宛先はデフォルトでコントラクトヘッドになります。これは 「このブランチのコントラクトはデータベースから到達可能ですか?また、どのように到達しますか?」 という質問への答えであり、「デプロイ時に何が実行されますか?」 への答えではありません。特定の環境について質問する場合は、ref を明示的に渡してください。

migration status は、保留中の各移行の操作をクラス(additive、widening、data、destructive)ごとに要約し、破壊的な操作がある場合はその件数を報告します。マージまたはデプロイの前に、その件数をユーザーに提示してください。破壊的な操作は手動レビューが必要なクラスです。

ワークフロー — 「各環境の現在の状態は?」

環境ごとの DB に対して migration status --db $URL を実行するだけです。マーカー(起点)は DB 自体から返されます。サマリー行には、その環境がコントラクトヘッドにあるか、名前付き ref にあるか、ヘッドより先にあるか、分岐したブランチ上にあるかが示されます。

コンセプト — 同じ分岐点からの並行マイグレーション

一部の PN ドキュメントでは、以前これを ダイヤモンド収束 と呼んでいました。呼び方に関係なく、状況は同じです。

何が起きているか。 2 つのトピックブランチが、それぞれ同じ親コントラクトハッシュを基点としてマイグレーションを作成しました。先に一方のブランチが main にマージされ、宛先 ref(例:production)がそのブランチの to ハッシュに進みます。もう一方のブランチのマイグレーションでは、from ハッシュが引き続き 古い 親を指しています。リベース後のマイグレーショングラフでは、そのマイグレーションを経由するクリーンなパスがなくなっています。

  • マイグレーションの from が、新しいヘッドの祖先ではなくなっています。
  • または、マイグレーションの from には到達できますが、そのマイグレーションを経由するパスの到達先ハッシュが、両ブランチの変更を統合したものではありません。

どちらの場合も、ディスク上のプランは古くなっています。

解決方法。 from ハッシュがグラフのヘッドではなくなっているため、ディスク上のプランは古くなっています。リベース後の状態に対して、クラスター標準の 編集 → プラン → 適用 のループを実行すると、プランナーが新しいヘッドに from が一致する新しいマイグレーションを生成します。

プランナーが代わりにできない唯一のことは、破棄した migration.ts に含まれるカスタムのデータ変換ロジックを新しいマイグレーションに移植することです。スキーマ差分はコントラクトから導出されますが、手書きの data 操作は、適用前にご自身で引き継ぐ必要があります。別途「再検証」の手順はなく、特別な「ダイヤモンド適用」のフローもありません。

ワークフロー — ref の設定、一覧表示、取得、削除

ref は小さな成果物です。環境ごとのライフサイクルはなく、名前をハッシュに紐付けるだけです。

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> にファイルを作成し、ハッシュと必要な不変条件を記録します。ref はコミットしやすい成果物です。git に保存してください。production が何を指すかは、main が何であるかと同じように、チームで合意します。

ワークフロー — 環境に対してマイグレーションを適用する

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

宛先は ref のハッシュ、起点は本番 DB のライブマーカーです。コマンドはその間のパスを計算し、保留中のマイグレーションを順番に適用して、マーカーを進めます。

--db は環境を選択するためのオプションです。--to は宛先ハッシュを指定するためのオプションです。この 2 つは独立しています。

コンセプト — CI/デプロイ時の ref 不一致

CI が次のように報告します:「記録されている ref production のハッシュは X ですが、ライブ DB のハッシュは Y です。」

この不一致は、一致しない 2 つの状態に関する事実です。どちらが誤っているかに関係なく、調査方法は同じです。

  • DB が ref より先に進んでいる。 誰かが CI の外でマイグレーションを適用したものの、git の ref を更新していません。prisma-next ref set <ref-name> <db-marker-hash> で ref を記録し直して(コミットしてプッシュ)、CI 外で適用が行われた経緯を監査します。
  • DB が ref より遅れている。 以前のデプロイがロールバックされたか、古いバックアップから DB が復元されました。prisma-next migrate --to <ref-name> --db $URL で前方に再適用するか、prisma-next ref set <ref-name> <db-marker-hash> で ref を実際のデプロイ状態に合わせて後方に戻します。どちらを選ぶかはユーザーが決めます。両方の選択肢を提示してください。
  • DB が別のブランチにある。 通常の手順外で行われたスキーマ変更(手動 SQL、場当たり的なマイグレーション)によって、マイグレーショングラフではモデル化されていない変更が加えられています。prisma-next db verify を実行してドリフトを調べたうえで、prisma-next contract infer でデータベースからコントラクトを再導出するか、コントラクトを編集して prisma-next migration plan を実行し、最終的にデータベースを宛先にします。

DB がたまたまどの状態にあるかに ref を黙って合わせるために 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 で終了します。エージェント(または CI ゲート)が diagnostics[] を調べて、ビルドを失敗させる必要があります。人が読む概要ではなく、構造化された形式をゲートで解析できるよう、--json を使ってください。

migrate は対話操作を必要とせず、破壊的操作の確認プロンプトもありません。破壊的な変更に対する安全策として確認を求めるのは db update です(prisma-next-migrations スキルを参照)。プランナーがマイグレーショングラフに設定した内容が、そのまま migrate によって実行されます。レビューは適用ステップの前、migration plan と migration status の実行時に行います。

よくある落とし穴

  1. デプロイについて確認する際に、--to を付けずに migration status を読む。 これは「このブランチのコントラクトはヘッドに到達できるか?」を尋ねるものであり、「ステージングでこれから何が実行されるか?」を尋ねるものではありません。特定の環境について確認する場合は、必ず参照先を指定してください。
  2. デプロイについて確認する際に、--db を付けずに migration status を読む。 ライブ DB がなければ、起点がありません。出力にはディスク上の内容が表示されますが、その環境で何が適用済みかはわかりません。重要な判断では必ず --db $URL を渡してください。
  3. 参照先と DB 接続を混同する。 --to staging は宛先ハッシュを選択するものであり、データベースを選択するものではありません。--to と --db の両方を明示的に渡してください。
  4. ダイヤモンド状の収束を特別な手順として扱う。 そうではありません。リベース後の状態に対して通常の 編集 → 計画 → 適用 のループを行うだけです。追加の手順は「古い migration.ts にあるデータ変換ロジックを移植すること」だけです。
  5. 原因を理解せずに、CI の不一致を解消するため ref set を実行する。 これにより、範囲外で行われた変更やロールバックのずれが隠れてしまうことがあります。まず原因を調査してください。

Prisma Next がまだ対応していないこと

  • デフォルトのチェーンを超える、環境ごとのマイグレーション順序。 ステージングではスキップし、本番環境では必要となるマイグレーションがある場合(またはその逆の場合)、サポートされている方法は、環境ごとの分岐を個別のマイグレーションとして作成し、デプロイスクリプトでゲートすることです。環境ごとのルーティングを標準機能として利用したい場合は、prisma-next-feedback スキルを通じて機能リクエストを提出してください。
  • ブランチを並べて比較する、組み込みの「ブランチ差分」ビュー。 ブランチを表示するグラフ全体のレンダリング(migration graph)はありますが、2 つのブランチのマイグレーションセットを比較する git diff 形式の機能はありません。回避策として、各ブランチで migration status を実行し、出力を diff してください。ブランチ比較ビューを標準機能として利用したい場合は、prisma-next-feedback スキルを通じて機能リクエストを提出してください。

リファレンスファイル

このスキルは意図的に本文のみで構成されています。基盤となる CLI リファレンス(prisma-next migration status --help、migrate --help、ref --help)が、フラグの詳細に関する正式な情報源です。迷った場合は、推測でこのスキルを解釈するのではなく、--help を実行して実際のコマンドの説明を読んでください。

チェックリスト

  • ユーザーの質問について、起点(ライブ DB のマーカー)と移行先(ref またはコントラクトの先頭)の両方を特定しました。
  • 特定の環境が関係する質問では、--db $URL を渡しました。
  • 現在のブランチの先頭からの移行ではなく、名前付き環境へのデプロイに関する質問では、--to <name> を渡しました。
  • エッジごとの一覧を読む前に、migration status のヘッダー(設定、ref、データベースを記載)とサマリー行(起点と移行先の差分を記載)を読みました。
  • マイグレーションの同時実行による競合では、記憶した「ダイヤモンド収束」の手順に従うのではなく、中核となるワークフロー(編集 → plan → apply)を再実行しました。中止した migration.ts にあったデータ変換ロジックも移植しました。
  • ref の不一致について、どの状態が間違っているのか(DB が先行、DB が遅延、DB が分岐したブランチ上にある)を調査しました。不一致を無視するために ref set を実行しませんでした。
  • ユーザーがマージまたはデプロイする前に、migration status の破壊的操作の件数(デプロイ前に手動確認が必要な唯一の操作クラス)を提示しました。
  • CI では、migration status --json の diagnostics[] を解析し、severity === 'warn' を条件にゲートしました。migrate に --dry-run フラグがある(実際には存在しません)とは考えませんでした。
  • --to をデータベースの選択と混同しませんでした(--to は移行先のハッシュを選択し、--db はデータベースを選択します)。
  • --ref は使用しませんでした(削除済みです。--to を使用してください)。
  • このスキルで言及されていない「ブランチ差分」の CLI サブコマンド、migration revalidate の手順、その他の API を作り上げませんでした。

コメント