Checkpoint: Correctif de production : le serveur exécute désormais les migrations Drizzle versionnées avant l'ouverture HTTP, ce qui initialise une base vide lors du premier déploiement. Test de régression ajouté. Validation complète réussie : 61 tests, TypeScript et build.
All checks were successful
Validation applicative / TypeScript, tests et build (push) Successful in 4m45s
All checks were successful
Validation applicative / TypeScript, tests et build (push) Successful in 4m45s
This commit is contained in:
@@ -7,6 +7,7 @@ import { registerOAuthRoutes } from "./oauth";
|
||||
import { registerStorageProxy } from "./storageProxy";
|
||||
import { appRouter } from "../routers";
|
||||
import { registerSalairesHttpRoutes } from "../salairesHttp";
|
||||
import { runDatabaseMigrations } from "../databaseMigrations";
|
||||
import { createContext } from "./context";
|
||||
import { serveStatic, setupVite } from "./vite";
|
||||
|
||||
@@ -30,6 +31,8 @@ async function findAvailablePort(startPort: number = 3000): Promise<number> {
|
||||
}
|
||||
|
||||
async function startServer() {
|
||||
// Une instance ne devient disponible qu'après la synchronisation du schéma.
|
||||
await runDatabaseMigrations();
|
||||
const app = express();
|
||||
const server = createServer(app);
|
||||
// Configure body parser with larger size limit for file uploads
|
||||
|
||||
24
server/databaseMigrations.ts
Normal file
24
server/databaseMigrations.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { migrate } from "drizzle-orm/mysql2/migrator";
|
||||
import { drizzle } from "drizzle-orm/mysql2";
|
||||
import { createPool } from "mysql2/promise";
|
||||
|
||||
/**
|
||||
* Synchronise la base avec les migrations versionnées avant d'exposer l'API.
|
||||
* Une base sans DATABASE_URL reste utilisable en développement statique, mais
|
||||
* un déploiement connecté échoue explicitement si la migration ne peut aboutir.
|
||||
*/
|
||||
export async function runDatabaseMigrations() {
|
||||
const databaseUrl = process.env.DATABASE_URL;
|
||||
if (!databaseUrl) {
|
||||
console.warn("[Database] DATABASE_URL absent : migrations ignorées.");
|
||||
return;
|
||||
}
|
||||
|
||||
const pool = createPool(databaseUrl);
|
||||
try {
|
||||
await migrate(drizzle(pool), { migrationsFolder: "./drizzle" });
|
||||
console.log("[Database] Migrations Drizzle synchronisées.");
|
||||
} finally {
|
||||
await pool.end();
|
||||
}
|
||||
}
|
||||
14
server/dockerMigrationBootstrap.test.ts
Normal file
14
server/dockerMigrationBootstrap.test.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { readFile } from "node:fs/promises";
|
||||
import { resolve } from "node:path";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
describe("bootstrap de migrations Docker", () => {
|
||||
it("exécute les migrations Drizzle avant de lancer le serveur", async () => {
|
||||
const server = await readFile(resolve(process.cwd(), "server/_core/index.ts"), "utf8");
|
||||
const migrationBootstrap = await readFile(resolve(process.cwd(), "server/databaseMigrations.ts"), "utf8");
|
||||
|
||||
expect(server).toContain("await runDatabaseMigrations()");
|
||||
expect(migrationBootstrap).toContain("migrate(");
|
||||
expect(migrationBootstrap).toContain("migrationsFolder: \"./drizzle\"");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user