#!/usr/bin/env bash # Run Findings Ledger database migrations # Usage: ./run-migrations.sh [connection-string] # # Environment variables: # LEDGER__DB__CONNECTIONSTRING - PostgreSQL connection string (if not provided as arg) set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" MIGRATIONS_DIR="${SCRIPT_DIR}/../migrations" # Color output helpers RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' log_info() { echo -e "${GREEN}[INFO]${NC} $*"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } log_error() { echo -e "${RED}[ERROR]${NC} $*"; } # Get connection string CONNECTION_STRING="${1:-${LEDGER__DB__CONNECTIONSTRING:-}}" if [[ -z "$CONNECTION_STRING" ]]; then log_error "Connection string required" echo "Usage: $0 " echo " or set LEDGER__DB__CONNECTIONSTRING environment variable" exit 1 fi # Detect container runtime detect_runtime() { if command -v docker &>/dev/null; then echo "docker" elif command -v nerdctl &>/dev/null; then echo "nerdctl" elif command -v podman &>/dev/null; then echo "podman" else log_error "No container runtime found" exit 1 fi } RUNTIME=$(detect_runtime) # Run migrations via container run_migrations_container() { log_info "Running migrations via container..." $RUNTIME run --rm \ -e "LEDGER__DB__CONNECTIONSTRING=${CONNECTION_STRING}" \ --network host \ stellaops/findings-ledger-migrations:2025.11.0 \ --connection "$CONNECTION_STRING" } # Alternative: Run migrations via psql (if dotnet not available) run_migrations_psql() { log_info "Running migrations via psql..." if ! command -v psql &>/dev/null; then log_error "psql not found and container runtime unavailable" exit 1 fi # Parse connection string for psql # Expected format: Host=...;Port=...;Database=...;Username=...;Password=... local host port database username password host=$(echo "$CONNECTION_STRING" | grep -oP 'Host=\K[^;]+') port=$(echo "$CONNECTION_STRING" | grep -oP 'Port=\K[^;]+' || echo "5432") database=$(echo "$CONNECTION_STRING" | grep -oP 'Database=\K[^;]+') username=$(echo "$CONNECTION_STRING" | grep -oP 'Username=\K[^;]+') password=$(echo "$CONNECTION_STRING" | grep -oP 'Password=\K[^;]+') export PGPASSWORD="$password" for migration in "${MIGRATIONS_DIR}"/*.sql; do if [[ -f "$migration" ]]; then log_info "Applying: $(basename "$migration")" psql -h "$host" -p "$port" -U "$username" -d "$database" -f "$migration" fi done unset PGPASSWORD } verify_connection() { log_info "Verifying database connection..." # Try container-based verification if $RUNTIME run --rm \ --network host \ postgres:14-alpine \ pg_isready -h "$(echo "$CONNECTION_STRING" | grep -oP 'Host=\K[^;]+')" \ -p "$(echo "$CONNECTION_STRING" | grep -oP 'Port=\K[^;]+' || echo 5432)" \ &>/dev/null; then log_info "Database connection verified" return 0 fi log_warn "Could not verify database connection (may still work)" return 0 } main() { log_info "Findings Ledger - Database Migrations" log_info "======================================" verify_connection # Prefer container-based migrations if $RUNTIME image inspect stellaops/findings-ledger-migrations:2025.11.0 &>/dev/null; then run_migrations_container else log_warn "Migration image not found, falling back to psql" run_migrations_psql fi log_info "Migrations complete" } main "$@"