diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index cc0d105..aa535b0 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -50,9 +50,11 @@ jobs: - name: Deploy Node.js app run: | + # drizzle/ and src/db/migrate.mjs are needed inside the Docker + # build context so the image can apply pending migrations on startup. rsync -avz --delete \ -e "ssh -i ~/.ssh/deploy_key" \ - dist package*.json docker-compose.yml Dockerfile \ + dist drizzle src package*.json docker-compose.yml Dockerfile \ ${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }}:~/www/randify.pro/ - name: Restart app diff --git a/Dockerfile b/Dockerfile index 7d13e01..9038b0a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,7 +3,11 @@ WORKDIR /app COPY package*.json ./ RUN npm ci --omit=dev COPY dist ./dist +COPY drizzle ./drizzle +COPY src/db/migrate.mjs ./src/db/migrate.mjs EXPOSE 4321 ENV HOST=0.0.0.0 ENV PORT=4321 -CMD ["node", "./dist/server/entry.mjs"] +# Run pending migrations on startup, then start the app. +# Fails the container if migrations fail (so we don't serve with a stale schema). +CMD ["sh", "-c", "node ./src/db/migrate.mjs && node ./dist/server/entry.mjs"] diff --git a/eslint.config.mjs b/eslint.config.mjs index 6d30944..a3fc1b9 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -19,4 +19,12 @@ export default [ "@typescript-eslint/no-unused-vars": "off", }, }, + { + files: ["src/db/migrate.mjs"], + languageOptions: { + globals: { + ...globals.node, + }, + }, + }, ]; diff --git a/package.json b/package.json index 152e47f..8c26502 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "format": "prettier --write .", "format:check": "prettier --check .", "db:generate": "drizzle-kit generate", - "db:migrate": "tsx src/db/migrate.ts", + "db:migrate": "node src/db/migrate.mjs", "db:studio": "drizzle-kit studio" }, "dependencies": { diff --git a/src/db/migrate.ts b/src/db/migrate.mjs similarity index 57% rename from src/db/migrate.ts rename to src/db/migrate.mjs index e13c053..6f3e472 100644 --- a/src/db/migrate.ts +++ b/src/db/migrate.mjs @@ -1,21 +1,24 @@ import { drizzle } from 'drizzle-orm/node-postgres'; import { migrate } from 'drizzle-orm/node-postgres/migrator'; -import { Pool } from 'pg'; +import pg from 'pg'; -const pool = new Pool({ - connectionString: process.env.DATABASE_URL, -}); +const connectionString = process.env.DATABASE_URL; +if (!connectionString) { + console.error('Migration aborted: DATABASE_URL is not set'); + process.exit(1); +} +const pool = new pg.Pool({ connectionString }); const db = drizzle(pool); -async function runMigrations() { +try { console.log('Running migrations...'); await migrate(db, { migrationsFolder: './drizzle' }); console.log('Migrations completed.'); +} catch (err) { + console.error('Migration failed:', err); await pool.end(); + process.exit(1); } -runMigrations().catch((err) => { - console.error('Migration failed:', err); - process.exit(1); -}); +await pool.end();