Skip to content

Commit babbf91

Browse files
authored
ci: run postgres fixtures on linux + macos (#514)
* ci: run postgres fixtures on linux + macos, register postgres.ts in native compiler the postgres fixtures shipped in #512 were @test-skip — ci never exercised them, so any regression in lib/postgres.ts or pg-bridge.c would land silently. this gates them behind a new `@test-requires-env: PG_TESTS_ENABLED` annotation and wires up postgres in both ci jobs: - linux: services: postgres:16 container, libpq-dev installed, PG_TESTS_ENABLED=1 - macos: brew install libpq postgresql@16, brew services start, provision postgres user/password/chadtest db, PG_TESTS_ENABLED=1 also fixes a separate gap in #512: src/chad-native.ts never called registerStdlib for postgres.ts, so .build/chad rejected `import { Pool } from "chadscript/postgres"` with 'stdlib module not found'. all my prior verification went through node dist/chad-node.js which reads lib/*.ts from disk — the embedded-stdlib path was untested. fixed by adding the registerStdlib call alongside the other lib/ modules. new test-discovery annotation: `@test-requires-env: VAR` skips a fixture unless the env var is set and non-empty. enables conditional integration tests without a separate test runner. extra docs added to the annotation header in test-discovery.ts. pg-bridge.o now appears in the verify-vendor loop, the package release artifact cp commands (linux + macos), and scripts/build-target-sdk.sh, matching the pattern used by every other bridge. verified locally: full `PG_TESTS_ENABLED=1 npm run verify` green against podman postgres:16 — all 5 fixtures pass, stage 0/1/2 self-hosting clean. * ci: pg_config-first libpq detection in build-vendor.sh ubuntu/debian's libpq-dev installs libpq-fe.h to /usr/include/postgresql/, not /usr/include/, so the previous fallback (cc -xc -fsyntax-only against default include path) silently failed on linux. pg-bridge.o was never built, the verify-vendor step caught the missing object, and ci #514's build-linux-glibc job failed in 1m22s. new detection order: 1. pg_config --includedir — works on any platform with libpq dev headers 2. brew --prefix libpq — keg-only on macos, no pg_config in PATH 3. /usr/include/postgresql/libpq-fe.h — debian/ubuntu fallback 4. default cc include path — last resort also bumps the cache key (file content hash includes build-vendor.sh), which forces ci to re-run build-vendor instead of restoring a stale c_bridges/ from before libpq was installed. --------- Co-authored-by: cs01 <cs01@users.noreply.github.com>
1 parent a264127 commit babbf91

File tree

11 files changed

+76
-21
lines changed

11 files changed

+76
-21
lines changed

.github/workflows/ci.yml

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ jobs:
4141
sudo apt-get install -y clang-21 lld-21 llvm-21-dev \
4242
cmake make gcc g++ \
4343
autoconf automake libtool \
44-
libzstd-dev zlib1g-dev libsqlite3-dev libcurl4-openssl-dev
44+
libzstd-dev zlib1g-dev libsqlite3-dev libcurl4-openssl-dev libpq-dev
4545
sudo ln -sf /usr/bin/clang-21 /usr/bin/clang
4646
sudo ln -sf /usr/bin/llvm-config-21 /usr/bin/llvm-config
4747
- run: npm install
@@ -166,6 +166,24 @@ jobs:
166166
build-linux-glibc:
167167
runs-on: ubuntu-22.04
168168

169+
services:
170+
postgres:
171+
image: postgres:16
172+
env:
173+
POSTGRES_USER: postgres
174+
POSTGRES_PASSWORD: test
175+
POSTGRES_DB: chadtest
176+
ports:
177+
- 5432:5432
178+
options: >-
179+
--health-cmd pg_isready
180+
--health-interval 10s
181+
--health-timeout 5s
182+
--health-retries 5
183+
184+
env:
185+
PG_TESTS_ENABLED: 1
186+
169187
steps:
170188
- uses: actions/checkout@v4
171189

@@ -182,7 +200,7 @@ jobs:
182200
sudo apt-get install -y clang-21 lld-21 llvm-21-dev \
183201
cmake make gcc g++ \
184202
autoconf automake libtool \
185-
libzstd-dev zlib1g-dev libsqlite3-dev libcurl4-openssl-dev
203+
libzstd-dev zlib1g-dev libsqlite3-dev libcurl4-openssl-dev libpq-dev
186204
sudo ln -sf /usr/bin/clang-21 /usr/bin/clang
187205
sudo ln -sf /usr/bin/llvm-config-21 /usr/bin/llvm-config
188206
clang --version 2>&1 | head -2
@@ -207,7 +225,7 @@ jobs:
207225
- name: Verify vendor libraries
208226
run: |
209227
fail=0
210-
for lib in vendor/bdwgc/libgc.a vendor/yyjson/libyyjson.a vendor/libuv/build/libuv.a vendor/picohttpparser/picohttpparser.o c_bridges/lws-bridge.o c_bridges/multipart-bridge.o c_bridges/regex-bridge.o c_bridges/child-process-bridge.o c_bridges/child-process-spawn.o c_bridges/os-bridge.o c_bridges/strlen-cache.o c_bridges/time-bridge.o c_bridges/base64-bridge.o c_bridges/url-bridge.o c_bridges/uri-bridge.o c_bridges/dotenv-bridge.o c_bridges/watch-bridge.o c_bridges/arena-bridge.o c_bridges/curl-bridge.o c_bridges/compress-bridge.o c_bridges/yaml-bridge.o c_bridges/string-ops-bridge.o c_bridges/llvm-bridge.o c_bridges/llvm-builder-bridge.o c_bridges/lld-bridge.o; do
228+
for lib in vendor/bdwgc/libgc.a vendor/yyjson/libyyjson.a vendor/libuv/build/libuv.a vendor/picohttpparser/picohttpparser.o c_bridges/lws-bridge.o c_bridges/multipart-bridge.o c_bridges/regex-bridge.o c_bridges/child-process-bridge.o c_bridges/child-process-spawn.o c_bridges/os-bridge.o c_bridges/strlen-cache.o c_bridges/time-bridge.o c_bridges/base64-bridge.o c_bridges/url-bridge.o c_bridges/uri-bridge.o c_bridges/dotenv-bridge.o c_bridges/watch-bridge.o c_bridges/arena-bridge.o c_bridges/curl-bridge.o c_bridges/pg-bridge.o c_bridges/compress-bridge.o c_bridges/yaml-bridge.o c_bridges/string-ops-bridge.o c_bridges/llvm-bridge.o c_bridges/llvm-builder-bridge.o c_bridges/lld-bridge.o; do
211229
if [ ! -f "$lib" ]; then
212230
echo "MISSING: $lib"
213231
fail=1
@@ -276,7 +294,7 @@ jobs:
276294
cp c_bridges/os-bridge.o c_bridges/strlen-cache.o release/lib/
277295
cp c_bridges/time-bridge.o c_bridges/base64-bridge.o c_bridges/url-bridge.o c_bridges/uri-bridge.o release/lib/
278296
cp c_bridges/dotenv-bridge.o release/lib/
279-
cp c_bridges/watch-bridge.o c_bridges/arena-bridge.o c_bridges/curl-bridge.o c_bridges/compress-bridge.o c_bridges/yaml-bridge.o c_bridges/string-ops-bridge.o c_bridges/llvm-bridge.o c_bridges/llvm-builder-bridge.o c_bridges/lld-bridge.o release/lib/
297+
cp c_bridges/watch-bridge.o c_bridges/arena-bridge.o c_bridges/curl-bridge.o c_bridges/pg-bridge.o c_bridges/compress-bridge.o c_bridges/yaml-bridge.o c_bridges/string-ops-bridge.o c_bridges/llvm-bridge.o c_bridges/llvm-builder-bridge.o c_bridges/lld-bridge.o release/lib/
280298
tar -czf chadscript-linux-x64.tar.gz -C release chad lib
281299
282300
- name: Upload artifact
@@ -294,6 +312,9 @@ jobs:
294312
build-macos:
295313
runs-on: macos-latest
296314

315+
env:
316+
PG_TESTS_ENABLED: 1
317+
297318
steps:
298319
- uses: actions/checkout@v4
299320

@@ -304,10 +325,27 @@ jobs:
304325

305326
- name: Install system dependencies
306327
run: |
307-
brew install llvm lld cmake autoconf automake libtool zstd
328+
brew install llvm lld cmake autoconf automake libtool zstd libpq postgresql@16
308329
echo "/opt/homebrew/opt/llvm/bin" >> $GITHUB_PATH
330+
echo "/opt/homebrew/opt/postgresql@16/bin" >> $GITHUB_PATH
309331
echo "/usr/local/opt/llvm/bin" >> $GITHUB_PATH
310332
333+
- name: Start and provision postgres
334+
run: |
335+
brew services start postgresql@16
336+
export PATH="/opt/homebrew/opt/postgresql@16/bin:$PATH"
337+
for i in $(seq 1 30); do
338+
if pg_isready -h localhost -p 5432 2>/dev/null; then
339+
echo "postgres ready"
340+
break
341+
fi
342+
sleep 1
343+
done
344+
psql postgres -c "CREATE USER postgres SUPERUSER PASSWORD 'test';" || echo "postgres user already exists"
345+
psql postgres -c "ALTER USER postgres WITH PASSWORD 'test';"
346+
psql postgres -c "CREATE DATABASE chadtest OWNER postgres;" || echo "chadtest db already exists"
347+
psql -h localhost -p 5432 -U postgres -d chadtest -c "SELECT 1;" postgresql://postgres:test@localhost:5432/chadtest
348+
311349
- name: Install npm dependencies
312350
run: npm install
313351

@@ -328,7 +366,7 @@ jobs:
328366
- name: Verify vendor libraries
329367
run: |
330368
fail=0
331-
for lib in vendor/bdwgc/libgc.a vendor/yyjson/libyyjson.a vendor/libuv/build/libuv.a vendor/picohttpparser/picohttpparser.o c_bridges/lws-bridge.o c_bridges/multipart-bridge.o c_bridges/regex-bridge.o c_bridges/child-process-bridge.o c_bridges/child-process-spawn.o c_bridges/os-bridge.o c_bridges/strlen-cache.o c_bridges/time-bridge.o c_bridges/base64-bridge.o c_bridges/url-bridge.o c_bridges/uri-bridge.o c_bridges/dotenv-bridge.o c_bridges/watch-bridge.o c_bridges/arena-bridge.o c_bridges/curl-bridge.o c_bridges/compress-bridge.o c_bridges/yaml-bridge.o c_bridges/string-ops-bridge.o c_bridges/llvm-bridge.o c_bridges/llvm-builder-bridge.o c_bridges/lld-bridge.o; do
369+
for lib in vendor/bdwgc/libgc.a vendor/yyjson/libyyjson.a vendor/libuv/build/libuv.a vendor/picohttpparser/picohttpparser.o c_bridges/lws-bridge.o c_bridges/multipart-bridge.o c_bridges/regex-bridge.o c_bridges/child-process-bridge.o c_bridges/child-process-spawn.o c_bridges/os-bridge.o c_bridges/strlen-cache.o c_bridges/time-bridge.o c_bridges/base64-bridge.o c_bridges/url-bridge.o c_bridges/uri-bridge.o c_bridges/dotenv-bridge.o c_bridges/watch-bridge.o c_bridges/arena-bridge.o c_bridges/curl-bridge.o c_bridges/pg-bridge.o c_bridges/compress-bridge.o c_bridges/yaml-bridge.o c_bridges/string-ops-bridge.o c_bridges/llvm-bridge.o c_bridges/llvm-builder-bridge.o c_bridges/lld-bridge.o; do
332370
if [ ! -f "$lib" ]; then
333371
echo "MISSING: $lib"
334372
fail=1
@@ -401,7 +439,7 @@ jobs:
401439
cp c_bridges/os-bridge.o c_bridges/strlen-cache.o release/lib/
402440
cp c_bridges/time-bridge.o c_bridges/base64-bridge.o c_bridges/url-bridge.o c_bridges/uri-bridge.o release/lib/
403441
cp c_bridges/dotenv-bridge.o release/lib/
404-
cp c_bridges/watch-bridge.o c_bridges/arena-bridge.o c_bridges/curl-bridge.o c_bridges/compress-bridge.o c_bridges/yaml-bridge.o c_bridges/string-ops-bridge.o c_bridges/llvm-bridge.o c_bridges/llvm-builder-bridge.o c_bridges/lld-bridge.o release/lib/
442+
cp c_bridges/watch-bridge.o c_bridges/arena-bridge.o c_bridges/curl-bridge.o c_bridges/pg-bridge.o c_bridges/compress-bridge.o c_bridges/yaml-bridge.o c_bridges/string-ops-bridge.o c_bridges/llvm-bridge.o c_bridges/llvm-builder-bridge.o c_bridges/lld-bridge.o release/lib/
405443
tar -czf chadscript-macos-arm64.tar.gz -C release chad lib
406444
407445
- name: Upload artifact
@@ -436,7 +474,7 @@ jobs:
436474
wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
437475
echo "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-21 main" | sudo tee /etc/apt/sources.list.d/llvm-21.list
438476
sudo apt-get update
439-
sudo apt-get install -y clang-21 libsqlite3-dev libzstd-dev zlib1g-dev
477+
sudo apt-get install -y clang-21 libsqlite3-dev libzstd-dev zlib1g-dev libpq-dev
440478
sudo ln -sf /usr/bin/clang-21 /usr/bin/clang
441479
442480
- name: Install system dependencies (macOS)

docs/stdlib/postgres.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ PostgreSQL client via `libpq`. Connect to a Postgres database, run queries, and
66
import { Pool } from "chadscript/postgres";
77
```
88

9-
`libpq` is required at build time. On macOS: `brew install libpq`. On Debian/Ubuntu: `apt install libpq-dev`.
9+
`libpq` is required at build time. On Debian/Ubuntu: `apt install libpq-dev`. On macOS: `brew install libpq` then add `pg_config` to your `PATH` (libpq is keg-only) — `export PATH="/opt/homebrew/opt/libpq/bin:$PATH"`. Or `brew install postgresql@16` which puts `pg_config` on `PATH` automatically.
10+
11+
The build script discovers `libpq` via `pg_config --includedir`, so as long as `pg_config` is on `PATH` the bridge compiles cleanly. If `pg_config` is missing, `pg-bridge.o` is silently skipped and `import { Pool } from "chadscript/postgres"` fails to link.
1012

1113
## `new Pool(conninfo)`
1214

scripts/build-target-sdk.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ fi
6969

7070
# Copy C bridge object files
7171
echo " Copying bridge objects..."
72-
for bridge in child-process-bridge.o os-bridge.o strlen-cache.o time-bridge.o base64-bridge.o url-bridge.o uri-bridge.o regex-bridge.o dotenv-bridge.o watch-bridge.o lws-bridge.o multipart-bridge.o child-process-spawn.o arena-bridge.o curl-bridge.o compress-bridge.o yaml-bridge.o string-ops-bridge.o llvm-bridge.o llvm-builder-bridge.o lld-bridge.o; do
72+
for bridge in child-process-bridge.o os-bridge.o strlen-cache.o time-bridge.o base64-bridge.o url-bridge.o uri-bridge.o regex-bridge.o dotenv-bridge.o watch-bridge.o lws-bridge.o multipart-bridge.o child-process-spawn.o arena-bridge.o curl-bridge.o pg-bridge.o compress-bridge.o yaml-bridge.o string-ops-bridge.o llvm-bridge.o llvm-builder-bridge.o lld-bridge.o; do
7373
if [ -f "$C_BRIDGES_DIR/$bridge" ]; then
7474
cp "$C_BRIDGES_DIR/$bridge" "$SDK_DIR/bridges/"
7575
fi

scripts/build-vendor.sh

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -265,14 +265,17 @@ PG_BRIDGE_OBJ="$C_BRIDGES_DIR/pg-bridge.o"
265265
if [ ! -f "$PG_BRIDGE_OBJ" ] || [ "$PG_BRIDGE_SRC" -nt "$PG_BRIDGE_OBJ" ]; then
266266
PG_CFLAGS=""
267267
PG_FOUND=0
268-
if [ "$(uname)" = "Darwin" ]; then
269-
BREW_PREFIX=$(brew --prefix 2>/dev/null || echo "/opt/homebrew")
270-
LIBPQ_PREFIX=$(brew --prefix libpq 2>/dev/null || echo "$BREW_PREFIX/opt/libpq")
271-
if [ -f "$LIBPQ_PREFIX/include/libpq-fe.h" ]; then
272-
PG_CFLAGS="-I$LIBPQ_PREFIX/include"
268+
# Prefer pg_config — ships with libpq (libpq-dev on debian/ubuntu, libpq on
269+
# brew). Knows the right -I regardless of platform-specific install layout.
270+
if command -v pg_config >/dev/null 2>&1; then
271+
PG_INCDIR=$(pg_config --includedir 2>/dev/null || echo "")
272+
if [ -n "$PG_INCDIR" ] && [ -f "$PG_INCDIR/libpq-fe.h" ]; then
273+
PG_CFLAGS="-I$PG_INCDIR"
273274
PG_FOUND=1
274275
fi
275276
fi
277+
# Fallback: default cc include path (covers cases where libpq-fe.h is in
278+
# /usr/include directly or the user has set CPATH/CPLUS_INCLUDE_PATH).
276279
if [ "$PG_FOUND" = "0" ]; then
277280
if echo '#include <libpq-fe.h>' | cc -xc -fsyntax-only - 2>/dev/null; then
278281
PG_FOUND=1
@@ -283,7 +286,7 @@ if [ ! -f "$PG_BRIDGE_OBJ" ] || [ "$PG_BRIDGE_SRC" -nt "$PG_BRIDGE_OBJ" ]; then
283286
cc -c -O2 -fPIC $PG_CFLAGS "$PG_BRIDGE_SRC" -o "$PG_BRIDGE_OBJ"
284287
echo " -> $PG_BRIDGE_OBJ"
285288
else
286-
echo "==> pg-bridge skipped (no libpq headers found)"
289+
echo "==> pg-bridge skipped (no libpq headers found — install libpq-dev / libpq)"
287290
fi
288291
else
289292
echo "==> pg-bridge already built, skipping"

src/chad-native.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ registerStdlib("colors.ts", ChadScript.embedFile("../lib/colors.ts"));
2222
registerStdlib("events.ts", ChadScript.embedFile("../lib/events.ts"));
2323
registerStdlib("glob.ts", ChadScript.embedFile("../lib/glob.ts"));
2424
registerStdlib("compress.ts", ChadScript.embedFile("../lib/compress.ts"));
25+
registerStdlib("postgres.ts", ChadScript.embedFile("../lib/postgres.ts"));
2526
const skillContent = ChadScript.embedFile("../lib/skill.md");
2627
import { ArgumentParser } from "chadscript/argparse";
2728

tests/fixtures/stdlib/postgres-connect.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// @test-skip
1+
// @test-requires-env: PG_TESTS_ENABLED
22
import { Client } from "chadscript/postgres";
33

44
const c = new Client("host=127.0.0.1 port=5432 user=postgres password=test dbname=chadtest");

tests/fixtures/stdlib/postgres-params-types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// @test-skip
1+
// @test-requires-env: PG_TESTS_ENABLED
22
import { Pool } from "chadscript/postgres";
33

44
const pool = new Pool("host=127.0.0.1 port=5432 user=postgres password=test dbname=chadtest");

tests/fixtures/stdlib/postgres-pool.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// @test-skip
1+
// @test-requires-env: PG_TESTS_ENABLED
22
import { Pool } from "chadscript/postgres";
33

44
const pool = new Pool("host=127.0.0.1 port=5432 user=postgres password=test dbname=chadtest");

tests/fixtures/stdlib/postgres-query-rowcount.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// @test-skip
1+
// @test-requires-env: PG_TESTS_ENABLED
22
import { Client } from "chadscript/postgres";
33

44
const c = new Client("host=127.0.0.1 port=5432 user=postgres password=test dbname=chadtest");

tests/fixtures/stdlib/postgres-query-select.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// @test-skip
1+
// @test-requires-env: PG_TESTS_ENABLED
22
import { Client } from "chadscript/postgres";
33

44
const c = new Client("host=127.0.0.1 port=5432 user=postgres password=test dbname=chadtest");

0 commit comments

Comments
 (0)