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

@@ -56,7 +56,9 @@ def create_app() -> FastAPI:
app = FastAPI(
title="__APP_NAME__",
version="0.1.0",
dependencies=[Depends(_require_auth_dep)] if settings.OPENAPI_REQUIRE_AUTH else [],
dependencies=(
[Depends(_require_auth_dep)] if settings.OPENAPI_REQUIRE_AUTH else []
),
)
@app.middleware("http")

View File

@@ -1,6 +1,16 @@
# Dependencias de desarrollo y CI del golden path web-backend/python.
# Self-contained (ADR-061): el repo del tenant no tiene acceso al monorepo IDP,
# así que las versiones de tooling se inlinean aquí en vez de referenciar
# code/requirements-dev-base.txt. Mantener alineadas a ese archivo (ADR-038).
-r requirements.txt
-r ../../code/requirements-dev-base.txt
# Tooling de calidad — versiones canónicas ADR-038
ruff==0.9.10
black==25.1.0
bandit==1.8.3
pytest==8.3.5
pytest-cov==6.0.0
# Específicas del shape — los tests corren sobre SQLite efímero (sin Docker).
httpx==0.27.2
pytest-asyncio==0.24.0
testcontainers[mariadb]==4.8.2

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()