#!/usr/bin/env bash set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ROOT_DIR="$(cd "${SCRIPT_DIR}/../.." && pwd)" MIGRATIONS_DIR="${ROOT_DIR}/migrations" VERIFY_DIR="${SCRIPT_DIR}/verify" load_database_url_from_env_file() { local env_file="$1" local line value while IFS= read -r line || [[ -n "${line}" ]]; do line="${line#"${line%%[![:space:]]*}"}" [[ -z "${line}" || "${line}" == \#* ]] && continue line="${line#export }" if [[ "${line}" == DATABASE_URL=* ]]; then value="${line#DATABASE_URL=}" value="${value%$'\r'}" value="${value%\"}" value="${value#\"}" value="${value%\'}" value="${value#\'}" printf '%s' "${value}" return 0 fi done < "${env_file}" return 1 } DATABASE_URL="${DATABASE_URL:-}" if [[ -z "${DATABASE_URL}" && -f "${ROOT_DIR}/.env" ]]; then DATABASE_URL="$(load_database_url_from_env_file "${ROOT_DIR}/.env" || true)" fi if [[ -z "${DATABASE_URL}" ]]; then echo "DATABASE_URL is required (export it, or set it in ${ROOT_DIR}/.env)" exit 1 fi if ! command -v psql >/dev/null 2>&1; then echo "psql not found in PATH" exit 127 fi checksum_hex_of_file() { local file="$1" if command -v sha384sum >/dev/null 2>&1; then sha384sum "${file}" | awk '{print $1}' return 0 fi if command -v openssl >/dev/null 2>&1; then openssl dgst -sha384 -binary "${file}" | xxd -p -c 256 return 0 fi echo "sha384sum or openssl is required to compute sqlx checksum" >&2 return 127 } psql "${DATABASE_URL}" -v ON_ERROR_STOP=1 -c "CREATE TABLE IF NOT EXISTS _sqlx_migrations (version BIGINT PRIMARY KEY, description TEXT NOT NULL, installed_on TIMESTAMPTZ NOT NULL DEFAULT now(), success BOOLEAN NOT NULL, checksum BYTEA NOT NULL, execution_time BIGINT NOT NULL)" echo "Checking migration checksums in _sqlx_migrations..." shopt -s nullglob migrations=( "${MIGRATIONS_DIR}/"*.sql ) for file in "${migrations[@]}"; do base="$(basename "${file}")" version_str="${base%%_*}" version_num="$((10#${version_str}))" expected_checksum="$(checksum_hex_of_file "${file}")" actual_checksum="$(psql "${DATABASE_URL}" -At -c "SELECT encode(checksum,'hex') FROM _sqlx_migrations WHERE version=${version_num} AND success=true LIMIT 1" || true)" if [[ -n "${actual_checksum}" && "${actual_checksum}" != "${expected_checksum}" ]]; then echo "Checksum mismatch: version=${version_str} expected=${expected_checksum} actual=${actual_checksum}" exit 2 fi done echo "Running schema verify scripts..." verify_files=( "${VERIFY_DIR}/"*.sql ) if [[ ${#verify_files[@]} -eq 0 ]]; then echo "No verify files found: ${VERIFY_DIR}/*.sql" exit 1 fi for file in "${verify_files[@]}"; do base="$(basename "${file}")" echo "Verifying ${base}" psql "${DATABASE_URL}" -v ON_ERROR_STOP=1 -f "${file}" >/dev/null done echo "Verify completed"