[BACKEND] Initialize Go backend structure and dependencies (#23)
This commit is contained in:
91
scripts/db-migrate.sh
Normal file
91
scripts/db-migrate.sh
Normal file
@@ -0,0 +1,91 @@
|
||||
#!/bin/bash
|
||||
# ============================================
|
||||
# Chat Switchboard - Database Migration Runner
|
||||
# ============================================
|
||||
# Tracks applied migrations in schema_migrations.
|
||||
# In dev (DB_WIPE=true): drops all tables, re-runs
|
||||
# all migrations for a clean slate every PR build.
|
||||
#
|
||||
# Required env vars:
|
||||
# PGHOST, PGPORT, PGUSER, PGPASSWORD — app-level connection
|
||||
# DB_NAME — target database
|
||||
# DB_WIPE — "true" to wipe first (dev only)
|
||||
# ============================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
MIGRATIONS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../migrations" && pwd)"
|
||||
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "Migration runner: ${DB_NAME}"
|
||||
echo " Wipe mode: ${DB_WIPE}"
|
||||
echo " Migrations: ${MIGRATIONS_DIR}"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
|
||||
export PGDATABASE="${DB_NAME}"
|
||||
|
||||
# ── Dev wipe: drop everything and start fresh ─
|
||||
if [[ "${DB_WIPE}" == "true" ]]; then
|
||||
echo "⚠ Dev wipe: dropping all objects..."
|
||||
psql <<'SQL'
|
||||
DO $$ DECLARE
|
||||
r RECORD;
|
||||
BEGIN
|
||||
-- Drop all views
|
||||
FOR r IN (SELECT viewname FROM pg_views WHERE schemaname = 'public') LOOP
|
||||
EXECUTE 'DROP VIEW IF EXISTS public.' || quote_ident(r.viewname) || ' CASCADE';
|
||||
END LOOP;
|
||||
-- Drop all tables (including schema_migrations for clean slate)
|
||||
FOR r IN (SELECT tablename FROM pg_tables WHERE schemaname = 'public') LOOP
|
||||
EXECUTE 'DROP TABLE IF EXISTS public.' || quote_ident(r.tablename) || ' CASCADE';
|
||||
END LOOP;
|
||||
-- Drop all functions (skip extension-owned like uuid_nil etc)
|
||||
FOR r IN (SELECT ns.nspname || '.' || p.proname || '(' || pg_get_function_identity_arguments(p.oid) || ')' AS func
|
||||
FROM pg_proc p JOIN pg_namespace ns ON p.pronamespace = ns.oid
|
||||
WHERE ns.nspname = 'public'
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM pg_depend d
|
||||
WHERE d.objid = p.oid AND d.deptype = 'e'
|
||||
)) LOOP
|
||||
EXECUTE 'DROP FUNCTION IF EXISTS ' || r.func || ' CASCADE';
|
||||
END LOOP;
|
||||
END $$;
|
||||
SQL
|
||||
echo "✓ All public schema objects dropped"
|
||||
fi
|
||||
|
||||
# ── Ensure tracking table exists ──────────────
|
||||
psql <<'SQL'
|
||||
CREATE TABLE IF NOT EXISTS schema_migrations (
|
||||
version VARCHAR(255) PRIMARY KEY,
|
||||
applied_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
SQL
|
||||
|
||||
# ── Apply pending migrations ──────────────────
|
||||
APPLIED=0
|
||||
SKIPPED=0
|
||||
|
||||
for migration in "${MIGRATIONS_DIR}"/*.sql; do
|
||||
[[ -f "${migration}" ]] || continue
|
||||
|
||||
VERSION=$(basename "${migration}")
|
||||
|
||||
ALREADY=$(psql -tAc "SELECT 1 FROM schema_migrations WHERE version = '${VERSION}';")
|
||||
|
||||
if [[ "${ALREADY}" == "1" ]]; then
|
||||
echo " skip: ${VERSION} (already applied)"
|
||||
SKIPPED=$((SKIPPED + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
echo " apply: ${VERSION}..."
|
||||
psql -v ON_ERROR_STOP=1 -f "${migration}"
|
||||
psql -c "INSERT INTO schema_migrations (version) VALUES ('${VERSION}');"
|
||||
APPLIED=$((APPLIED + 1))
|
||||
echo " ✓ ${VERSION} applied"
|
||||
done
|
||||
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "Migrations complete: ${APPLIED} applied, ${SKIPPED} skipped"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
Reference in New Issue
Block a user