Lägesmedveten DB-URL: runtime endast DATABASE_URL, tester endast TEST_DATABASE_URL

This commit is contained in:
Sven (AAMOS AI)
2026-08-06 17:43:11 +07:00
parent fd5c828f96
commit e5a9d72197
6 changed files with 50 additions and 12 deletions
+5 -1
View File
@@ -24,7 +24,11 @@ export interface WorkerContext {
} }
export function createContext(): WorkerContext { export function createContext(): WorkerContext {
const { db, pool } = createDatabase(); const databaseUrl = process.env.DATABASE_URL;
if (!databaseUrl) {
throw new Error("Missing DATABASE_URL. Worker must connect explicitly to the app database.");
}
const { db, pool } = createDatabase(databaseUrl);
const aamos = createAamosClient(); const aamos = createAamosClient();
const apiBaseUrl = process.env.API_BASE_URL ?? "http://localhost:4000"; const apiBaseUrl = process.env.API_BASE_URL ?? "http://localhost:4000";
const secret = process.env.ENTITLEMENT_SIGNING_SECRET ?? "dev-only-change-me-three"; const secret = process.env.ENTITLEMENT_SIGNING_SECRET ?? "dev-only-change-me-three";
+14 -1
View File
@@ -17,7 +17,20 @@
använder `DATABASE_URL`. använder `DATABASE_URL`.
- Dedikerad testdatabas `cibello_test` skapad; `TEST_DATABASE_URL` lagd i - Dedikerad testdatabas `cibello_test` skapad; `TEST_DATABASE_URL` lagd i
`.env` och `.env.example`. `packages/database` test-skript migrerar `.env` och `.env.example`. `packages/database` test-skript migrerar
automatiskt testdatabasen före varje körning. automatiskt testdatabasen före varje körning (`tsx src/migrate.ts --test`).
- **Buggrättning (kritisk):** `createDatabase()` var lägesberoende men
föredrog ändå `TEST_DATABASE_URL` före `DATABASE_URL`. Åtgärdat så att
runtime **endast** ser `DATABASE_URL` och tester **endast** ser
`TEST_DATABASE_URL`.
- `apps/worker/src/context.ts`: skickar nu `DATABASE_URL` explicit till
`createDatabase()`, samma mönster som API:et.
- `packages/database/src/migrate.ts` och `src/seed/run.ts`: stöd för
`--test` / `MIGRATE_TARGET=test` / `SEED_TARGET=test`. Utan flagga
används endast `DATABASE_URL` deploy kan aldrig migrera/seed test-DB.
- Driftsreparation: staging migrerad explicit, worker omstartad med ny
build, expiry-notis skapad i staging-databasens `notifications`-tabell.
Kontroll av `cibello_test` visade 0 worker-skrivna rader i
`notifications` / `domain_events` / `inventory_items` / `households`.
- Bevis: radantal i staging-databasen före/efter full `pnpm test` är - Bevis: radantal i staging-databasen före/efter full `pnpm test` är
identiska (users=6, households=0, household_members=0, identiska (users=6, households=0, household_members=0,
product_analytics_events=0, user_consents=3). product_analytics_events=0, user_consents=3).
+1 -1
View File
@@ -11,7 +11,7 @@
}, },
"scripts": { "scripts": {
"typecheck": "tsc --noEmit", "typecheck": "tsc --noEmit",
"test": "tsx src/migrate.ts && vitest run --passWithNoTests", "test": "tsx src/migrate.ts --test && vitest run --passWithNoTests",
"db:generate": "drizzle-kit generate", "db:generate": "drizzle-kit generate",
"db:migrate": "tsx src/migrate.ts", "db:migrate": "tsx src/migrate.ts",
"db:seed": "tsx src/seed/run.ts" "db:seed": "tsx src/seed/run.ts"
+1 -7
View File
@@ -13,7 +13,7 @@ let sharedPool: pg.Pool | undefined;
*/ */
export function createDatabase(connectionString?: string) { export function createDatabase(connectionString?: string) {
const isTest = process.env.NODE_ENV === "test" || process.env.VITEST !== undefined; const isTest = process.env.NODE_ENV === "test" || process.env.VITEST !== undefined;
const url = connectionString ?? process.env.TEST_DATABASE_URL ?? process.env.DATABASE_URL; const url = connectionString ?? (isTest ? process.env.TEST_DATABASE_URL : process.env.DATABASE_URL);
if (!url) { if (!url) {
if (isTest) { if (isTest) {
@@ -24,12 +24,6 @@ export function createDatabase(connectionString?: string) {
throw new Error("Missing DATABASE_URL. Set it in your .env or environment before starting the app."); throw new Error("Missing DATABASE_URL. Set it in your .env or environment before starting the app.");
} }
if (isTest && !process.env.TEST_DATABASE_URL) {
throw new Error(
"Sätt TEST_DATABASE_URL till en dedikerad testdatabas. Tester får aldrig använda DATABASE_URL.",
);
}
const pool = new pg.Pool({ const pool = new pg.Pool({
connectionString: url, connectionString: url,
max: Number(process.env.DATABASE_POOL_MAX ?? 10), max: Number(process.env.DATABASE_POOL_MAX ?? 10),
+14 -1
View File
@@ -17,14 +17,27 @@ import { createDatabase } from "./client.js";
/** /**
* Kör alla väntande SQL-migrationer från infrastructure/migrations. * Kör alla väntande SQL-migrationer från infrastructure/migrations.
* Används i dev, CI och deploy (spec §63: migration + rollback + kontroll). * Används i dev, CI och deploy (spec §63: migration + rollback + kontroll).
*
* `--test` eller `MIGRATE_TARGET=test` migrerar TEST_DATABASE_URL.
* Utan flagga används ENDAST DATABASE_URL deploy kan aldrig röra testdatabasen.
*/ */
const isTestTarget = process.argv.includes("--test") || process.env.MIGRATE_TARGET === "test";
const connectionString = isTestTarget ? process.env.TEST_DATABASE_URL : process.env.DATABASE_URL;
if (!connectionString) {
if (isTestTarget) {
throw new Error("Sätt TEST_DATABASE_URL för test-migrationer.");
}
throw new Error("Sätt DATABASE_URL innan migration körs.");
}
const migrationsFolder = path.resolve( const migrationsFolder = path.resolve(
path.dirname(fileURLToPath(import.meta.url)), path.dirname(fileURLToPath(import.meta.url)),
"../../../infrastructure/migrations", "../../../infrastructure/migrations",
); );
async function main() { async function main() {
const { db, pool } = createDatabase(); const { db, pool } = createDatabase(connectionString);
console.log(`[migrate] Kör migrationer från ${migrationsFolder}`); console.log(`[migrate] Kör migrationer från ${migrationsFolder}`);
await migrate(db, { migrationsFolder }); await migrate(db, { migrationsFolder });
+15 -1
View File
@@ -27,11 +27,25 @@ import { SEED_SEASON_EVENTS } from "./data/seasonEvents.js";
/** /**
* Seed-körning. Idempotent: onConflictDoNothing/Update där det är säkert. * Seed-körning. Idempotent: onConflictDoNothing/Update där det är säkert.
* *
* `--test` eller `SEED_TARGET=test` kör mot TEST_DATABASE_URL.
* Utan flagga används ENDAST DATABASE_URL deploy seedar aldrig testdatabasen.
*/
const isTestTarget = process.argv.includes("--test") || process.env.SEED_TARGET === "test";
const connectionString = isTestTarget ? process.env.TEST_DATABASE_URL : process.env.DATABASE_URL;
if (!connectionString) {
if (isTestTarget) {
throw new Error("Sätt TEST_DATABASE_URL för test-seed.");
}
throw new Error("Sätt DATABASE_URL innan seed körs.");
}
/**
* Näring, allergener och kostnad för recepten beräknas HÄR, deterministiskt, * Näring, allergener och kostnad för recepten beräknas HÄR, deterministiskt,
* ur ingredienserna (spec §61.12) aldrig hårdkodade och aldrig från AI. * ur ingredienserna (spec §61.12) aldrig hårdkodade och aldrig från AI.
*/ */
async function main() { async function main() {
const { db, pool } = createDatabase(); const { db, pool } = createDatabase(connectionString);
console.log("[seed] Startar …"); console.log("[seed] Startar …");
// 1. Kanoniska ingredienser // 1. Kanoniska ingredienser