Skip to content

Commit cc44930

Browse files
committed
feat: pg_upgrade testing
1 parent c98ecf3 commit cc44930

File tree

15 files changed

+644
-29
lines changed

15 files changed

+644
-29
lines changed
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
name: Test pg_upgrade
2+
3+
on:
4+
push:
5+
branches:
6+
- develop
7+
- pcnc/auto-pg_upgrade-testing
8+
pull_request:
9+
workflow_dispatch:
10+
11+
permissions:
12+
id-token: write
13+
14+
jobs:
15+
test:
16+
strategy:
17+
matrix:
18+
base_pg_version:
19+
- 15.1.0.100
20+
runs-on: arm-runner
21+
timeout-minutes: 30
22+
defaults:
23+
run:
24+
working-directory: ./tests/pg_upgrade
25+
env:
26+
PGPORT: 5478
27+
PGPASSWORD: postgres
28+
PGDATABASE: postgres
29+
PGUSER: supabase_admin
30+
PGHOST: localhost
31+
PG_MAJOR_VERSION: 15
32+
IS_CI: true
33+
container: pg_upgrade_test
34+
steps:
35+
- uses: actions/checkout@v3
36+
37+
- name: Grab release version
38+
id: process_release_version
39+
working-directory: ./
40+
run: |
41+
VERSION=$(sed -e 's/postgres-version = "\(.*\)"/\1/g' common.vars.pkr.hcl)
42+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
43+
44+
- name: configure aws credentials - staging
45+
uses: aws-actions/configure-aws-credentials@v1
46+
with:
47+
role-to-assume: ${{ secrets.DEV_AWS_ROLE }}
48+
aws-region: "us-east-1"
49+
50+
- name: Download pg_upgrade_scripts and binaries
51+
run: |
52+
aws s3 cp s3://${{ secrets.ARTIFACTS_BUCKET }}/upgrades/postgres/supabase-postgres-${{ steps.process_release_version.outputs.version }}/pg_upgrade_scripts.tar.gz scripts/pg_upgrade_scripts.tar.gz
53+
aws s3 cp s3://${{ secrets.ARTIFACTS_BUCKET }}/upgrades/postgres/supabase-postgres-${{ steps.process_release_version.outputs.version }}/20.04.tar.gz scripts/pg_upgrade_bin.tar.gz
54+
55+
- run: docker context create builders
56+
- uses: docker/setup-buildx-action@v2
57+
with:
58+
endpoint: builders
59+
driver-opts: image=moby/buildkit:v0.11.6
60+
buildkitd-flags: --debug
61+
62+
- name: Start Postgres
63+
run: |
64+
docker rm -f "$container" || true
65+
docker run --name "$container" --env-file .env \
66+
-v "$(pwd)/scripts:/tmp/upgrade" \
67+
--entrypoint "/tmp/upgrade/entrypoint.sh" -d \
68+
-p ${PGPORT}:5432 \
69+
"supabase/postgres:${{ matrix.base_pg_version }}"
70+
71+
- name: Install psql
72+
run: |
73+
sudo apt update
74+
sudo apt install -y --no-install-recommends postgresql-client
75+
76+
- name: Install pg_prove
77+
run: |
78+
sudo apt-get update
79+
sudo apt-get install -y --no-install-recommends perl cpanminus
80+
sudo cpanm -n App::cpanminus
81+
sudo cpanm -n TAP::Parser::SourceHandler::pgTAP
82+
env:
83+
SHELL: /bin/bash
84+
PERL_MM_USE_DEFAULT: 1
85+
PERL_MM_NONINTERACTIVE: 1
86+
87+
- name: Wait for healthy database
88+
run: |
89+
count=0
90+
while ! docker exec "$container" bash -c "pg_isready"; do
91+
count=$((count + 1))
92+
if [ $count -ge "$retries" ]; then
93+
echo "Retry $count/$retries exited $exit, no more retries left."
94+
docker logs "$container"
95+
docker rm -f "$container"
96+
exit 1
97+
fi
98+
done
99+
env:
100+
retries: 20
101+
102+
- name: Run migrations
103+
run: docker exec "$container" bash -c "/docker-entrypoint-initdb.d/migrate.sh > /tmp/migrate.log 2>&1"
104+
105+
- name: Run initial tests
106+
run: pg_prove "../../migrations/tests/test.sql"
107+
env:
108+
PERL5LIB: /usr/local/lib/perl5
109+
110+
- name: Apply pre-upgrade fixtures
111+
run: |
112+
psql -f "./tests/98-data-fixtures.sql"
113+
psql -f "./tests/99-fixtures.sql"
114+
115+
- name: Initiate upgrade
116+
run: docker exec "$container" bash -c '/tmp/upgrade/pg_upgrade_scripts/initiate.sh "$PG_MAJOR_VERSION"; exit $?'
117+
118+
- name: Complete pg_upgrade
119+
run: docker exec pg_upgrade_test bash -c '/tmp/upgrade/pg_upgrade_scripts/complete.sh; exit $?'
120+
121+
- name: Run post-upgrade tests
122+
run: |
123+
pg_prove tests/01-schema.sql
124+
pg_prove tests/02-data.sql
125+
pg_prove tests/03-settings.sql
126+
127+
- name: Clean up container
128+
if: ${{ always() }}
129+
continue-on-error: true
130+
run: docker rm -f "$container" || true

