sync: workflow CI self-contained + imagen Harbor t-<short> (ADR-061)
Some checks failed
__APP_NAME__ — build & deploy / Calidad + build + push (push) Failing after 2m44s
__APP_NAME__ — build & deploy / Helm upgrade --install (push) Has been skipped

Workflow <app>-build.yaml self-contained — sin uses: cross-repo al repo
privado coralware/IDP. requirements-dev.txt inline. image.repository apunta
al proyecto Harbor dedicado del tenant t-<tenant-id-short> (ADR-019 D-03).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Coralware Template Sync
2026-05-21 22:08:14 -05:00
parent 5d51971270
commit 1c6b8ae182
5 changed files with 128 additions and 37 deletions

View File

@@ -1,32 +1,47 @@
"""
Fixtures para los tests del shape.
Fixtures para los tests del shape web-backend/python.
Levanta una MariaDB efímera con testcontainers para que los tests corran
contra una BD real (no mocks). El reusable workflow ADR-038 garantiza que
Docker está disponible en el runner.
Los tests corren contra una BD SQLite efímera en archivo temporal — el runner
CI (executor=host, ADR-043) no tiene Docker daemon, por lo que no se usa
testcontainers (ADR-061). El deploy real usa MariaDB (claim-mariadb.yaml + hook
Alembic); los tests del scaffold solo ejercen /health, /demo y /metrics, sin
tocar Alembic ni modelos de dominio. Al añadir modelos reales, agrega tests de
integración contra tu propia infra.
"""
import os
import tempfile
from collections.abc import Iterator
import pytest
from fastapi.testclient import TestClient
from testcontainers.mariadb import MariaDbContainer
# La configuración debe existir ANTES de importar app.settings: Settings() exige
# DATABASE_URL al cargar el módulo. Se usa un archivo SQLite temporal (no
# :memory:) para evitar problemas de hilos con el TestClient.
_DB_FD, _DB_PATH = tempfile.mkstemp(suffix=".sqlite", prefix="webapp-test-")
os.close(_DB_FD)
_SQLITE_URL = f"sqlite:///{_DB_PATH}"
os.environ.setdefault("DATABASE_URL", _SQLITE_URL)
os.environ.setdefault("MIGRATION_DATABASE_URL", _SQLITE_URL)
# El frontend estático /demo se sirve desde el árbol del repo durante los tests.
_DEMO_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "app", "static", "demo"))
os.environ.setdefault("STATIC_DEMO_PATH", _DEMO_DIR)
@pytest.fixture(scope="session")
def mariadb_url() -> Iterator[str]:
"""MariaDB efímera por sesión de tests; URL exportada como DATABASE_URL."""
with MariaDbContainer("mariadb:11") as mdb:
url = mdb.get_connection_url().replace("mysql://", "mysql+pymysql://", 1)
os.environ["DATABASE_URL"] = url
os.environ["MIGRATION_DATABASE_URL"] = url
yield url
@pytest.fixture(scope="session", autouse=True)
def _cleanup_sqlite() -> Iterator[None]:
"""Borra el archivo SQLite temporal al terminar la sesión de tests."""
yield
try:
os.unlink(_DB_PATH)
except OSError:
pass
@pytest.fixture
def client(mariadb_url: str) -> Iterator[TestClient]:
"""TestClient con la app cargada contra la BD efímera."""
def client() -> Iterator[TestClient]:
"""TestClient con la app cargada contra la BD SQLite efímera."""
from app.main import create_app
app = create_app()