Merge pull request 'Enhance database URL handling in Alembic environment' (#250) from ci-cd/migrations into development

Reviewed-on: ADUANASOFT/anexo76#250
This commit is contained in:
2026-03-24 20:33:15 +00:00

View File

@@ -3,7 +3,7 @@ import logging
import os
import sys
from logging.config import fileConfig
from urllib.parse import quote_plus
from urllib.parse import quote_plus, urlparse
from alembic import context
from alembic.operations import ops
@@ -18,9 +18,15 @@ logger = logging.getLogger(__name__)
config = context.config
def _strip_env_url(raw: str) -> str:
"""Quita espacios/comillas típicos de secretos CI (.env, Gitea)."""
url = raw.strip().strip('"').strip("'")
return url
def _normalize_alembic_sqlalchemy_url(url: str) -> str:
"""Alembic usa el driver síncrono psycopg2; normaliza DSN típicos de app/tests."""
url = url.strip()
url = _strip_env_url(url)
if url.startswith("postgresql+asyncpg://"):
return url.replace("postgresql+asyncpg://", "postgresql+psycopg2://", 1)
if url.startswith("postgresql+psycopg2://"):
@@ -34,11 +40,18 @@ def _normalize_alembic_sqlalchemy_url(url: str) -> str:
def get_database_url():
"""Obtiene la URL de la base de datos (PostgreSQL) desde variables de entorno o alembic.ini."""
# CI / pytest: misma URL que los tests (secret TEST_DATABASE_URL) o DATABASE_URL explícita
# CI / pytest: misma URL que los tests (secret TEST_DATABASE_URL) o DATABASE_URL explícita.
# Nota: ("X") sin coma es str, no tupla; el for iteraría caracteres y jamás leería la variable.
for env_key in ("TEST_DATABASE_URL"):
raw = os.environ.get(env_key)
if raw and raw.strip():
return _normalize_alembic_sqlalchemy_url(raw)
normalized = _normalize_alembic_sqlalchemy_url(raw)
if not urlparse(normalized).scheme:
raise RuntimeError(
f"{env_key} no es una URL válida (falta esquema). "
"Ejemplo: postgresql://usuario:clave@host:5432/nombre_bd"
)
return normalized
# Construcción desde settings (CORE_DB_* en .env / entorno)
host = settings.CORE_DB_HOST
@@ -58,11 +71,11 @@ def get_database_url():
# Fallback al archivo de configuración
url = config.get_main_option("sqlalchemy.url")
if not url:
if not url or "${" in url or "%(" in url:
raise RuntimeError(
"No se ha configurado la cadena de conexión a PostgreSQL. "
"Define TEST_DATABASE_URL o DATABASE_URL, o CORE_DB_HOST/CORE_DB_USER/CORE_DB_PASSWORD/CORE_DB_NAME, "
"o sqlalchemy.url en alembic.ini"
"Define TEST_DATABASE_URL o DATABASE_URL, o variables CORE_DB_*; "
"sqlalchemy.url en alembic.ini con placeholders ${...} no está soportado."
)
return url