Skip to content

Commit 0a591fb

Browse files
committed
test(testcontainers): strip run foreign keys after schema push
Production drops the foreign keys on and referencing the run tables, but the test harness builds via prisma db push, which recreates them from the schema relations. Drop them after the push so test databases match production and a run can live in either run table.
1 parent 1e60662 commit 0a591fb

1 file changed

Lines changed: 42 additions & 0 deletions

File tree

  • internal-packages/testcontainers/src

internal-packages/testcontainers/src/utils.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { createClient } from "@clickhouse/client";
22
import { PostgreSqlContainer, StartedPostgreSqlContainer } from "@testcontainers/postgresql";
33
import { RedisContainer, StartedRedisContainer } from "@testcontainers/redis";
44
import { tryCatch } from "@trigger.dev/core";
5+
import { PrismaClient } from "@trigger.dev/database";
56
import Redis from "ioredis";
67
import path from "path";
78
import { isDebug } from "std-env";
@@ -48,9 +49,50 @@ export async function pushDatabaseSchema(databaseUrl: string) {
4849
}
4950
);
5051

52+
await dropRunForeignKeys(databaseUrl);
53+
5154
return result;
5255
}
5356

57+
/**
58+
* Production drops every foreign key that sits on, or points at, the run tables (`TaskRun` and
59+
* `task_run_v2`) — a run's id is just a scalar that may live in either physical table, so the FKs
60+
* can't be enforced. `prisma db push` doesn't know that: it recreates a constraint for every
61+
* relation still declared in schema.prisma, so the template DB ends up with run FKs production
62+
* doesn't have. That makes tests diverge — e.g. inserting a child row (a `TaskRunExecutionSnapshot`
63+
* whose `runId` is a `task_run_v2` id) trips a `..._runId_fkey -> TaskRun` constraint that doesn't
64+
* exist in prod. So after the push we strip those FKs to match production exactly.
65+
*
66+
* This is done dynamically (rather than naming each constraint) so any relation added to the schema
67+
* later has its test-only run FK stripped automatically. It only removes FK constraints, so it
68+
* cannot corrupt valid data — it makes the template DB strictly more faithful to production.
69+
*/
70+
async function dropRunForeignKeys(databaseUrl: string) {
71+
const prisma = new PrismaClient({
72+
datasources: { db: { url: databaseUrl } },
73+
});
74+
75+
try {
76+
await prisma.$executeRawUnsafe(`
77+
DO $$
78+
DECLARE r record;
79+
BEGIN
80+
FOR r IN
81+
SELECT conrelid::regclass::text AS tbl, conname
82+
FROM pg_constraint
83+
WHERE contype = 'f'
84+
AND (confrelid IN ('"TaskRun"'::regclass, 'task_run_v2'::regclass)
85+
OR conrelid IN ('"TaskRun"'::regclass, 'task_run_v2'::regclass))
86+
LOOP
87+
EXECUTE format('ALTER TABLE %s DROP CONSTRAINT %I', r.tbl, r.conname);
88+
END LOOP;
89+
END $$;
90+
`);
91+
} finally {
92+
await prisma.$disconnect();
93+
}
94+
}
95+
5496
/**
5597
* Caps each container's CPU/memory to approximate the 2-core CI runner locally (for timing + flake
5698
* reproduction). Set TESTCONTAINERS_CPU (cores per container, e.g. "2") and/or

0 commit comments

Comments
 (0)