civicship-api データベースマイグレーションガイド
Prismaスキーマ変更、マイグレーション作成、型生成をプロジェクトのベストプラクティスに従って安全にガイドします。
使用方法
# マイグレーションワークフローを実行 /db-migration # マイグレーションステータスのみをチェック /db-migration status
マイグレーションワークフロー
ステップ1: スキーマ変更の検出
prisma/schema.prisma に未コミット変更があるかチェック:
git status --porcelain prisma/schema.prisma
変更なしの場合:
- •メッセージ表示: "スキーマ変更は検出されませんでした"
- •保留中のマイグレーションをチェック
変更が検出された場合:
- •diffを表示:
git diff prisma/schema.prisma - •検証へ進む
ステップ2: スキーマ変更の検証
スキーマ変更を読み取り、一般的な問題を分析:
チェック項目:
- •
破壊的変更
- •データマイグレーションなしでのカラム削除
- •カラム型の変更(データ損失の可能性)
- •外部キー依存関係のあるテーブルの削除
- •プライマリキーの変更
- •
制約の欠落
- •インデックスのない外部キー
- •nullable フィールドに対するユニーク制約
- •non-nullable フィールドへの @default の欠落
- •
命名規則
- •テーブル名: snake_case(例:
t_users,t_opportunities) - •カラム名: camelCase(例:
createdAt,updatedAt) - •Enum名: PascalCase(例:
UserStatus,PublishStatus)
- •テーブル名: snake_case(例:
- •
Row-Level Security (RLS)
- •テーブルは
t_プレフィックスを持つべき(例:t_users) - •RLSポリシーの更新が必要かチェック
- •テーブルは
- •
インデックス
- •外部キーにはインデックスがあるべき
- •頻繁にクエリされるカラムにインデックスを追加
- •複数カラムクエリには複合インデックスを検討
検証結果を表示:
## スキーマ検証 ✅ 破壊的変更は検出されませんでした ✅ 命名規則に従っています ⚠️ 外部キーにインデックスがありません: `t_reservations` の `opportunityId` ⚠️ `t_participations` の `status` フィールドに @default の追加を検討してください
ステップ3: マイグレーション名の生成
規約に従った説明的なマイグレーション名を提案:
フォーマット: {action}_{subject}_{detail}
アクション:
- •
add- 新しいテーブルまたはカラム - •
update- 既存構造の変更 - •
remove- テーブルまたはカラムの削除 - •
fix- バグ修正または訂正 - •
refactor- 構造の改善
例:
- •
add_user_phone_field - •
update_opportunity_status_enum - •
remove_deprecated_wallet_type - •
fix_reservation_foreign_key - •
refactor_identity_primary_key
スキーマdiffを分析して名前を提案:
# 新しいテーブルを追加する場合 add_products_table # フィールドを追加する場合 add_user_email_verified_field # enumを変更する場合 update_publish_status_enum
ステップ4: マイグレーションの作成
重要: マイグレーションを自動実行しないでください。最初にユーザーの確認を求めてください。
マイグレーションコマンドを表示し、承認を待機:
## マイグレーションコマンド マイグレーション名 `add_user_phone_field` で作成準備完了 実行コマンド: \`\`\`bash pnpm db:migrate add_user_phone_field \`\`\` ⚠️ **実行前に:** 1. スキーマ変更をもう一度確認 2. 影響を受けるテーブルで開発が行われていないことを確認 3. 本番環境に適用する場合はデータベースをバックアップ 続行しますか? (yes/no)
ユーザーが確認した場合:
pnpm db:migrate add_user_phone_field
期待される出力:
- •
prisma/migrations/にマイグレーションファイルが作成される - •SQLファイルが生成される
ステップ5: 生成されたSQLのレビュー
生成されたマイグレーションSQLを読み取り、表示:
# 最新のマイグレーションを見つける
LATEST_MIGRATION=$(ls -t prisma/migrations/ | head -1)
# SQLを表示
cat "prisma/migrations/${LATEST_MIGRATION}/migration.sql"
レビューチェックリスト:
- •✅ SQL構文が正しい
- •✅ データマイグレーションなしの DROP TABLE がない
- •✅ ALTER TABLE 変更が安全
- •✅ 外部キーに対してインデックスが作成されている
- •✅ デフォルト値が適切
ユーザーにレビューを依頼:
## 生成されたマイグレーションSQL \`\`\`sql [ここにSQLの内容を表示] \`\`\` このSQLは正しく見えますか? (yes/no)
ステップ6: Prismaクライアントの生成
マイグレーション作成後、TypeScript型を生成:
pnpm db:generate
これにより:
- •
@prisma/client型が更新される - •TypeScript定義が生成される
- •
node_modules/.prisma/client/が更新される
生成を確認:
# Prismaクライアントが更新されたかチェック ls -la node_modules/.prisma/client/index.d.ts
ステップ7: アプリケーションコードの更新
更新が必要なアプリケーションコードをチェック:
- •
Prisma型をインポートしているファイルを検索:
bashgrep -r "from '@prisma/client'" src/ --files-with-matches
- •
Prisma select shapesを持つファイルを検索:
bashgrep -r "select.*{" src/application/domain/**/data/type.ts --files-with-matches - •
更新が必要な可能性のあるファイルを表示:
## 更新が必要な可能性のあるファイル 以下のファイルはPrisma型をインポートしており、更新が必要な可能性があります: - src/application/domain/account/user/data/type.ts - src/application/domain/account/membership/service.ts - src/application/domain/experience/opportunity/data/repository.ts これらのファイルで以下を確認してください: - select shapesの新しいフィールド - 更新されたenum値 - 変更された型定義
ステップ8: TypeScriptコンパイルの確認
型エラーをチェックするためにTypeScriptをコンパイル:
pnpm build
エラーがある場合:
- •コンパイルエラーを表示
- •エラーメッセージに基づいて修正を提案
- •一般的な問題:
- •型のプロパティの欠落
- •enum値の変更
- •型の不一致
成功した場合:
✅ TypeScriptコンパイル成功 ✅ 型エラーは検出されませんでした
ステップ9: テストの実行
重要: スキーマ変更後は常にテストを実行してください。
pnpm test --runInBand
テストが失敗した場合:
- •失敗したテストを表示
- •以下をチェックすることを提案:
- •テストフィクスチャ(データの更新が必要な可能性)
- •ファクトリ定義(Prisma Fabbrica)
- •シードデータスクリプト
テストが成功した場合:
✅ 全てのテストが成功しました ✅ データベーススキーマ変更は既存コードと互換性があります
ステップ10: ドキュメントの更新
関連ドキュメントの更新をリマインド:
## ドキュメントの更新 以下の更新を検討してください: - [ ] `docs/database/schema.md` - 新しいテーブル/フィールドをドキュメント化 - [ ] `docs/handbook/FEATURES.md` - 機能ドキュメントを更新 - [ ] GraphQLスキーマコメント - 新しいフィールドの説明を追加 - [ ] `CHANGELOG.md` - マイグレーションをchangelogに追加 Prismaスキーマのコメントは生成された型に自動的に含まれます。
マイグレーションのベストプラクティス
マイグレーション作成前
- •✅ スキーマ変更を慎重にレビュー
- •✅ 破壊的変更をチェック
- •✅ 命名規則に従っていることを確認
- •✅ 適切なインデックスを追加
- •✅ データマイグレーションの必要性を検討
マイグレーション作成後
- •✅ 生成されたSQLをレビュー
- •✅
pnpm db:generateを実行 - •✅ TypeScriptコンパイルエラーを修正
- •✅
pnpm test --runInBandでテストを実行 - •✅ 必要に応じてアプリケーションコードを更新
- •✅ ドキュメントを更新
本番環境マイグレーション
- •✅ ステージング環境で最初にマイグレーションをテスト
- •✅ 本番データベースをバックアップ
- •✅ 必要に応じてダウンタイムを計画
- •✅ ロールバック計画を用意
- •✅ デプロイ後アプリケーションを監視
一般的なマイグレーションパターン
新しいテーブルの追加
model t_products {
id String @id @default(cuid())
name String
price Int
communityId String
community t_communities @relation(fields: [communityId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([communityId])
@@map("t_products")
}
マイグレーション名: add_products_table
カラムの追加
model t_users {
// ... 既存のフィールド
phoneNumber String? // 新しいフィールド
}
マイグレーション名: add_user_phone_number_field
Enumの更新
enum PublishStatus {
DRAFT
PUBLISHED
ARCHIVED
SCHEDULED // 新しい値
}
マイグレーション名: update_publish_status_enum_add_scheduled
インデックスの追加
model t_opportunities {
// ... 既存のフィールド
@@index([communityId, publishStatus]) // 新しい複合インデックス
}
マイグレーション名: add_opportunity_community_status_index
トラブルシューティング
マイグレーションが失敗
エラー: "Migration failed to apply"
解決策:
- •PostgreSQL接続をチェック:
pnpm container:up - •
.envのデータベース認証情報を確認 - •テーブル/カラムが既に存在していないかチェック
- •マイグレーションSQLの構文エラーをレビュー
型生成が失敗
エラー: "Prisma client generation failed"
解決策:
- •Prismaスキーマの構文をチェック:
pnpm prisma format - •全てのリレーションが有効であることを確認
- •循環依存をチェック
- •参照される全てのモデルが存在することを確認
マイグレーション後にテストが失敗
エラー: データベースエラーでテストが失敗
解決策:
- •新しいフィールドでテストフィクスチャを更新
- •テストデータベースを再シード:
pnpm db:seed-domain - •Prisma Fabブリカファクトリを更新
- •必須フィールドの欠落をチェック
参考資料
以下については @CLAUDE.md を参照してください:
- •データベースコマンド(
pnpm db:*) - •マイグレーションワークフロー
- •Prismaスキーマ規約
- •マイグレーション後のテスト