Skip to content

Commit 7a19127

Browse files
committed
refactor: update migration handling and build configuration
- Changed the build command in vercel.json to use the standard build script. - Updated package.json to include a postbuild script for running database migrations. - Enhanced the run-gel-migrations script to improve environment detection and error handling during migration execution. - Added checks for database configuration and migration status, ensuring smoother deployment processes.
1 parent 56ddfc1 commit 7a19127

File tree

3 files changed

+150
-23
lines changed

3 files changed

+150
-23
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"scripts": {
77
"dev": "next dev",
88
"build": "next build",
9-
"build:vercel": "node ./scripts/vercel-build.mjs",
9+
"postbuild": "node ./scripts/run-gel-migrations.mjs || echo 'Migrations skipped'",
1010
"start": "next start",
1111
"lint": "next lint",
1212
"lint:fix": "next lint --fix",

scripts/run-gel-migrations.mjs

Lines changed: 148 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,53 +14,180 @@ try {
1414
const __filename = fileURLToPath(import.meta.url)
1515
const __dirname = path.dirname(__filename)
1616

17-
// Load .env.local if present
18-
const envPath = path.join(process.cwd(), '.env.local')
19-
if (fs.existsSync(envPath)) {
20-
dotenv.config({ path: envPath })
17+
// Check if we're in Vercel environment
18+
const isVercel = process.env.VERCEL === '1';
19+
const isProduction = process.env.VERCEL_ENV === 'production';
20+
21+
console.log(`Environment: ${isVercel ? 'Vercel' : 'Local'}`);
22+
console.log(`Deployment: ${isProduction ? 'Production' : 'Preview'}`);
23+
24+
// Load .env.local if present (only in local development)
25+
if (!isVercel) {
26+
const envPath = path.join(process.cwd(), '.env.local')
27+
if (fs.existsSync(envPath)) {
28+
dotenv.config({ path: envPath })
29+
}
2130
}
2231

23-
// Execute SQL files in order when a GEL_DATABASE_URL is available
32+
// Check for database configuration
33+
const edgedbInstance = process.env.EDGEDB_INSTANCE;
34+
const edgedbSecretKey = process.env.EDGEDB_SECRET_KEY;
35+
const gelDatabaseUrl = process.env.GEL_DATABASE_URL;
36+
37+
console.log('Database configuration:');
38+
console.log(`- EdgeDB: ${edgedbInstance && edgedbSecretKey ? '✅ Configured' : '❌ Not configured'}`);
39+
console.log(`- GelDB/PostgreSQL: ${gelDatabaseUrl ? '✅ Configured' : '❌ Not configured'}`);
40+
41+
// Execute SQL files in order when a database connection is available
2442
const migrationsDir = path.join(__dirname, 'gel', 'migrations')
43+
44+
if (!fs.existsSync(migrationsDir)) {
45+
console.log('Migrations directory not found. Skipping migrations.');
46+
process.exit(0);
47+
}
48+
2549
const files = fs.readdirSync(migrationsDir).filter(f => f.endsWith('.sql')).sort()
2650
console.log('Found migrations:', files)
2751

28-
const connectionString = process.env.GEL_DATABASE_URL || process.env.DATABASE_URL
29-
if (!connectionString) {
30-
console.error('No GEL_DATABASE_URL provided. Skipping execution.')
31-
process.exit(0)
52+
if (files.length === 0) {
53+
console.log('No migration files found. Skipping migrations.');
54+
process.exit(0);
55+
}
56+
57+
// Determine connection string
58+
let connectionString = null;
59+
60+
if (edgedbInstance && edgedbSecretKey) {
61+
// Use EdgeDB connection string
62+
connectionString = `edgedb://${edgedbInstance}:${edgedbSecretKey}@edgedb.cloud`;
63+
console.log('Using EdgeDB connection');
64+
} else if (gelDatabaseUrl) {
65+
// Use GelDB/PostgreSQL connection string
66+
connectionString = gelDatabaseUrl;
67+
console.log('Using GelDB/PostgreSQL connection');
68+
} else {
69+
console.log('No database configuration found. Skipping migrations.');
70+
process.exit(0);
3271
}
3372

3473
if (!Client) {
35-
console.error('No pg client available. Install pg to execute migrations.')
36-
process.exit(1)
74+
console.error('No pg client available. Install pg to execute migrations.');
75+
if (isVercel) {
76+
console.log('Continuing build without migrations (Vercel environment)');
77+
process.exit(0);
78+
} else {
79+
process.exit(1);
80+
}
3781
}
3882

39-
const client = new Client({ connectionString })
40-
await client.connect()
83+
const client = new Client({
84+
connectionString,
85+
connectionTimeoutMillis: 10000, // 10 seconds
86+
query_timeout: 30000, // 30 seconds
87+
})
88+
4189
try {
42-
for (const file of files) {
90+
await client.connect()
91+
console.log('Connected to database successfully')
92+
} catch (connectError) {
93+
console.error('Failed to connect to database:', connectError.message)
94+
if (isVercel) {
95+
console.log('Continuing build without migrations (database connection failed)')
96+
process.exit(0)
97+
} else {
98+
process.exit(1)
99+
}
100+
}
101+
102+
try {
103+
// Create migrations tracking table if it doesn't exist
104+
await client.query(`
105+
CREATE TABLE IF NOT EXISTS schema_migrations (
106+
id SERIAL PRIMARY KEY,
107+
version VARCHAR(255) UNIQUE NOT NULL,
108+
applied_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
109+
)
110+
`)
111+
console.log('Migrations tracking table ready')
112+
113+
// Get already applied migrations
114+
let appliedMigrations = []
115+
try {
116+
const result = await client.query('SELECT version FROM schema_migrations ORDER BY version')
117+
appliedMigrations = result.rows.map(row => row.version)
118+
console.log('Already applied migrations:', appliedMigrations)
119+
} catch (error) {
120+
console.log('No migrations table found, assuming no migrations applied')
121+
}
122+
123+
// Filter out already applied migrations
124+
const pendingMigrations = files.filter(file => !appliedMigrations.includes(file))
125+
console.log('Pending migrations:', pendingMigrations)
126+
127+
if (pendingMigrations.length === 0) {
128+
console.log('All migrations already applied')
129+
await client.end()
130+
process.exit(0)
131+
}
132+
133+
// Apply each pending migration
134+
for (const file of pendingMigrations) {
43135
const full = path.join(migrationsDir, file)
44136
const sql = fs.readFileSync(full, 'utf8')
45137
console.log(`Applying ${file}...`)
138+
46139
try {
47140
await client.query('BEGIN')
48141
await client.query(sql)
142+
143+
// Record migration as applied
144+
await client.query('INSERT INTO schema_migrations (version) VALUES ($1)', [file])
145+
49146
await client.query('COMMIT')
147+
console.log(`✅ Successfully applied ${file}`)
50148
} catch (e) {
51149
await client.query('ROLLBACK')
52150
const msg = String(e?.message || e)
53-
if (/already exists|duplicate_object/i.test(msg)) {
54-
console.warn(`Skipping ${file}: objects already exist`)
151+
152+
if (/already exists|duplicate_object|relation.*already exists/i.test(msg)) {
153+
console.warn(`⚠️ Skipping ${file}: objects already exist`)
154+
155+
// Still record it as applied since the objects exist
156+
try {
157+
await client.query('BEGIN')
158+
await client.query('INSERT INTO schema_migrations (version) VALUES ($1) ON CONFLICT (version) DO NOTHING', [file])
159+
await client.query('COMMIT')
160+
} catch (recordError) {
161+
await client.query('ROLLBACK')
162+
console.warn(`Could not record ${file} as applied:`, recordError.message)
163+
}
164+
continue
165+
}
166+
167+
console.error(`❌ Failed to apply ${file}:`, msg)
168+
if (isVercel) {
169+
console.log('Continuing with other migrations...')
55170
continue
171+
} else {
172+
throw e
56173
}
57-
throw e
58174
}
59175
}
60-
console.log('Migrations applied successfully')
176+
177+
console.log('✅ Migrations completed successfully')
61178
} catch (err) {
62-
console.error('Migration failed:', err)
63-
process.exit(1)
179+
console.error('❌ Migration process failed:', err.message)
180+
if (isVercel) {
181+
console.log('Continuing build despite migration failure (Vercel environment)')
182+
console.log('💡 Run migrations manually after deployment if needed')
183+
} else {
184+
process.exit(1)
185+
}
64186
} finally {
65-
await client.end()
187+
try {
188+
await client.end()
189+
console.log('Database connection closed')
190+
} catch (closeError) {
191+
console.warn('Error closing database connection:', closeError.message)
192+
}
66193
}

vercel.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"env": {
1010
"NODE_ENV": "production"
1111
},
12-
"buildCommand": "npm run build:vercel",
12+
"buildCommand": "npm run build",
1313
"build": {
1414
"env": {
1515
"NEXT_TELEMETRY_DISABLED": "1"

0 commit comments

Comments
 (0)