#!/bin/sh set -eu ROOT=$(CDPATH='' cd -- "$(dirname -- "$0")/.." && pwd) cd "$ROOT" if [ "$#" -ne 1 ]; then echo "Usage: $0 PATH_TO_CUSTOM_FORMAT_DUMP" >&2 exit 1 fi dump=$1 checksum="$dump.sha256" if [ ! -f "$dump" ] || [ ! -s "$dump" ]; then echo "Dump does not exist or is empty: $dump" >&2 exit 1 fi if [ ! -f "$checksum" ]; then echo "Checksum manifest is required: $checksum" >&2 exit 1 fi if [ ! -f "$ROOT/.env" ]; then echo "Missing $ROOT/.env." >&2 exit 1 fi set -a # shellcheck source=/dev/null . "$ROOT/.env" set +a : "${POSTGRES_DB:?Set POSTGRES_DB in .env}" : "${POSTGRES_USER:?Set POSTGRES_USER in .env}" : "${DATABASE_URL:?Set DATABASE_URL in .env}" dump_dir=$(CDPATH='' cd -- "$(dirname -- "$dump")" && pwd) dump_name=$(basename -- "$dump") ( cd "$dump_dir" sha256sum --check --status "$(basename -- "$checksum")" ) docker compose exec -T db pg_restore --list <"$dump" >/dev/null drill_db="who_need_help_restore_drill_$(date -u +%Y%m%d%H%M%S)_$$" created=false cleanup() { if [ "$created" = true ]; then docker compose exec -T db \ dropdb --username "$POSTGRES_USER" --if-exists "$drill_db" >/dev/null fi } trap cleanup EXIT HUP INT TERM docker compose exec -T db \ createdb \ --username "$POSTGRES_USER" \ --template template0 \ "$drill_db" created=true docker compose exec -T db \ pg_restore \ --username "$POSTGRES_USER" \ --dbname "$drill_db" \ --exit-on-error \ --no-owner \ --no-privileges <"$dump" tables=$( docker compose exec -T db \ psql --username "$POSTGRES_USER" --dbname "$drill_db" --tuples-only --no-align \ --command " SELECT tablename FROM pg_tables WHERE schemaname = 'public' AND tablename <> 'spatial_ref_sys' ORDER BY tablename; " ) table_count=0 total_rows=0 for table in $tables; do restored_count=$( docker compose exec -T db \ psql --username "$POSTGRES_USER" --dbname "$drill_db" --tuples-only --no-align \ --command "SELECT count(*) FROM \"$table\";" ) table_count=$((table_count + 1)) total_rows=$((total_rows + restored_count)) done if [ "$table_count" -eq 0 ]; then echo "The restored database contains no public application tables." >&2 exit 1 fi postgis_version=$( docker compose exec -T db \ psql --username "$POSTGRES_USER" --dbname "$drill_db" --tuples-only --no-align \ --command "SELECT PostGIS_Lib_Version();" ) case "$DATABASE_URL" in *\?*) database_base=${DATABASE_URL%%\?*} database_query="?${DATABASE_URL#*\?}" ;; *) database_base=$DATABASE_URL database_query= ;; esac database_prefix=${database_base%/*} if [ "$database_prefix" = "$database_base" ]; then echo "Could not derive the temporary drill DATABASE_URL." >&2 exit 1 fi drill_database_url="$database_prefix/$drill_db$database_query" docker compose run --rm --no-deps \ --env APP_ROLE=migrate \ --env "DATABASE_URL=$drill_database_url" \ migrate /app/bin/migrate docker compose run --rm --no-deps \ --env APP_ROLE=migrate \ --env "DATABASE_URL=$drill_database_url" \ migrate /app/bin/who_need_help eval 'WhoNeedHelp.Release.await_migrations()' migration_count=$( docker compose exec -T db \ psql --username "$POSTGRES_USER" --dbname "$drill_db" --tuples-only --no-align \ --command "SELECT count(*) FROM schema_migrations;" ) docker compose exec -T db \ dropdb --username "$POSTGRES_USER" "$drill_db" created=false trap - EXIT HUP INT TERM remaining=$( docker compose exec -T db \ psql --username "$POSTGRES_USER" --dbname postgres --tuples-only --no-align \ --command "SELECT count(*) FROM pg_database WHERE datname = '$drill_db';" ) if [ "$remaining" != "0" ]; then echo "Restore drill database was not removed: $drill_db" >&2 exit 1 fi echo "Restore drill passed for: $dump_name" echo "Readable public tables: $table_count" echo "Restored rows read: $total_rows" echo "Applied migrations: $migration_count" echo "PostGIS library: $postgis_version" echo "Temporary database removed: $drill_db"