#!/usr/bin/env bash set -Eeuo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" MIGRATIONS_DIR="${ROOT_DIR}/migrations" require_cmd() { if ! command -v "$1" >/dev/null 2>&1; then echo "[setup] ERRO: comando '$1' não encontrado. Instale-o e tente novamente." >&2 exit 1 fi } require_cmd psql require_cmd php if [[ -f "${ROOT_DIR}/.env" ]]; then set -a # shellcheck disable=SC1090 source <(sed $'s/\r$//' "${ROOT_DIR}/.env") set +a fi for var in DB_HOST DB_PORT DB_NAME DB_USER DB_PASSWORD; do if [[ -z "${!var:-}" ]]; then echo "[setup] ERRO: variável ${var} não definida (.env)." >&2 exit 1 fi done DB_SUPERUSER="${DB_SUPERUSER:-${DB_USER}}" DB_SUPERUSER_PASSWORD="${DB_SUPERUSER_PASSWORD:-${DB_PASSWORD}}" DB_SUPERUSER_DB="${DB_SUPERUSER_DB:-postgres}" run_psql() { local db="$1" shift PGPASSWORD="${DB_PASSWORD}" psql -h "${DB_HOST}" -p "${DB_PORT}" -U "${DB_USER}" -d "${db}" "$@" } run_psql_super() { local db="${1:-${DB_SUPERUSER_DB}}" shift PGPASSWORD="${DB_SUPERUSER_PASSWORD}" psql -h "${DB_HOST}" -p "${DB_PORT}" -U "${DB_SUPERUSER}" -d "${db}" "$@" } database_exists() { local exists exists="$(run_psql_super "${DB_SUPERUSER_DB}" -tAc "SELECT 1 FROM pg_database WHERE datname='${DB_NAME}'" | tr -d '[:space:]')" [[ "${exists}" == "1" ]] } ensure_migrations_table() { run_psql "${DB_NAME}" -v ON_ERROR_STOP=1 <<'SQL' CREATE TABLE IF NOT EXISTS migrations_run ( filename TEXT PRIMARY KEY, applied_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); SQL } migration_already_applied() { local name="$1" local result result="$(run_psql "${DB_NAME}" -tAc "SELECT 1 FROM migrations_run WHERE filename='${name//\'/''}'" | tr -d '[:space:]')" [[ "${result}" == "1" ]] } record_migration_applied() { local name="$1" run_psql "${DB_NAME}" -v ON_ERROR_STOP=1 -c "INSERT INTO migrations_run (filename) VALUES ('${name//\'/''}') ON CONFLICT (filename) DO NOTHING;" } bootstrap_migrations_state() { local count count="$(run_psql "${DB_NAME}" -tAc "SELECT COUNT(*) FROM migrations_run" | tr -d '[:space:]')" if [[ "${count}" -gt 0 ]]; then return fi local chain_reg chain_reg="$(run_psql "${DB_NAME}" -tAc "SELECT to_regclass('public.chain')" | tr -d '[:space:]')" if [[ -n "${chain_reg}" ]]; then record_migration_applied "migrations_v1.sql" fi local cpr_col cpr_col="$(run_psql "${DB_NAME}" -tAc "SELECT 1 FROM information_schema.columns WHERE table_name='cpr' AND column_name='user_id'" | tr -d '[:space:]')" if [[ "${cpr_col}" == "1" ]]; then record_migration_applied "migration_user_id.sql" fi } if [[ ! -d "${MIGRATIONS_DIR}" ]]; then echo "[setup] ERRO: diretório de migrações inexistente (${MIGRATIONS_DIR})." >&2 exit 1 fi collect_migrations() { local -a ordered=() local primary="${MIGRATIONS_DIR}/migrations_v1.sql" if [[ -f "${primary}" ]]; then ordered+=("${primary}") fi local -a extras=() local file shopt -s nullglob for file in "${MIGRATIONS_DIR}"/*.sql; do [[ "${file}" == "${primary}" ]] && continue extras+=("${file}") done shopt -u nullglob if (( ${#extras[@]} )); then # shellcheck disable=SC2207 extras=($(printf '%s\n' "${extras[@]}" | sort)) ordered+=("${extras[@]}") fi if (( ${#ordered[@]} == 0 )); then echo "[setup] ERRO: nenhum arquivo .sql encontrado em ${MIGRATIONS_DIR}." >&2 exit 1 fi MIGRATION_FILES=("${ordered[@]}") } collect_migrations echo "[setup] Host=${DB_HOST} Port=${DB_PORT} DB=${DB_NAME} User=${DB_USER}" echo "[setup] Verificando existência do banco '${DB_NAME}'..." if database_exists; then echo "[setup] Banco já existe. Pulando recriação." else echo "[setup] Banco não encontrado. Criando..." run_psql_super "${DB_SUPERUSER_DB}" -v ON_ERROR_STOP=1 -c "CREATE DATABASE \"${DB_NAME}\";" fi ensure_migrations_table bootstrap_migrations_state echo "[setup] Aplicando migrações..." for migration in "${MIGRATION_FILES[@]}"; do name="$(basename "${migration}")" if migration_already_applied "${name}"; then echo " -> ${name} (já aplicada, pulando)" continue fi echo " -> ${name}" run_psql "${DB_NAME}" -v ON_ERROR_STOP=1 -f "${migration}" record_migration_applied "${name}" done echo "[setup] Inserindo dados iniciais (seed)..." run_psql "${DB_NAME}" -v ON_ERROR_STOP=1 <