Update .gitea/workflows/build.yaml
Conservé:
actions/checkout@v3
docker/login-action@v2
docker/build-push-action@v4
Secretos REGISTRY_USER y REGISTRY_PASSWORD
Versionamiento v1.0.${{ github.run_number }}
Imagen versionada y latest
Actualización automática de frontend.yaml
Commit [skip ci]
Timeout de 20 minutos
Las mejoras agregadas son:
Ya no construye imágenes por cambios exclusivos en frontend.yaml, ingress.yaml o patches/.
Elimina integration/ y archivos *.example.tsx únicamente dentro del runner, evitando el error de compilación anterior.
Comprueba que CategoryMenu.tsx, cuando exista:
lea los parámetros actuales de la URL;
contenga collection=Marvel;
contenga category=Mochilas;
esté realmente importado por otro componente, Header o Layout.
Evita que un pipeline antiguo actualice el manifiesto si ya existe un commit más nuevo.
This commit is contained in:
+167
-23
@@ -5,7 +5,29 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
paths:
|
paths:
|
||||||
- 'workloads/ecommerce/**'
|
# Código y configuración real del frontend.
|
||||||
|
# Los cambios exclusivos de GitOps (frontend.yaml, ingress, patches, etc.)
|
||||||
|
# no vuelven a construir la imagen.
|
||||||
|
- 'workloads/ecommerce/Dockerfile'
|
||||||
|
- 'workloads/ecommerce/.dockerignore'
|
||||||
|
- 'workloads/ecommerce/.npmrc'
|
||||||
|
- 'workloads/ecommerce/package.json'
|
||||||
|
- 'workloads/ecommerce/package-lock.json'
|
||||||
|
- 'workloads/ecommerce/next.config.*'
|
||||||
|
- 'workloads/ecommerce/tsconfig.json'
|
||||||
|
- 'workloads/ecommerce/tailwind.config.*'
|
||||||
|
- 'workloads/ecommerce/postcss.config.*'
|
||||||
|
- 'workloads/ecommerce/eslint.config.*'
|
||||||
|
- 'workloads/ecommerce/*.js'
|
||||||
|
- 'workloads/ecommerce/*.mjs'
|
||||||
|
- 'workloads/ecommerce/*.ts'
|
||||||
|
- 'workloads/ecommerce/*.tsx'
|
||||||
|
- 'workloads/ecommerce/app/**'
|
||||||
|
- 'workloads/ecommerce/src/**'
|
||||||
|
- 'workloads/ecommerce/components/**'
|
||||||
|
- 'workloads/ecommerce/lib/**'
|
||||||
|
- 'workloads/ecommerce/public/**'
|
||||||
|
- 'workloads/ecommerce/styles/**'
|
||||||
- '.gitea/workflows/build.yaml'
|
- '.gitea/workflows/build.yaml'
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
@@ -14,20 +36,29 @@ permissions:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
name: Construir y Subir Imagen
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 20 # Aumentamos a 20 min para evitar que se corte el clone
|
timeout-minutes: 20
|
||||||
|
|
||||||
|
env:
|
||||||
|
APP_DIR: workloads/ecommerce
|
||||||
|
MANIFEST_FILE: workloads/ecommerce/frontend.yaml
|
||||||
|
IMAGE_NAME: gitea.cruzcloud.net/devops/ecommerce-frontend
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout del código
|
- name: Checkout del código
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
fetch-depth: 1 # IMPORTANTE: Solo descarga el último commit, no todo el historial
|
fetch-depth: 1
|
||||||
|
persist-credentials: true
|
||||||
|
|
||||||
# 1. NUEVO: Generamos la versión semántica dinámica
|
# Conservamos el esquema estable v1.0.X basado en el número del pipeline.
|
||||||
- name: Definir Versión Semántica
|
- name: Definir Versión Semántica
|
||||||
id: vars
|
id: vars
|
||||||
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
# Formato v1.0.X (X = número de ejecución del pipeline)
|
set -euo pipefail
|
||||||
echo "VERSION=v1.0.${{ github.run_number }}" >> $GITHUB_OUTPUT
|
echo "VERSION=v1.0.${{ github.run_number }}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- name: Validar secretos del Registry
|
- name: Validar secretos del Registry
|
||||||
shell: bash
|
shell: bash
|
||||||
@@ -49,6 +80,76 @@ jobs:
|
|||||||
|
|
||||||
echo "OK: secretos del Registry disponibles."
|
echo "OK: secretos del Registry disponibles."
|
||||||
|
|
||||||
|
# Evita que archivos de ejemplo entren en la compilación de Next.js.
|
||||||
|
# Se eliminan únicamente del workspace temporal del runner.
|
||||||
|
- name: Preparar contexto de producción
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
test -f "${APP_DIR}/Dockerfile"
|
||||||
|
test -f "${APP_DIR}/package.json"
|
||||||
|
test -f "${APP_DIR}/package-lock.json"
|
||||||
|
test -f "${MANIFEST_FILE}"
|
||||||
|
|
||||||
|
rm -rf "${APP_DIR}/integration"
|
||||||
|
|
||||||
|
find "${APP_DIR}" -type f \( -name '*.example.ts' -o -name '*.example.tsx' \) -delete
|
||||||
|
|
||||||
|
echo "Contexto listo:"
|
||||||
|
du -sh "${APP_DIR}"
|
||||||
|
|
||||||
|
# Diagnóstico temprano para el hotfix de navegación.
|
||||||
|
# No modifica el frontend, pero evita publicar silenciosamente un menú
|
||||||
|
# que existe y no está conectado al Header/Layout real.
|
||||||
|
- name: Validar integración del menú de categorías
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
MENU_FILE="$(
|
||||||
|
find "${APP_DIR}" -type f -name 'CategoryMenu.tsx' -print -quit
|
||||||
|
)"
|
||||||
|
|
||||||
|
if [ -z "${MENU_FILE}" ]; then
|
||||||
|
echo "AVISO: no se encontró CategoryMenu.tsx."
|
||||||
|
echo "El build continuará usando el menú actualmente integrado."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "CategoryMenu encontrado: ${MENU_FILE}"
|
||||||
|
|
||||||
|
if ! grep -Eq 'useSearchParams|URLSearchParams|window\.location\.search' "${MENU_FILE}"; then
|
||||||
|
echo "ERROR: CategoryMenu.tsx no deriva el estado activo desde la URL."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! grep -q 'collection=Marvel' "${MENU_FILE}"; then
|
||||||
|
echo "ERROR: falta collection=Marvel para Acción y aventura."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! grep -q 'category=Mochilas' "${MENU_FILE}"; then
|
||||||
|
echo "ERROR: falta category=Mochilas."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
MENU_USAGE="$(
|
||||||
|
grep -Rsl --include='*.tsx' --include='*.ts' 'CategoryMenu' "${APP_DIR}/app" "${APP_DIR}/src" "${APP_DIR}/components" 2>/dev/null |
|
||||||
|
grep -Fvx "${MENU_FILE}" |
|
||||||
|
head -n 1 ||
|
||||||
|
true
|
||||||
|
)"
|
||||||
|
|
||||||
|
if [ -z "${MENU_USAGE}" ]; then
|
||||||
|
echo "ERROR: CategoryMenu.tsx existe, pero ningún Header/Layout lo importa."
|
||||||
|
echo "Debe renderizarse <CategoryMenu /> en el encabezado que ve el usuario."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "CategoryMenu integrado desde: ${MENU_USAGE}"
|
||||||
|
echo "Validación del menú: OK"
|
||||||
|
|
||||||
- name: Login en Gitea Registry
|
- name: Login en Gitea Registry
|
||||||
uses: docker/login-action@v2
|
uses: docker/login-action@v2
|
||||||
with:
|
with:
|
||||||
@@ -57,7 +158,6 @@ jobs:
|
|||||||
password: ${{ secrets.REGISTRY_PASSWORD }}
|
password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||||
logout: true
|
logout: true
|
||||||
|
|
||||||
# 2. ACTUALIZADO: Usamos la nueva variable para los tags de Docker
|
|
||||||
- name: Construir y Subir Imagen
|
- name: Construir y Subir Imagen
|
||||||
uses: docker/build-push-action@v4
|
uses: docker/build-push-action@v4
|
||||||
with:
|
with:
|
||||||
@@ -67,25 +167,69 @@ jobs:
|
|||||||
gitea.cruzcloud.net/devops/ecommerce-frontend:${{ steps.vars.outputs.VERSION }}
|
gitea.cruzcloud.net/devops/ecommerce-frontend:${{ steps.vars.outputs.VERSION }}
|
||||||
gitea.cruzcloud.net/devops/ecommerce-frontend:latest
|
gitea.cruzcloud.net/devops/ecommerce-frontend:latest
|
||||||
|
|
||||||
# 3. ACTUALIZADO: Inyectamos la versión limpia en el manifiesto YAML
|
# Evita que una ejecución antigua actualice frontend.yaml después de que
|
||||||
- name: Actualizar Manifiesto GitOps (CD)
|
# ya exista un commit más reciente en main.
|
||||||
|
- name: Verificar promoción segura
|
||||||
|
id: promotion
|
||||||
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
git fetch origin main
|
||||||
|
|
||||||
|
CURRENT_SHA="${{ github.sha }}"
|
||||||
|
REMOTE_SHA="$(git rev-parse origin/main)"
|
||||||
|
|
||||||
|
echo "Commit del pipeline: ${CURRENT_SHA}"
|
||||||
|
echo "Último commit remoto: ${REMOTE_SHA}"
|
||||||
|
|
||||||
|
if [ "${CURRENT_SHA}" = "${REMOTE_SHA}" ]; then
|
||||||
|
echo "promote=true" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "La imagen puede promocionarse."
|
||||||
|
else
|
||||||
|
echo "promote=false" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "La imagen fue publicada, pero no se actualizará el manifiesto."
|
||||||
|
echo "Existe un commit más reciente y su pipeline debe realizar la promoción."
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Actualizar Manifiesto GitOps (CD)
|
||||||
|
if: steps.promotion.outputs.promote == 'true'
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
VERSION="${{ steps.vars.outputs.VERSION }}"
|
||||||
|
|
||||||
git config user.name "Cristian Felipe"
|
git config user.name "Cristian Felipe"
|
||||||
git config user.email "[email protected]"
|
git config user.email "[email protected]"
|
||||||
|
|
||||||
# 1. Forzamos a Git a ignorar la historia local y sincronizarse 100% con el servidor
|
# Sincronizamos el workspace temporal con main.
|
||||||
|
# No se fuerza ni se sobrescribe la rama remota.
|
||||||
git fetch origin main
|
git fetch origin main
|
||||||
git reset --hard origin/main
|
git checkout -B main origin/main
|
||||||
|
|
||||||
# 2. Aplicamos el cambio de versión
|
sed -i -E "s|(image: ${IMAGE_NAME}:).*|\1${VERSION}|g" "${MANIFEST_FILE}"
|
||||||
sed -i -E "s|(image: gitea.cruzcloud.net/devops/ecommerce-frontend:).*|\1${{ steps.vars.outputs.VERSION }}|g" workloads/ecommerce/frontend.yaml
|
|
||||||
|
git add "${MANIFEST_FILE}"
|
||||||
# 3. Solo hacemos commit si realmente hubo un cambio
|
|
||||||
git add workloads/ecommerce/frontend.yaml
|
|
||||||
if git diff --cached --quiet; then
|
if git diff --cached --quiet; then
|
||||||
echo "No hay cambios en el manifiesto."
|
echo "No hay cambios en el manifiesto."
|
||||||
else
|
exit 0
|
||||||
git commit -m "chore: release ${{ steps.vars.outputs.VERSION }} [skip ci]"
|
fi
|
||||||
# 4. Forzamos el push usando --force para limpiar cualquier discrepancia
|
|
||||||
git push origin HEAD:main --force
|
git commit -m "chore: release ${VERSION} [skip ci]"
|
||||||
fi
|
|
||||||
|
# Push normal: si main cambió durante el job, se detiene para evitar
|
||||||
|
# sobrescribir commits ajenos o promocionar una versión antigua.
|
||||||
|
git push origin HEAD:main
|
||||||
|
|
||||||
|
- name: Resumen del pipeline
|
||||||
|
if: always()
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "========================================"
|
||||||
|
echo "ARI Shopping Frontend"
|
||||||
|
echo "Versión: ${{ steps.vars.outputs.VERSION }}"
|
||||||
|
echo "Commit: ${{ github.sha }}"
|
||||||
|
echo "Promoción GitOps: ${{ steps.promotion.outputs.promote }}"
|
||||||
|
echo "========================================"
|
||||||
Reference in New Issue
Block a user