#!/usr/bin/env bash # # Ship local `supabase/migrations/*.sql` to the prod DB and apply them in # alphabetical order (= timestamp order given Supabase's filename convention). # # Usage: # ./scripts/prod/push-migrations.sh # apply all migrations # ./scripts/prod/push-migrations.sh 20260501_foo # apply only matching files # # Migrations should be idempotent (`IF NOT EXISTS` / `OR REPLACE`) — the # script stops on the first failing statement so you notice drift immediately. set -euo pipefail here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "${here}/config.sh" repo_root="$(cd "${here}/../.." && pwd)" migrations_dir="${repo_root}/supabase/migrations" if [[ ! -d "${migrations_dir}" ]]; then echo "migrations dir not found: ${migrations_dir}" >&2 exit 1 fi filter="${1:-}" echo "syncing ${migrations_dir} → ${SSH_HOST}:/tmp/migrations" remote "rm -rf /tmp/migrations && mkdir -p /tmp/migrations" # shellcheck disable=SC2086 scp ${SSH_OPTS} -r "${migrations_dir}"/* "${SSH_HOST}:/tmp/migrations/" echo echo "applying migrations via docker exec db psql" remote "cd ${PROD_SUPABASE_DIR} && for f in /tmp/migrations/*.sql; do \ case \"\$(basename \"\$f\")\" in \ *${filter}*) echo \"=== applying \$f ===\"; docker compose exec -T db psql -U postgres -d postgres -v ON_ERROR_STOP=1 < \"\$f\" ;; \ *) echo \"=== skipping \$f (filter '${filter}') ===\" ;; \ esac; \ done" echo echo "done."