ansible/files/admin_api_scripts/pg_upgrade_scripts/common.sh

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,33 @@ function retry {
6161
done
6262
return 0
6363
}
64+
65+
stop_postgres() {
66+
BINDIR=$(pg_config --bindir)
67+
ARG=${1:-""}
68+
69+
if [ "$ARG" = "--new-bin" ]; then
70+
BINDIR="/tmp/pg_upgrade_bin/$PG_MAJOR_VERSION/bin"
71+
fi
72+
73+
if [ -z "$IS_CI" ]; then
74+
systemctl stop postgresql
75+
else
76+
su postgres -c "$BINDIR/pg_ctl stop -o '-c config_file=/etc/postgresql/postgresql.conf' -l /tmp/postgres.log"
77+
fi
78+
}
79+
80+
start_postgres() {
81+
BINDIR=$(pg_config --bindir)
82+
ARG=${1:-""}
83+
84+
if [ "$ARG" = "--new-bin" ]; then
85+
BINDIR="/tmp/pg_upgrade_bin/$PG_MAJOR_VERSION/bin"
86+
fi
87+
88+
if [ -z "$IS_CI" ]; then
89+
systemctl start postgresql
90+
else
91+
su postgres -c "$BINDIR/pg_ctl start -o '-c config_file=/etc/postgresql/postgresql.conf' -l /tmp/postgres.log"
92+
fi
93+
}

