diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml index c03afc92..f9688f35 100644 --- a/.gitea/workflows/build.yml +++ b/.gitea/workflows/build.yml @@ -13,6 +13,60 @@ jobs: steps: - name: Checkout código uses: actions/checkout@v4 + with: + fetch-depth: 0 # Necesario para obtener el historial completo de git + + # ------------------------ + # Generar versión automática + # ------------------------ + - name: Generar versión automática + id: version + run: | + # Obtener año y mes actual + YEAR=$(date +%y) + MONTH=$(date +%m) + + # Detectar rama actual usando variables de Gitea + BRANCH="${GITHUB_REF##*/}" + + if [ "$BRANCH" = "development" ]; then + # Para development: YY.MM.1. + SHORT_HASH=$(git rev-parse --short=8 HEAD) + VERSION="${YEAR}.${MONTH}.${{ secrets.VERSION_MAYOR }}.${SHORT_HASH}" + elif [ "$BRANCH" = "main" ]; then + # Para main: YY.MM.0. + # Intentar obtener el último tag + LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") + + if [ -z "$LAST_TAG" ]; then + # No hay tags, usar commit count total (primera ejecución) + COMMIT_COUNT=$(git rev-list --count HEAD) + echo "⚠️ No se encontraron tags. Usando commit count total: ${COMMIT_COUNT}" + else + # Hay tags, contar commits desde el último tag + COMMIT_COUNT=$(git rev-list ${LAST_TAG}..HEAD --count) + # Si es 0, significa que estamos en el mismo commit del tag, incrementar + if [ "$COMMIT_COUNT" -eq 0 ]; then + COMMIT_COUNT=1 + fi + echo "📌 Último tag: ${LAST_TAG}" + echo "🔢 Commits desde el último tag: ${COMMIT_COUNT}" + fi + + VERSION="${YEAR}.${MONTH}.${{ secrets.VERSION_MAYOR }}.${COMMIT_COUNT}" + else + # Fallback para otras ramas + SHORT_HASH=$(git rev-parse --short=8 HEAD) + VERSION="${YEAR}.${MONTH}.99.${SHORT_HASH}" + fi + + # Guardar versión en output para usarla en steps posteriores + echo "VERSION=${VERSION}" >> $GITHUB_OUTPUT + echo "BRANCH=${BRANCH}" >> $GITHUB_OUTPUT + + # Mostrar en logs + echo "📦 Versión generada: ${VERSION}" + echo "🌿 Rama: ${BRANCH}" - name: Login a Harbor run: | @@ -27,6 +81,7 @@ jobs: - name: Build backend run: | docker build \ + --build-arg APP_VERSION=${{ steps.version.outputs.VERSION }} \ -t dev.aduanasoft.com/anexo76/backend:latest \ -f ./backend/Dockerfile \ ./backend @@ -55,6 +110,19 @@ jobs: run: | docker push dev.aduanasoft.com/anexo76/frontend:latest + # ------------------------ + # Crear tag de versión (solo para main) + # ------------------------ + - name: Crear tag de versión + if: github.ref == 'refs/heads/main' + run: | + VERSION=${{ steps.version.outputs.VERSION }} + git config user.name "Gitea Actions" + git config user.email "actions@gitea.local" + git tag -a "v${VERSION}" -m "Release version ${VERSION}" + git push origin "v${VERSION}" + echo "✅ Tag v${VERSION} creado y pusheado" + # ------------------------ # Deploy a Development # ------------------------ diff --git a/backend/Dockerfile b/backend/Dockerfile index 89d5822d..f6253da3 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -2,6 +2,12 @@ FROM python:3.11-slim WORKDIR /app +# ======================================== +# ARG para recibir la versión desde CI/CD +# ======================================== +ARG APP_VERSION="dev" +ENV APP_VERSION=${APP_VERSION} + # Instalar dependencias del sistema RUN apt-get update && apt-get install -y \ gcc \ diff --git a/backend/core/config.py b/backend/core/config.py index 37c5d52f..31919a35 100644 --- a/backend/core/config.py +++ b/backend/core/config.py @@ -2,6 +2,7 @@ Configuración centralizada de la aplicación usando Pydantic Settings """ +import os from typing import List from pydantic_settings import BaseSettings, SettingsConfigDict @@ -12,7 +13,9 @@ class Settings(BaseSettings): # Application APP_NAME: str = "Anexo76" - APP_VERSION: str = "1.0.0" + # La versión se obtiene de la variable de entorno APP_VERSION que se pasa desde Docker + # Si no existe, usa un valor por defecto de desarrollo + APP_VERSION: str = os.getenv("APP_VERSION", "dev-local") DEBUG: bool = True ENVIRONMENT: str = "development" diff --git a/backend/main.py b/backend/main.py index b7ed6b69..ddfb17d5 100644 --- a/backend/main.py +++ b/backend/main.py @@ -77,10 +77,8 @@ async def http_exception_handler(request: Request, exc: HTTPException): def run_migrations(): - subprocess.run( - ["alembic", "upgrade", "head"], - check=True - ) + subprocess.run(["alembic", "upgrade", "head"], check=True) + # Inicializar la base de datos @app.on_event("startup") @@ -132,3 +130,24 @@ async def root(): async def health_check(): """Health check endpoint""" return {"status": "healthy", "environment": settings.ENVIRONMENT} + + +@app.get("/api/version") +async def get_version(): + """ + Endpoint de versión de la aplicación + + Retorna la versión de la aplicación que fue incrustada en la imagen Docker + durante el proceso de CI/CD. La versión se genera automáticamente según la rama: + - development: YY.MM.1. + - main: YY.MM.0. + + Returns: + dict: Información de versión y entorno + """ + return { + "service": settings.APP_NAME, + "version": settings.APP_VERSION, + "environment": settings.ENVIRONMENT, + "debug": settings.DEBUG, + } diff --git a/frontend/src/lib/components/app-version.svelte b/frontend/src/lib/components/app-version.svelte new file mode 100644 index 00000000..8c282936 --- /dev/null +++ b/frontend/src/lib/components/app-version.svelte @@ -0,0 +1,90 @@ + + + +
+ {#if loading} +
Cargando versión...
+ {:else if error} +
Error: {error}
+ {:else if versionInfo} +
+ + + + v{versionInfo.version} + + + + {#if versionInfo.debug} + + DEBUG + + {/if} +
+ {/if} +
diff --git a/frontend/src/lib/components/sidebar/nav-user.svelte b/frontend/src/lib/components/sidebar/nav-user.svelte index 8ec56490..ebf7eee3 100644 --- a/frontend/src/lib/components/sidebar/nav-user.svelte +++ b/frontend/src/lib/components/sidebar/nav-user.svelte @@ -17,6 +17,7 @@ import { goto } from "$app/navigation"; import { browser } from "$app/environment"; import { getBackendAssetUrl } from "$lib/utils"; + import AppVersion from "$lib/components/app-version.svelte"; let { user }: { user: { name: string; email: string; avatar: string } } = $props(); const sidebar = useSidebar(); @@ -172,6 +173,10 @@ Log out + +
+ +