#!/usr/bin/env bash # # pg_upgrade_cluster - Shared binary pg_upgrade mechanics for CI. Used by BOTH # pg-upgrade-test (filesystem-installed cat_tools) and pg-tle-upgrade-test # (pg_tle-registered cat_tools) in .github/workflows/ci.yml -- this part of # the flow has nothing extension-specific about it, so it lives here once # instead of being duplicated near-verbatim in both jobs. # # Lives under .github/, not bin/: unlike bin/test_existing (which a developer # can run locally against a scratch database), this is CI-mechanics-only -- # pg_ctlcluster/pg_createcluster/pg_upgrade against the pgxn-tools image's # "test" cluster convention isn't a locally-runnable workflow. # # USAGE: .github/scripts/pg_upgrade_cluster [args] # # recreate-old PG_VERSION # pg-start's default "test" cluster doesn't have data checksums # enabled, but binary pg_upgrade requires the old and new clusters to # have MATCHING checksum/auth settings (see $INITDB_OPTS below) -- # stop, drop, and recreate the "test" cluster for PG_VERSION with them, # then start it and wait for readiness. # # upgrade OLD_PG NEW_PG [EXTRA_NEW_CONF] # Stop the old cluster, create the new cluster's "test" cluster (same # $INITDB_OPTS), optionally append EXTRA_NEW_CONF to its # postgresql.conf (e.g. to enable pg_tle before pg_upgrade runs), binary # pg_upgrade OLD_PG -> NEW_PG, then start the new cluster and wait for # readiness. On pg_upgrade failure, dumps its logs (PG17+ writes them to # $new_datadir/pg_upgrade_output.d/; older versions write to CWD -- both # are searched) before failing. # # $INITDB_OPTS (env var, required): initdb options both clusters must share so # pg_upgrade sees consistent settings on old and new (e.g. # "--data-checksums --auth trust"). Deliberately left unquoted at each use # site so its (space-separated) options word-split into separate arguments. set -euo pipefail : "${INITDB_OPTS:?INITDB_OPTS must be set}" recreate_old() { local pg=$1 pg_ctlcluster "$pg" test stop pg_dropcluster "$pg" test # -p 5432: pg_createcluster assigns the next available port, which may not # be 5432 after pg-start has claimed and released it. Force 5432 so # subsequent psql/createdb calls connect without -p. pg_createcluster -p 5432 "$pg" test -- $INITDB_OPTS pg_ctlcluster "$pg" test start pg_isready -t 30 } upgrade() { local old_pg=$1 new_pg=$2 extra_conf=${3:-} pg_ctlcluster "$old_pg" test stop pg_createcluster -p 5432 "$new_pg" test -- $INITDB_OPTS # Use `if`, not `&&`: a false test under `set -e` would abort the script. if [ -n "$extra_conf" ]; then echo "$extra_conf" >> "/etc/postgresql/$new_pg/test/postgresql.conf" fi # PG17+ writes logs to $new_datadir/pg_upgrade_output.d/; older versions # write to CWD. Search both on failure. mkdir -p /tmp/pg_upgrade_logs chown postgres:postgres /tmp/pg_upgrade_logs su -c "cd /tmp/pg_upgrade_logs && /usr/lib/postgresql/$new_pg/bin/pg_upgrade \ -b /usr/lib/postgresql/$old_pg/bin \ -B /usr/lib/postgresql/$new_pg/bin \ -d /var/lib/postgresql/$old_pg/test \ -D /var/lib/postgresql/$new_pg/test \ -o '-c config_file=/etc/postgresql/$old_pg/test/postgresql.conf' \ -O '-c config_file=/etc/postgresql/$new_pg/test/postgresql.conf'" postgres \ || { find /tmp/pg_upgrade_logs \ "/var/lib/postgresql/$new_pg/test/pg_upgrade_output.d" \ -name '*.log' 2>/dev/null | sort | xargs -r tail -n +1; exit 1; } pg_ctlcluster "$new_pg" test start pg_isready -t 30 } usage() { echo "usage: .github/scripts/pg_upgrade_cluster [args]" >&2 echo " recreate-old PG_VERSION" >&2 echo " upgrade OLD_PG NEW_PG [EXTRA_NEW_CONF]" >&2 exit 2 } main() { local cmd=${1:-} shift || true case "$cmd" in recreate-old) recreate_old "$@" ;; upgrade) upgrade "$@" ;; *) usage ;; esac } main "$@"