chatdesk-ui/postgres_15.8.1.044/nix/tools/dbmate-tool.sh.in

305 lines
9.8 KiB
Bash

#!/usr/bin/env bash
# shellcheck shell=bash
[ ! -z "$DEBUG" ] && set -x
# Default values
PSQL_VERSION="ALL"
PORTNO="@PGSQL_DEFAULT_PORT@"
PGSQL_SUPERUSER="@PGSQL_SUPERUSER@"
PGPASSWORD="${PGPASSWORD:-postgres}"
PGSQL_USER="postgres"
FLAKE_URL="github:supabase/postgres"
MIGRATIONS_DIR="@MIGRATIONS_DIR@"
CURRENT_SYSTEM="@CURRENT_SYSTEM@"
ANSIBLE_VARS="@ANSIBLE_VARS@"
PGBOUNCER_AUTH_SCHEMA_SQL=@PGBOUNCER_AUTH_SCHEMA_SQL@
STAT_EXTENSION_SQL=@STAT_EXTENSION_SQL@
# Start PostgreSQL using nix
start_postgres() {
DATDIR=$(mktemp -d)
echo "Starting PostgreSQL in directory: $DATDIR" # Create the DATDIR if it doesn't exist
nix run "$FLAKE_URL#start-server" -- "$PSQL_VERSION" --skip-migrations --daemonize --datdir "$DATDIR"
echo "PostgreSQL started."
}
# Cleanup function
cleanup() {
echo "Cleaning up..."
# Check if PostgreSQL processes exist
if pgrep -f "postgres" >/dev/null; then
echo "Stopping PostgreSQL gracefully..."
# Use pg_ctl to stop PostgreSQL
pg_ctl -D "$DATDIR" stop
# Wait a bit for graceful shutdown
sleep 5
# Check if processes are still running
if pgrep -f "postgres" >/dev/null; then
echo "Warning: Some PostgreSQL processes could not be stopped gracefully."
fi
else
echo "PostgreSQL is not running, skipping stop."
fi
# Always exit successfully, log any remaining processes
if pgrep -f "postgres" >/dev/null; then
echo "Warning: Some PostgreSQL processes could not be cleaned up:"
pgrep -f "postgres"
else
echo "Cleanup completed successfully"
fi
}
# Function to display help
print_help() {
echo "Usage: nix run .#dbmate-tool -- [options]"
echo
echo "Options:"
echo " -v, --version [15|16|orioledb-17|all] Specify the PostgreSQL version to use (required defaults to --version all)"
echo " -p, --port PORT Specify the port number to use (default: 5435)"
echo " -h, --help Show this help message"
echo " -f, --flake-url URL Specify the flake URL to use (default: github:supabase/postgres)"
echo "Description:"
echo " Runs 'dbmate up' against a locally running the version of database you specify. Or 'all' to run against all versions."
echo " NOTE: To create a migration, you must run 'nix develop' and then 'dbmate new <migration_name>' to create a new migration file."
echo
echo "Examples:"
echo " nix run .#dbmate-tool"
echo " nix run .#dbmate-tool -- --version 15"
echo " nix run .#dbmate-tool -- --version 16 --port 5433"
echo " nix run .#dbmate-tool -- --version 16 --port 5433 --flake-url github:supabase/postgres/<commithash>"
}
# Parse arguments
while [[ "$#" -gt 0 ]]; do
case "$1" in
-v|--version)
if [[ -n "$2" && ! "$2" =~ ^- ]]; then
PSQL_VERSION="$2"
shift 2
else
echo "Error: --version requires an argument (15, 16, or orioledb-17)"
exit 1
fi
;;
-u|--user)
if [[ -n "$2" && ! "$2" =~ ^- ]]; then
PGSQL_USER="$2"
shift 2
else
echo "Error: --user requires an argument"
exit 1
fi
;;
-f|--flake-url)
if [[ -n "$2" && ! "$2" =~ ^- ]]; then
FLAKE_URL="$2"
shift 2
else
echo "Error: --flake-url requires an argument"
exit 1
fi
;;
-p|--port)
if [[ -n "$2" && ! "$2" =~ ^- ]]; then
PORTNO="$2"
shift 2
else
echo "Error: --port requires an argument"
exit 1
fi
;;
-h|--help)
print_help
exit 0
;;
*)
echo "Unknown option: $1"
print_help
exit 1
;;
esac
done
# Function to wait for PostgreSQL to be ready
wait_for_postgres() {
local max_attempts=30 # Increased significantly
local attempt=1
# Give PostgreSQL a moment to actually start the process
sleep 2
while [ $attempt -le $max_attempts ]; do
"${PSQLBIN}/pg_isready" -h localhost -p "$PORTNO" -U "$PGSQL_SUPERUSER" -d postgres
local status=$?
if [ $status -eq 0 ]; then
echo "PostgreSQL is ready!"
return 0
fi
echo "Waiting for PostgreSQL to start (attempt $attempt/$max_attempts)..."
sleep 2
attempt=$((attempt + 1))
done
echo "PostgreSQL failed to start after $max_attempts attempts"
return 1
}
check_orioledb_ready() {
local max_attempts=30
local attempt=1
while [ $attempt -le $max_attempts ]; do
if "${PSQLBIN}/psql" -v ON_ERROR_STOP=1 -U "$PGSQL_SUPERUSER" -p "$PORTNO" -h localhost -d postgres -c "SELECT * FROM pg_am WHERE amname = 'orioledb'" | grep -q orioledb; then
echo "Orioledb extension is ready!"
return 0
fi
echo "Waiting for orioledb to be ready (attempt $attempt/$max_attempts)..."
sleep 2
attempt=$((attempt + 1))
done
echo "Orioledb failed to initialize after $max_attempts attempts"
return 1
}
trim_schema() {
case "$CURRENT_SYSTEM" in
"x86_64-darwin"|"aarch64-darwin")
sed -i '' '/INSERT INTO public.schema_migrations/,$d' "./db/schema.sql"
echo "Matched: $CURRENT_SYSTEM"
;;
*)
sed -i '/INSERT INTO public.schema_migrations/,$d' "./db/schema.sql"
;;
esac
}
perform_dump() {
local max_attempts=3
local attempt=1
while [ $attempt -le $max_attempts ]; do
echo "Attempting dbmate dump (attempt $attempt/$max_attempts)"
if dbmate dump; then
return 0
fi
echo "Dump attempt $attempt failed, waiting before retry..."
sleep 5
attempt=$((attempt + 1))
done
echo "All dump attempts failed"
return 1
}
migrate_version() {
echo "PSQL_VERSION: $PSQL_VERSION"
#pkill -f "postgres" || true # Ensure PostgreSQL is stopped before starting
PSQLBIN=$(nix build --no-link "$FLAKE_URL#psql_$PSQL_VERSION/bin" --json | jq -r '.[].outputs.out + "/bin"')
echo "Using PostgreSQL version $PSQL_VERSION from $PSQLBIN"
# Start PostgreSQL
start_postgres
echo "Waiting for PostgreSQL to be ready..."
# Wait for PostgreSQL to be ready to accept connections
if ! wait_for_postgres; then
echo "Failed to connect to PostgreSQL server"
exit 1
fi
if [ "$PSQL_VERSION" = "orioledb-17" ]; then
if ! check_orioledb_ready; then
echo "Failed to initialize orioledb extension"
exit 1
fi
fi
echo "PostgreSQL server is ready"
# Configure PostgreSQL roles and permissions
if ! "${PSQLBIN}/psql" -v ON_ERROR_STOP=1 --no-password --no-psqlrc -U "$PGSQL_SUPERUSER" -p "$PORTNO" -h localhost -d postgres <<-EOSQL
create role postgres superuser login password '$PGPASSWORD';
alter database postgres owner to postgres;
EOSQL
then
echo "Failed to configure PostgreSQL roles and permissions"
exit 1
fi
"${PSQLBIN}/psql" -v ON_ERROR_STOP=1 --no-password --no-psqlrc -U postgres -p "$PORTNO" -h localhost -d postgres -f "$PGBOUNCER_AUTH_SCHEMA_SQL"
"${PSQLBIN}/psql" -v ON_ERROR_STOP=1 --no-password --no-psqlrc -U postgres -p "$PORTNO" -h localhost -d postgres -f "$STAT_EXTENSION_SQL"
# Set db url to run dbmate
export DATABASE_URL="postgres://$PGSQL_USER:$PGPASSWORD@localhost:$PORTNO/postgres?sslmode=disable"
# Export path so dbmate can find correct psql and pg_dump
export PATH="$PSQLBIN:$PATH"
# Run init scripts
if ! dbmate --migrations-dir "$MIGRATIONS_DIR/init-scripts" up; then
echo "Error: Initial migration failed"
exit 1
fi
# Password update command
if ! "${PSQLBIN}/psql" -v ON_ERROR_STOP=1 --no-password --no-psqlrc -U postgres -p "$PORTNO" -h localhost -c "ALTER USER supabase_admin WITH PASSWORD '$PGPASSWORD'"; then
echo "Error: Failed to update supabase_admin password"
exit 1
fi
# Set up database URL
export DATABASE_URL="postgres://$PGSQL_SUPERUSER:$PGPASSWORD@localhost:$PORTNO/postgres?sslmode=disable"
# Run migrations
if ! dbmate --migrations-dir "$MIGRATIONS_DIR/migrations" up; then
echo "Error: Final migration failed"
exit 1
fi
echo "Running dbmate dump with $PSQLBIN"
perform_dump
echo "CURRENT_SYSTEM: $CURRENT_SYSTEM"
if [ -f "./db/schema.sql" ]; then
trim_schema
cp "./db/schema.sql" "./migrations/schema-$PSQL_VERSION.sql"
echo "Schema file moved to ./migrations/schema-$PSQL_VERSION.sql"
echo "PSQLBIN is $PSQLBIN"
else
echo "Warning: schema.sql file not found in ./db directory"
exit 1
fi
# If we get here, all commands succeeded
echo "PostgreSQL migration completed successfully"
echo "Check migrations are idempotent"
for sql in ./migrations/db/migrations/*.sql; do
echo "$0: running $sql"
"${PSQLBIN}/psql" -v ON_ERROR_STOP=1 --no-password --no-psqlrc -U "$PGSQL_SUPERUSER" -p "$PORTNO" -h localhost -d postgres -f "$sql" || {
echo "Failed to execute $sql"
exit 1
}
done
}
if [ "$PSQL_VERSION" == "all" ]; then
VERSIONS=$(yq '.postgres_major[]' "$ANSIBLE_VARS" | tr -d '"')
echo "$VERSIONS" | while read -r version; do
PSQL_VERSION="$version"
echo "Migrating to PostgreSQL version $PSQL_VERSION"
migrate_version
cleanup
done
else
echo "Migrating to PostgreSQL version $PSQL_VERSION"
migrate_version
cleanup
fi