ansible/files/admin_api_scripts/pg_upgrade_scripts/complete.sh

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,22 +33,31 @@ function complete_pg_upgrade {
3333
echo "running" > /tmp/pg-upgrade-status
3434

3535
echo "1. Mounting data disk"
36-
retry 3 mount -a -v
36+
if [ -z "$IS_CI" ]; then
37+
retry 3 mount -a -v
38+
else
39+
echo "Skipping mount -a -v"
40+
fi
3741

3842
# copying custom configurations
3943
echo "2. Copying custom configurations"
4044
retry 3 copy_configs
4145

4246
echo "3. Starting postgresql"
43-
retry 3 service postgresql start
47+
if [ -z "$IS_CI" ]; then
48+
retry 3 start_postgres
49+
else
50+
start_postgres --new-bin
51+
fi
4452

4553
echo "4. Running generated SQL files"
4654
retry 3 run_generated_sql
4755

4856
sleep 5
4957

5058
echo "5. Restarting postgresql"
51-
retry 3 service postgresql restart
59+
retry 3 stop_postgres || true
60+
retry 3 start_postgres
5261

5362
echo "6. Starting vacuum analyze"
5463
retry 3 start_vacuum_analyze
@@ -78,5 +87,16 @@ function start_vacuum_analyze {
7887

7988
trap cleanup ERR
8089

90+
if [ -z "$IS_CI" ]; then
91+
complete_pg_upgrade >> $LOG_FILE 2>&1 &
92+
else
93+
stop_postgres || true
94+
95+
rm -f /tmp/pg-upgrade-status
96+
mv /data_migration /data
97+
98+
rm -rf /var/lib/postgresql/data
99+
ln -s /data/pgdata /var/lib/postgresql/data
81100

82-
complete_pg_upgrade >> $LOG_FILE 2>&1 &
101+
complete_pg_upgrade
102+
fi

ansible/files/admin_api_scripts/pg_upgrade_scripts/initiate.sh

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,6 @@ source "$SCRIPT_DIR/common.sh"
3434
LOG_FILE="/var/log/pg-upgrade-initiate.log"
3535

3636
PGVERSION=$1
37-
IS_DRY_RUN=${2:-false}
38-
if [ "$IS_DRY_RUN" != false ]; then
39-
IS_DRY_RUN=true
40-
fi
41-
4237
MOUNT_POINT="/data_migration"
4338

4439
POST_UPGRADE_EXTENSION_SCRIPT="/tmp/pg_upgrade/pg_upgrade_extensions.sql"
@@ -52,11 +47,16 @@ if [[ "$OLD_PGVERSION" =~ 13* ]]; then
5247
EXTENSIONS_TO_DISABLE+=("${PG13_EXTENSIONS_TO_DISABLE[@]}")
5348
fi
5449

50+
PGBINOLD="$(pg_config --bindir)"
5551

5652
cleanup() {
5753
UPGRADE_STATUS=${1:-"failed"}
5854
EXIT_CODE=${?:-0}
5955

56+
if [ "$UPGRADE_STATUS" = "failed" ]; then
57+
EXIT_CODE=1
58+
fi
59+
6060
if [ "$UPGRADE_STATUS" = "failed" ]; then
6161
echo "Upgrade job failed. Cleaning up and exiting."
6262
fi
@@ -71,21 +71,21 @@ cleanup() {
7171

7272
if [ -L "/usr/share/postgresql/${PGVERSION}" ]; then
7373
rm "/usr/share/postgresql/${PGVERSION}"
74+
fi
7475

75-
if [ -f "/usr/share/postgresql/${PGVERSION}.bak" ]; then
76-
mv "/usr/share/postgresql/${PGVERSION}.bak" "/usr/share/postgresql/${PGVERSION}"
77-
fi
76+
if [ -d "/usr/share/postgresql/${PGVERSION}.bak" ]; then
77+
rm -f "/usr/share/postgresql/${PGVERSION}"
78+
mv "/usr/share/postgresql/${PGVERSION}.bak" "/usr/share/postgresql/${PGVERSION}"
7879
fi
7980

8081
if [ -f "/usr/lib/postgresql/lib/aarch64/libpq.so.5.bak" ]; then
8182
rm /usr/lib/postgresql/lib/aarch64/libpq.so.5
8283
mv /usr/lib/postgresql/lib/aarch64/libpq.so.5.bak /usr/lib/postgresql/lib/aarch64/libpq.so.5
8384
fi
8485

85-
if [ "$IS_DRY_RUN" = false ]; then
86-
echo "Restarting postgresql"
87-
systemctl restart postgresql
88-
fi
86+
echo "Restarting postgresql"
87+
stop_postgres || true
88+
start_postgres
8989

9090
echo "Re-enabling extensions"
9191
if [ -f $POST_UPGRADE_EXTENSION_SCRIPT ]; then
@@ -95,13 +95,18 @@ cleanup() {
9595
echo "Removing SUPERUSER grant from postgres"
9696
run_sql -c "ALTER USER postgres WITH NOSUPERUSER;"
9797

98-
if [ "$IS_DRY_RUN" = false ]; then
98+
if [ "$IS_CI" = false ]; then
9999
echo "Unmounting data disk from ${MOUNT_POINT}"
100100
umount $MOUNT_POINT
101101
fi
102102
echo "$UPGRADE_STATUS" > /tmp/pg-upgrade-status
103103

104-
exit "$EXIT_CODE"
104+
if [ "$IS_CI" = false ]; then
105+
exit "$EXIT_CODE"
106+
else
107+
echo "CI run complete with code ${EXIT_CODE}. Exiting."
108+
exit "$EXIT_CODE"
109+
fi
105110
}
106111

107112
function handle_extensions {
@@ -165,6 +170,7 @@ function initiate_upgrade {
165170

166171
# copy upgrade-specific pgsodium_getkey script into the share dir
167172
chmod +x "$SCRIPT_DIR/pgsodium_getkey.sh"
173+
mkdir -p "$PGSHARENEW/extension"
168174
cp "$SCRIPT_DIR/pgsodium_getkey.sh" "$PGSHARENEW/extension/pgsodium_getkey"
169175
if [ -d "/var/lib/postgresql/extension/" ]; then
170176
cp "$SCRIPT_DIR/pgsodium_getkey.sh" "/var/lib/postgresql/extension/pgsodium_getkey"
@@ -190,12 +196,12 @@ function initiate_upgrade {
190196
DEBIAN_FRONTEND=noninteractive dpkg --configure -a --force-confold || true # handle errors generated by dpkg
191197

192198
# Needed for PostGIS, since it's compiled with Protobuf-C support now
193-
echo "3. Installing libprotobuf-c1 if missing"
199+
echo "3. Installing libprotobuf-c1 and libicu66 if missing"
194200
if [[ ! "$(apt list --installed libprotobuf-c1 | grep "installed")" ]]; then
195-
apt-get update && apt --fix-broken install -y libprotobuf-c1
201+
apt-get update && apt --fix-broken install -y libprotobuf-c1 libicu66 || true
196202
fi
197203

198-
if [ "$IS_DRY_RUN" = false ]; then
204+
if [ "$IS_CI" = false ]; then
199205
# awk NF==3 prints lines with exactly 3 fields, which are the block devices currently not mounted anywhere
200206
# excluding nvme0 since it is the root disk
201207
echo "4. Determining block device to mount"
@@ -213,6 +219,8 @@ function initiate_upgrade {
213219

214220
sleep 1
215221
resize2fs "$BLOCK_DEVICE"
222+
else
223+
mkdir -p "$MOUNT_POINT"
216224
fi
217225

218226
if [ -f "$MOUNT_POINT/pgsodium_root.key" ]; then
@@ -242,7 +250,7 @@ function initiate_upgrade {
242250

243251
UPGRADE_COMMAND=$(cat <<EOF
244252
time ${PGBINNEW}/pg_upgrade \
245-
--old-bindir="/usr/lib/postgresql/bin" \
253+
--old-bindir="${PGBINOLD}" \
246254
--new-bindir=${PGBINNEW} \
247255
--old-datadir=${PGDATAOLD} \
248256
--new-datadir=${PGDATANEW} \
@@ -254,12 +262,10 @@ function initiate_upgrade {
254262
EOF
255263
)
256264

257-
if [ "$IS_DRY_RUN" = true ]; then
258-
UPGRADE_COMMAND="$UPGRADE_COMMAND --check"
259-
else
260-
echo "9. Stopping postgres; running pg_upgrade"
261-
systemctl stop postgresql
262-
fi
265+
su -c "$UPGRADE_COMMAND --check" -s "$SHELL" postgres
266+
267+
echo "9. Stopping postgres; running pg_upgrade"
268+
stop_postgres
263269

264270
su -c "$UPGRADE_COMMAND" -s "$SHELL" postgres
265271

@@ -281,7 +287,8 @@ EOF
281287
trap cleanup ERR
282288

283289
echo "running" > /tmp/pg-upgrade-status
284-
if [ "$IS_DRY_RUN" = true ]; then
290+
if [ "$IS_CI" = true ]; then
291+
rm -f /tmp/pg-upgrade-status
285292
initiate_upgrade
286293
else
287294
initiate_upgrade >> "$LOG_FILE" 2>&1 &

tests/pg_upgrade/.env

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
POSTGRES_PASSWORD=postgres
2+
POSTGRES_HOST=/var/run/postgresql
3+
POSTGRES_INITDB_ARGS=--lc-ctype=C.UTF-8
4+
PG_MAJOR_VERSION=15
5+
IS_CI=true
6+
SCRIPT_DIR=/tmp/upgrade

tests/pg_upgrade/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# excluding these since running debug.sh will download the files locally
2+
pg_upgrade_bin.tar.gz
3+
pg_upgrade_scripts.tar.gz
4+
pg_upgrade_scripts/

0 commit comments

Comments
 (0)