77 lines
1.7 KiB
Bash
77 lines
1.7 KiB
Bash
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
MIGRATION_DIR="${1:-db/migrations}"
|
|
DB_CONNECTION_STRING="${2:-}"
|
|
|
|
if [ ! -d "$MIGRATION_DIR" ]; then
|
|
echo "Migration directory not found: $MIGRATION_DIR" >&2
|
|
exit 1
|
|
fi
|
|
|
|
mapfile -t files < <(find "$MIGRATION_DIR" -maxdepth 1 -type f -name 'V*.sql' | sort)
|
|
|
|
if [ "${#files[@]}" -eq 0 ]; then
|
|
echo "No migration files found in $MIGRATION_DIR" >&2
|
|
exit 1
|
|
fi
|
|
|
|
declare -A seen_versions=()
|
|
duplicate_found=0
|
|
|
|
for file in "${files[@]}"; do
|
|
name="$(basename "$file")"
|
|
version="${name#V}"
|
|
version="${version%%__*}"
|
|
if [ -n "${seen_versions[$version]:-}" ]; then
|
|
echo "Duplicate migration version detected: V$version" >&2
|
|
echo " - ${seen_versions[$version]}" >&2
|
|
echo " - $file" >&2
|
|
duplicate_found=1
|
|
else
|
|
seen_versions["$version"]="$file"
|
|
fi
|
|
done
|
|
|
|
if [ "$duplicate_found" -ne 0 ]; then
|
|
exit 1
|
|
fi
|
|
|
|
if [ -z "$DB_CONNECTION_STRING" ]; then
|
|
echo "Duplicate version check passed."
|
|
exit 0
|
|
fi
|
|
|
|
if ! command -v psql >/dev/null 2>&1; then
|
|
echo "psql is required for database dry-run validation." >&2
|
|
exit 1
|
|
fi
|
|
|
|
mapfile -t executed_versions < <(
|
|
psql "$DB_CONNECTION_STRING" -Atc "SELECT version FROM schema_migrations ORDER BY version;" 2>/dev/null || true
|
|
)
|
|
|
|
declare -A executed_map=()
|
|
for version in "${executed_versions[@]}"; do
|
|
if [ -n "$version" ]; then
|
|
executed_map["$version"]=1
|
|
fi
|
|
done
|
|
|
|
for file in "${files[@]}"; do
|
|
name="$(basename "$file")"
|
|
version="${name#V}"
|
|
version="${version%%__*}"
|
|
if [ -n "${executed_map[$version]:-}" ]; then
|
|
continue
|
|
fi
|
|
echo "Dry-run migration V$version: $name"
|
|
psql "$DB_CONNECTION_STRING" -v ON_ERROR_STOP=1 <<PSQL
|
|
BEGIN;
|
|
\\i $file
|
|
ROLLBACK;
|
|
PSQL
|
|
done
|
|
|
|
echo "Migration dry-run validation passed."
|