From f88c05c5f281f67b05d3d60f9aebc17509837574 Mon Sep 17 00:00:00 2001 From: Trung Anh Date: Thu, 2 Jul 2026 13:30:34 +0700 Subject: [PATCH] ci: add automatic database migration and seed check on npm run dev --- backend/package.json | 2 +- backend/scripts/db-check.js | 47 +++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 backend/scripts/db-check.js diff --git a/backend/package.json b/backend/package.json index dc411bd..49a2ca7 100644 --- a/backend/package.json +++ b/backend/package.json @@ -13,7 +13,7 @@ "prepare": "test -d node_modules/husky && husky install || echo \"husky is not installed\"", "lint": "eslint --fix --ext .js .", "lint:staged": "lint-staged", - "dev": "npx nodemon --exec npx babel-node src/core/bin/www.js", + "dev": "node scripts/db-check.js && npx nodemon --exec npx babel-node src/core/bin/www.js", "start": "npm run build && node ./dist/core/bin/www.js", "clean": "rimraf dist && mkdir dist", "build:babel": "babel ./src --out-dir dist --copy-files", diff --git a/backend/scripts/db-check.js b/backend/scripts/db-check.js new file mode 100644 index 0000000..6a9cbf3 --- /dev/null +++ b/backend/scripts/db-check.js @@ -0,0 +1,47 @@ +require('dotenv').config(); +const { execSync } = require('child_process'); +const fs = require('fs'); +const path = require('path'); + +async function checkAndMigrate() { + console.log('🔍 Checking database migration status...'); + + // Ensure Prisma client is generated + const clientPath = path.join(__dirname, '../node_modules/.prisma/client'); + if (!fs.existsSync(clientPath)) { + console.log('Prisma client not found. Generating...'); + try { + execSync('npx prisma generate --schema=prisma/schema', { stdio: 'inherit' }); + } catch (err) { + console.error('Failed to generate Prisma client:', err.message); + } + } + + try { + // Run migrate diff with exit-code flag. + // Exit code 0 = no diff (in sync), 2 = diff detected, 1 = error. + execSync('npx prisma migrate diff --exit-code --from-config-datasource --to-schema=prisma/schema', { stdio: 'ignore' }); + console.log('✅ Database schema is up to date. Skipping migrations and seeding.'); + } catch (error) { + // execSync throws an error if exit code is non-zero + if (error.status === 2) { + console.log('⚠️ Detected database schema differences. Applying migrations and seeding...'); + try { + // Apply/create migrations (interactive in dev, will prompt for name if there are unmigrated changes) + execSync('npx prisma migrate dev', { stdio: 'inherit' }); + + // Seed the database + console.log('🌱 Seeding database...'); + execSync('npx prisma db seed', { stdio: 'inherit' }); + } catch (err) { + console.error('❌ Failed to apply migrations or seed database:', err.message); + process.exit(1); + } + } else { + console.error('❌ Error checking database migration status:', error.message || error); + // We don't exit with 1 here to avoid blocking start if the DB is temporarily down or unreachable + } + } +} + +checkAndMigrate();