Skip to content

Commit efd4387

Browse files
committed
refactor: improve test harness logging and error handling
Integrate bashlog framework throughout the test harness to provide better visibility and debuggability: - Add log_cmd function to capture command execution, stdout, and stderr to debug.log - Replace raw echo statements with structured log info/error/debug calls - Extract check_postgres_ready function to eliminate code duplication - Improve error handling with proper trap handling via on_exit function - Show debug logs only on test failures to reduce noise - Switch from 'set -e' to 'set -uo pipefail' for better error control
1 parent 0987406 commit efd4387

File tree

1 file changed

+95
-65
lines changed

1 file changed

+95
-65
lines changed

nix/checks.nix

Lines changed: 95 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
pgroonga = self'.packages."psql_15/exts/pgroonga";
1717
inherit (self.supabase) defaults;
1818
};
19+
bashlog = builtins.fetchurl {
20+
url = "https://raw.githubusercontent.com/Zordrak/bashlog/master/log.sh";
21+
sha256 = "1vrjcbzls0ba2qkg7ffddz2gxqn2rlj3wyvril2gz0mfi89y9vk9";
22+
};
1923
in
2024
{
2125
checks =
@@ -168,32 +172,74 @@
168172
];
169173
}
170174
''
171-
set -e
175+
source ${bashlog}
176+
set -uo pipefail
172177
173-
# Start HTTP mock server for http extension tests
178+
export BASHLOG_FILE=1
179+
export BASHLOG_FILE_PATH=debug.log
174180
# Use a build-specific directory for coordination
175181
BUILD_TMP=$(mktemp -d)
182+
183+
# Function to log command execution with stdout and stderr
184+
function log_cmd {
185+
local cmd_name="$1"
186+
shift
187+
log debug "Executing: $cmd_name $@"
188+
local exit_code=0
189+
echo "\$ $cmd_name $@" >> debug.log
190+
"$cmd_name" "$@" 2>&1 >> debug.log || exit_code=$?
191+
log debug "Exit code: $exit_code"
192+
return $exit_code
193+
}
194+
195+
function on_exit {
196+
local exit_code=$?
197+
kill $HTTP_MOCK_PID 2>/dev/null || true
198+
rm -rf "$BUILD_TMP"
199+
if [ $exit_code -ne 0 ]; then
200+
log error "An error occurred. Exit code: $exit_code"
201+
log error "Debug logs:"
202+
cat debug.log || log error "No debug.log file found"
203+
fi
204+
}
205+
trap on_exit EXIT
206+
trap "" DEBUG
207+
208+
function check_postgres_ready {
209+
for i in {1..60}; do
210+
if log_cmd pg_isready -h ${self.supabase.defaults.host} -p ${pgPort} -U supabase_admin -q; then
211+
log info "PostgreSQL is ready"
212+
break
213+
fi
214+
sleep 1
215+
if [ $i -eq 60 ]; then
216+
log error "PostgreSQL failed to start"
217+
exit 1
218+
fi
219+
done
220+
}
221+
222+
# Start HTTP mock server for http extension tests
176223
HTTP_MOCK_PORT_FILE="$BUILD_TMP/http-mock-port"
177224
178-
echo "Starting HTTP mock server (will find free port)..."
179-
HTTP_MOCK_PORT_FILE="$HTTP_MOCK_PORT_FILE" ${pkgs.python3}/bin/python3 ${./tests/http-mock-server.py} &
225+
log info "Starting HTTP mock server (will find free port)..."
226+
HTTP_MOCK_PORT_FILE="$HTTP_MOCK_PORT_FILE" log_cmd ${pkgs.python3}/bin/python3 ${./tests/http-mock-server.py} &
180227
HTTP_MOCK_PID=$!
181228
182229
# Clean up on exit
183-
trap "kill $HTTP_MOCK_PID 2>/dev/null || true; rm -rf '$BUILD_TMP'" EXIT
184230
185231
# Wait for server to start and write port file
186232
for i in {1..10}; do
187233
if [ -f "$HTTP_MOCK_PORT_FILE" ]; then
188234
HTTP_MOCK_PORT=$(cat "$HTTP_MOCK_PORT_FILE")
189-
echo "HTTP mock server started on port $HTTP_MOCK_PORT"
235+
log info "HTTP mock server started on port $HTTP_MOCK_PORT"
190236
break
191237
fi
192238
sleep 1
193239
done
194240
195241
if [ ! -f "$HTTP_MOCK_PORT_FILE" ]; then
196-
echo "Failed to start HTTP mock server"
242+
log error "Failed to start HTTP mock server"
197243
exit 1
198244
fi
199245
@@ -203,133 +249,117 @@
203249
#First we need to create a generic pg cluster for pgtap tests and run those
204250
export GRN_PLUGINS_DIR=${pkgs.supabase-groonga}/lib/groonga/plugins
205251
PGTAP_CLUSTER=$(mktemp -d)
206-
initdb --locale=C --username=supabase_admin -D "$PGTAP_CLUSTER"
252+
log info "Creating temporary PostgreSQL cluster at $PGTAP_CLUSTER"
253+
log_cmd initdb --locale=C --username=supabase_admin -D "$PGTAP_CLUSTER"
207254
substitute ${./tests/postgresql.conf.in} "$PGTAP_CLUSTER"/postgresql.conf \
208255
--subst-var-by PGSODIUM_GETKEY_SCRIPT "${getkey-script}/bin/pgsodium-getkey"
209256
echo "listen_addresses = '*'" >> "$PGTAP_CLUSTER"/postgresql.conf
210257
echo "port = ${pgPort}" >> "$PGTAP_CLUSTER"/postgresql.conf
211258
echo "host all all 127.0.0.1/32 trust" >> $PGTAP_CLUSTER/pg_hba.conf
212-
echo "Checking shared_preload_libraries setting:"
213-
grep -rn "shared_preload_libraries" "$PGTAP_CLUSTER"/postgresql.conf
259+
log info "Checking shared_preload_libraries setting:"
260+
log info $(grep -rn "shared_preload_libraries" "$PGTAP_CLUSTER"/postgresql.conf)
214261
# Remove timescaledb if running orioledb-17 check
215-
echo "I AM ${pgpkg.version}===================================================="
262+
log info "pgpkg.version is: ${pgpkg.version}"
216263
if [[ "${pgpkg.version}" == *"17"* ]]; then
217264
perl -pi -e 's/ timescaledb,//g' "$PGTAP_CLUSTER/postgresql.conf"
218265
fi
219266
#NOTE in the future we may also need to add the orioledb extension to the cluster when cluster is oriole
220-
echo "PGTAP_CLUSTER directory contents:"
221-
ls -la "$PGTAP_CLUSTER"
222267
223268
# Check if postgresql.conf exists
224269
if [ ! -f "$PGTAP_CLUSTER/postgresql.conf" ]; then
225-
echo "postgresql.conf is missing!"
270+
log error "postgresql.conf is missing!"
226271
exit 1
227272
fi
228273
229274
# PostgreSQL startup
230275
if [[ "$(uname)" == "Darwin" ]]; then
231-
pg_ctl -D "$PGTAP_CLUSTER" -l "$PGTAP_CLUSTER"/postgresql.log -o "-k "$PGTAP_CLUSTER" -p ${pgPort} -d 5" start 2>&1
276+
log_cmd pg_ctl -D "$PGTAP_CLUSTER" -l "$PGTAP_CLUSTER"/postgresql.log -o "-k "$PGTAP_CLUSTER" -p ${pgPort} -d 5" start
232277
else
233278
mkdir -p "$PGTAP_CLUSTER/sockets"
234-
pg_ctl -D "$PGTAP_CLUSTER" -l "$PGTAP_CLUSTER"/postgresql.log -o "-k $PGTAP_CLUSTER/sockets -p ${pgPort} -d 5" start 2>&1
279+
log_cmd pg_ctl -D "$PGTAP_CLUSTER" -l "$PGTAP_CLUSTER"/postgresql.log -o "-k $PGTAP_CLUSTER/sockets -p ${pgPort} -d 5" start
235280
fi || {
236-
echo "pg_ctl failed to start PostgreSQL"
237-
echo "Contents of postgresql.log:"
281+
log error "pg_ctl failed to start PostgreSQL"
282+
log error "Contents of postgresql.log:"
238283
cat "$PGTAP_CLUSTER"/postgresql.log
239284
exit 1
240285
}
241-
for i in {1..60}; do
242-
if pg_isready -h ${self.supabase.defaults.host} -p ${pgPort}; then
243-
echo "PostgreSQL is ready"
244-
break
245-
fi
246-
sleep 1
247-
if [ $i -eq 60 ]; then
248-
echo "PostgreSQL is not ready after 60 seconds"
249-
echo "PostgreSQL status:"
250-
pg_ctl -D "$PGTAP_CLUSTER" status
251-
echo "PostgreSQL log content:"
252-
cat "$PGTAP_CLUSTER"/postgresql.log
253-
exit 1
254-
fi
255-
done
256-
createdb -p ${pgPort} -h ${self.supabase.defaults.host} --username=supabase_admin testing
257-
if ! psql -p ${pgPort} -h ${self.supabase.defaults.host} --username=supabase_admin -d testing -v ON_ERROR_STOP=1 -Xf ${./tests/prime.sql}; then
258-
echo "Error executing SQL file. PostgreSQL log content:"
286+
287+
log info "Waiting for PostgreSQL to be ready..."
288+
check_postgres_ready
289+
290+
log info "Creating test database"
291+
log_cmd createdb -p ${pgPort} -h ${self.supabase.defaults.host} --username=supabase_admin testing
292+
293+
log info "Loading prime SQL file"
294+
if ! log_cmd psql -p ${pgPort} -h ${self.supabase.defaults.host} --username=supabase_admin -d testing -v ON_ERROR_STOP=1 -Xf ${./tests/prime.sql}; then
295+
log error "Error executing SQL file. PostgreSQL log content:"
259296
cat "$PGTAP_CLUSTER"/postgresql.log
260297
pg_ctl -D "$PGTAP_CLUSTER" stop
261298
exit 1
262299
fi
263300
264301
# Create a table to store test configuration
265-
psql -p ${pgPort} -h ${self.supabase.defaults.host} --username=supabase_admin -d testing -c "
302+
log info "Creating test_config table"
303+
log_cmd psql -p ${pgPort} -h ${self.supabase.defaults.host} --username=supabase_admin -d testing -c "
266304
CREATE TABLE IF NOT EXISTS test_config (key TEXT PRIMARY KEY, value TEXT);
267305
INSERT INTO test_config (key, value) VALUES ('http_mock_port', '$HTTP_MOCK_PORT')
268306
ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value;
269307
"
270308
SORTED_DIR=$(mktemp -d)
271309
for t in $(printf "%s\n" ${builtins.concatStringsSep " " sortedTestList}); do
272-
psql -p ${pgPort} -h ${self.supabase.defaults.host} --username=supabase_admin -d testing -f "${./tests/sql}/$t.sql" || true
310+
log info "Running pgtap test: $t.sql"
311+
#XXX enable ON_ERROR_STOP ?
312+
log_cmd psql -p ${pgPort} -h ${self.supabase.defaults.host} --username=supabase_admin -d testing -f "${./tests/sql}/$t.sql"
273313
done
274314
rm -rf "$SORTED_DIR"
275-
pg_ctl -D "$PGTAP_CLUSTER" stop
315+
log_cmd pg_ctl -D "$PGTAP_CLUSTER" stop
276316
rm -rf $PGTAP_CLUSTER
277317
278318
# End of pgtap tests
279319
# from here on out we are running pg_regress tests, we use a different cluster for this
280320
# which is start by the start-postgres-server-bin script
281321
# start-postgres-server-bin script closely matches our AMI setup, configurations and migrations
282322
323+
log info "Starting PostgreSQL server for pg_regress tests"
283324
unset GRN_PLUGINS_DIR
284-
${start-postgres-server-bin}/bin/start-postgres-server ${getVersionArg pgpkg} --daemonize
325+
log_cmd ${start-postgres-server-bin}/bin/start-postgres-server ${getVersionArg pgpkg} --daemonize
285326
286-
for i in {1..60}; do
287-
if pg_isready -h ${self.supabase.defaults.host} -p ${pgPort} -U supabase_admin -q; then
288-
echo "PostgreSQL is ready"
289-
break
290-
fi
291-
sleep 1
292-
if [ $i -eq 60 ]; then
293-
echo "PostgreSQL failed to start"
294-
exit 1
295-
fi
296-
done
327+
check_postgres_ready
297328
298-
if ! psql -p ${pgPort} -h ${self.supabase.defaults.host} --no-password --username=supabase_admin -d postgres -v ON_ERROR_STOP=1 -Xf ${./tests/prime.sql}; then
299-
echo "Error executing SQL file"
329+
log info "Loading prime SQL file"
330+
if ! log_cmd psql -p ${pgPort} -h ${self.supabase.defaults.host} --no-password --username=supabase_admin -d postgres -v ON_ERROR_STOP=1 -Xf ${./tests/prime.sql} 2>&1; then
331+
log error "Error executing SQL file"
300332
exit 1
301333
fi
302334
303335
# Create a table to store test configuration for pg_regress tests
304-
psql -p ${pgPort} -h ${self.supabase.defaults.host} --no-password --username=supabase_admin -d postgres -c "
336+
log info "Creating test_config table for pg_regress tests"
337+
log_cmd psql -p ${pgPort} -h ${self.supabase.defaults.host} --no-password --username=supabase_admin -d postgres -c "
305338
CREATE TABLE IF NOT EXISTS test_config (key TEXT PRIMARY KEY, value TEXT);
306339
INSERT INTO test_config (key, value) VALUES ('http_mock_port', '$HTTP_MOCK_PORT')
307340
ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value;
308341
"
309342
310343
mkdir -p $out/regression_output
311-
if ! pg_regress \
344+
log info "Running pg_regress tests"
345+
if ! log_cmd pg_regress \
312346
--use-existing \
313347
--dbname=postgres \
314348
--inputdir=${./tests} \
315349
--outputdir=$out/regression_output \
316350
--host=${self.supabase.defaults.host} \
317351
--port=${pgPort} \
318352
--user=supabase_admin \
319-
${builtins.concatStringsSep " " sortedTestList}; then
320-
echo "pg_regress tests failed"
353+
${builtins.concatStringsSep " " sortedTestList} 2>&1; then
354+
log error "pg_regress tests failed"
321355
cat $out/regression_output/regression.diffs
322356
exit 1
323357
fi
358+
log info "pg_regress tests completed successfully"
324359
325-
echo "Running migrations tests"
326-
pg_prove -p ${pgPort} -U supabase_admin -h ${self.supabase.defaults.host} -d postgres -v ${../migrations/tests}/test.sql
327-
328-
# Copy logs to output
329-
for logfile in $(find /tmp -name postgresql.log -type f); do
330-
cp "$logfile" $out/postgresql.log
331-
done
332-
exit 0
360+
log info "Running migrations tests"
361+
log_cmd pg_prove -p ${pgPort} -U supabase_admin -h ${self.supabase.defaults.host} -d postgres -v ${../migrations/tests}/test.sql
362+
log info "Migrations tests completed successfully"
333363
'';
334364
in
335365
{

0 commit comments

Comments
 (0)