ReviewOS

also looking at this

stacks/bun-query-builder

test(pg): make the Postgres-gated tests actually run in CI

#1077
Merged glennmichael123 wants to merge test/pg-gated-tests-in-ci into main
4 files +68 -35
packages/bun-query-builder/test/client.transaction-connection.test.tsmodified+3-11
Changes to packages/bun-query-builder/test/client.transaction-connection.test.ts
@@ -30,19 +30,11 @@ import { join, resolve } from 'node:path'
3030import process from 'node:process'
3131import { SQL } from 'bun'
3232import { describe, expect, it } from 'bun:test'
33import { PG_URL, probePostgres } from './pg'
34
35const pgAvailable = await probePostgres()
3336
34const PG_URL = `postgres://${process.env.USER}@localhost:5432/postgres`
3537
36let pgAvailable = false
37try {
38 const probe = new SQL(PG_URL)
39 await probe.unsafe('SELECT 1')
40 await probe.end()
41 pgAvailable = true
42}
43catch {
44 pgAvailable = false
45}
4638
4739describe.skipIf(!pgAvailable)('builder-local connection routing', () => {
4840 it('keeps transactional writes inside the transaction, and reads inside it current', () => {
packages/bun-query-builder/test/integration.postgres.test.tsmodified+6-12
Changes to packages/bun-query-builder/test/integration.postgres.test.ts
@@ -14,18 +14,10 @@ import { tmpdir } from 'node:os'
1414import { join, resolve } from 'node:path'
1515import { SQL } from 'bun'
1616import { describe, expect, it } from 'bun:test'
17import { PG_URL, probePostgres } from './pg'
18
19const pgAvailable = await probePostgres()
1720
18const PG_URL = `postgres://${process.env.USER}@localhost:5432/postgres`
19let pgAvailable = false
20try {
21 const probe = new SQL(PG_URL)
22 await probe.unsafe('SELECT 1')
23 await probe.end()
24 pgAvailable = true
25}
26catch {
27 pgAvailable = false
28}
2921
3022describe.skipIf(!pgAvailable)('Postgres integration (#1038)', () => {
3123 it('runs ORM CRUD + relations + raw builder against live Postgres', () => {
@@ -47,7 +39,9 @@ await raw.unsafe('CREATE TABLE _qb_users (id serial primary key, name text, age
4739await raw.unsafe('CREATE TABLE _qb_posts (id serial primary key, title text, pguser_id int)')
4840await raw.end()
4941
50setConfig({ dialect: 'postgres', database: { database: 'postgres', username: process.env.USER, host: 'localhost', port: 5432, password: '' } })
42// Configure from the same URL the gate probed, not a second hand-built copy of
43// it — the two drifting is what made this file skip in CI.
44setConfig({ dialect: 'postgres', database: { url: URL } })
5145resetConnection()
5246
5347// defineModel registers in the model registry, so relations resolve to the
packages/bun-query-builder/test/migrate-atomicity.test.tsmodified+4-12
Changes to packages/bun-query-builder/test/migrate-atomicity.test.ts
@@ -24,20 +24,12 @@ import { join, resolve } from 'node:path'
2424import process from 'node:process'
2525import { SQL } from 'bun'
2626import { describe, expect, it } from 'bun:test'
27import { PG_URL, probePostgres } from './pg'
28
29const pgAvailable = await probePostgres()
2730
2831const SRC = resolve(import.meta.dir, '../src/index.ts')
29const PG_URL = `postgres://${process.env.USER}@localhost:5432/postgres`
30
31let pgAvailable = false
32try {
33 const probe = new SQL(PG_URL)
34 await probe.unsafe('SELECT 1')
35 await probe.end()
36 pgAvailable = true
37}
38catch {
39 pgAvailable = false
40}
32
4133
4234/** A throwaway workspace with a migrations directory. */
4335function workspace(files: Record<string, string>): string {
packages/bun-query-builder/test/pg.tsadded+55-0
Changes to packages/bun-query-builder/test/pg.ts
@@ -0,0 +1,55 @@
1/**
2 * The Postgres a gated test should connect to, and whether it is reachable.
3 *
4 * Several tests can only be written against a real pooled driver — the
5 * transaction data leak (#1065), the migration lock (#1067), the ORM
6 * integration pass (#1038) — so they gate on a live server and skip without
7 * one. That gate was quietly wrong in CI.
8 *
9 * Each of those files built its own URL as
10 * `postgres://${process.env.USER}@localhost:5432/postgres`, which describes a
11 * developer machine: a peer-authenticated server owned by the current user,
12 * no password. CI is not that. It starts Postgres 17 as a service with
13 * `POSTGRES_USER=postgres`, `POSTGRES_PASSWORD=postgres`, `POSTGRES_DB=test_db`
14 * and exports `DATABASE_URL`. On a runner, `process.env.USER` is `runner`, so
15 * every probe failed with
16 *
17 * FATAL: password authentication failed for user "runner"
18 *
19 * the gate read that as "no Postgres here", and the tests SKIPPED. CI stayed
20 * green while the guards for the two most severe bugs in the release never
21 * ran at all — the worst shape for a test to be in, because the green tick
22 * says the opposite.
23 *
24 * So: prefer what the environment tells us, fall back to the local shape.
25 */
26
27import { SQL } from 'bun'
28import process from 'node:process'
29
30export const PG_URL: string
31 = process.env.DATABASE_URL
32 ?? process.env.POSTGRES_URL
33 ?? `postgres://${process.env.USER ?? 'postgres'}@localhost:5432/postgres`
34
35/**
36 * Whether that server actually answers.
37 *
38 * A function rather than an awaited constant so this module needs no top-level
39 * await: the rule against it exists to keep one out of the shipped bundle, and
40 * suppressing it in a helper to save three callers one line each is a poor
41 * trade. Callers await it at the top of their own `.test.ts`, where the rule
42 * does not apply. The URL above is the part that was wrong and the part worth
43 * sharing; this is three lines of probe.
44 */
45export async function probePostgres(): Promise<boolean> {
46 try {
47 const probe = new SQL(PG_URL)
48 await probe.unsafe('SELECT 1')
49 await probe.end()
50 return true
51 }
52 catch {
53 return false
54 }
55}