From 367b0b2357e538d071fbb33a1129ee01eb0a9357 Mon Sep 17 00:00:00 2001 From: Djalim Simaila Date: Sun, 26 Apr 2026 13:22:45 +0200 Subject: [PATCH] fix(ci): fix postgres TCP setup and truncateAll superuser error - Use apt-get install + configure listen_addresses + md5 auth in pg_hba so psql can connect via 127.0.0.1 (not just Unix socket) - Use pg_ctlcluster restart after config changes + wait for pg_isready - Replace session_replication_role (requires superuser) with a single TRUNCATE ... CASCADE which handles FK deps without elevated privileges - All 3 integration tests now pass in CI (act + Gitea Actions) Co-Authored-By: Claude Sonnet 4.6 --- .gitea/workflows/test.yml | 21 ++++++------ tests/helpers/db_integration.ts | 29 ++++------------- tests/integration/users_test.ts | 58 +++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 34 deletions(-) create mode 100644 tests/integration/users_test.ts diff --git a/.gitea/workflows/test.yml b/.gitea/workflows/test.yml index 1a9c62b..6b3b830 100644 --- a/.gitea/workflows/test.yml +++ b/.gitea/workflows/test.yml @@ -44,26 +44,25 @@ jobs: run: | sudo apt-get update -qq && sudo apt-get install -y -qq postgresql > /dev/null PG_VER=$(ls /etc/postgresql/) - sudo pg_ctlcluster $PG_VER main start + sudo sed -i "s/^#*listen_addresses\s*=.*/listen_addresses = '127.0.0.1'/" /etc/postgresql/$PG_VER/main/postgresql.conf + echo "host all all 127.0.0.1/32 md5" | sudo tee -a /etc/postgresql/$PG_VER/main/pg_hba.conf + sudo pg_ctlcluster $PG_VER main restart + until sudo -u postgres pg_isready -h 127.0.0.1; do sleep 1; done sudo -u postgres psql -c "CREATE USER test WITH PASSWORD 'test';" sudo -u postgres psql -c "CREATE DATABASE polympr_test OWNER test;" sudo -u postgres psql -d polympr_test -c "GRANT ALL ON SCHEMA public TO test;" + - name: Apply migrations + run: | + sed 's/--> statement-breakpoint/;/g' databases/migrations/0000_square_jetstream.sql | \ + PGPASSWORD=test psql -h 127.0.0.1 -U test -d polympr_test + - name: Install dependencies run: npm install --ignore-scripts && deno install - - name: Apply migrations - env: - POSTGRES_HOST: localhost - POSTGRES_PORT: 5432 - POSTGRES_USER: test - POSTGRES_PASS: test - POSTGRES_DB: polympr_test - run: node_modules/.bin/drizzle-kit migrate - - name: Run integration tests env: - POSTGRES_HOST: localhost + POSTGRES_HOST: 127.0.0.1 POSTGRES_PORT: 5432 POSTGRES_USER: test POSTGRES_PASS: test diff --git a/tests/helpers/db_integration.ts b/tests/helpers/db_integration.ts index b74cd36..ee7fe04 100644 --- a/tests/helpers/db_integration.ts +++ b/tests/helpers/db_integration.ts @@ -18,29 +18,15 @@ function createTestPool(): pg.Pool { user: Deno.env.get("POSTGRES_USER") ?? "test", password: Deno.env.get("POSTGRES_PASS") ?? "test", database: Deno.env.get("POSTGRES_DB") ?? "polympr_test", + ssl: false, }); } export const testPool = createTestPool(); export const testDb = drizzle(testPool, { schema }); -// Ordre de truncate respectant les FK (enfants avant parents) -const TRUNCATE_ORDER = [ - "mobility", - "ajustements", - "notes", - "ue_modules", - "enseignements", - "role_permissions", - "students", - "ue_modules", - "users", - "modules", - "ues", - "promotions", - "permissions", - "roles", -] as const; +const ALL_TABLES = + '"mobility","ajustements","notes","ue_modules","enseignements","role_permissions","students","users","modules","ues","promotions","permissions","roles"'; /** * Vide toutes les tables dans le bon ordre. @@ -49,12 +35,9 @@ const TRUNCATE_ORDER = [ export async function truncateAll(): Promise { const client = await testPool.connect(); try { - // Désactiver les FK temporairement pour simplifier - await client.query("SET session_replication_role = replica"); - for (const table of TRUNCATE_ORDER) { - await client.query(`TRUNCATE TABLE "${table}" RESTART IDENTITY CASCADE`); - } - await client.query("SET session_replication_role = DEFAULT"); + await client.query( + `TRUNCATE TABLE ${ALL_TABLES} RESTART IDENTITY CASCADE`, + ); } finally { client.release(); } diff --git a/tests/integration/users_test.ts b/tests/integration/users_test.ts new file mode 100644 index 0000000..e0d5ae9 --- /dev/null +++ b/tests/integration/users_test.ts @@ -0,0 +1,58 @@ +import { assertEquals, assertExists } from "@std/assert"; +import { + closeTestPool, + seedRoles, + seedUsers, + testDb, + truncateAll, +} from "../helpers/db_integration.ts"; +import { users } from "$root/databases/schema.ts"; + +Deno.test({ + name: "integration: GET /users - DB round trip", + async fn() { + await truncateAll(); + + const [role] = await seedRoles([{ nom: "employee" }]); + await seedUsers([ + { id: "dupont.jean", nom: "Dupont", prenom: "Jean", idRole: role.id }, + { id: "martin.alice", nom: "Martin", prenom: "Alice", idRole: role.id }, + ]); + + const rows = await testDb.select().from(users); + assertEquals(rows.length, 2); + assertExists(rows.find((u) => u.id === "dupont.jean")); + }, + sanitizeResources: false, + sanitizeOps: false, +}); + +Deno.test({ + name: "integration: INSERT user and retrieve by id", + async fn() { + await truncateAll(); + + const [role] = await seedRoles([{ nom: "admin" }]); + const [created] = await testDb.insert(users).values({ + id: "durand.claire", + nom: "Durand", + prenom: "Claire", + idRole: role.id, + }).returning(); + + assertExists(created); + assertEquals(created.id, "durand.claire"); + assertEquals(created.nom, "Durand"); + }, + sanitizeResources: false, + sanitizeOps: false, +}); + +Deno.test({ + name: "integration: cleanup - close pool", + async fn() { + await closeTestPool(); + }, + sanitizeResources: false, + sanitizeOps: false, +});