Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 36 additions & 4 deletions apps/core/server/db/migrate.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
/**
* Database Migration Runner
* Runs pending migrations against the database
* Note: Bun auto-loads .env files, no dotenv needed
*/

import "dotenv/config";
import { drizzle } from "drizzle-orm/postgres-js";
import { logger } from "../utils/logger";
import { migrate } from "drizzle-orm/postgres-js/migrator";
import postgres from "postgres";
import { fileURLToPath } from "node:url";
import { dirname, join } from "node:path";
import { logger } from "../utils/logger";

// Get absolute path to migrations folder
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const migrationsFolder = join(__dirname, "migrations");

// Validate environment
if (!process.env.DATABASE_URL) {
Expand All @@ -22,6 +29,23 @@ if (!process.env.DATABASE_URL) {
process.exit(1);
}

// Log migration info for debugging
logger.info(
{
migrationsFolder,
databaseUrl: (() => {
try {
const url = new URL(process.env.DATABASE_URL!);
url.password = "****";
return url.toString();
} catch {
return process.env.DATABASE_URL!.replace(/:[^:@]+@/, ":****@");
}
})(), // Hide password
},
"[Migrations] Starting migration process",
);

// Migration connection with NOTICE suppression
const migrationClient = postgres(process.env.DATABASE_URL, {
max: 1,
Expand All @@ -34,7 +58,7 @@ async function main() {
logger.info({}, "[Migrations] Running migrations...");

try {
await migrate(db, { migrationsFolder: "./server/db/migrations" });
await migrate(db, { migrationsFolder });
logger.info({}, "[Migrations] ✓ Migrations completed successfully");
} catch (error: any) {
// Check if it's a "relation already exists" error (PostgreSQL code 42P07)
Expand All @@ -49,7 +73,15 @@ async function main() {
logger.warn({}, "[Migrations] ⚠️ Some tables already exist - skipping");
logger.info({}, "[Migrations] ✓ Database schema is up to date");
} else {
logger.error({ err: error }, "[Migrations] ✗ Migration failed:");
logger.error(
{
err: error,
code: errorCode,
message: errorMessage,
migrationsFolder,
},
"[Migrations] ✗ Migration failed",
);
process.exit(1);
}
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resource Management: Potential Unclosed Database Connection

If an error occurs before migrationClient.end() is called (for example, if an exception is thrown before or during the migration process), the database connection may remain open. To ensure proper resource cleanup, consider using a finally block to always close the connection, regardless of whether an error occurs:

try {
  await migrate(db, { migrationsFolder });
  logger.info({}, "[Migrations] ✓ Migrations completed successfully");
} catch (error: any) {
  // ... error handling ...
} finally {
  await migrationClient.end();
}

This guarantees that the connection is closed even if an error is thrown.

Expand Down
42 changes: 0 additions & 42 deletions apps/core/server/db/migrations/0030_fix_uuid_defaults.sql

This file was deleted.

194 changes: 0 additions & 194 deletions apps/core/server/db/migrations/0031_add_row_level_security.sql

This file was deleted.

Loading