chore(mirror): sync desde templates/rest-api-python (ADR-095)
All checks were successful
__APP_NAME__ — build & deploy / ¿Credenciales de build listas? (push) Successful in 1s
__APP_NAME__ — build & deploy / Calidad + build + push (push) Has been skipped
__APP_NAME__ — build & deploy / ¿Cluster del tenant listo? (push) Has been skipped
__APP_NAME__ — build & deploy / Helm upgrade --install (push) Has been skipped

This commit is contained in:
idp-template-mirror
2026-06-20 01:02:29 +00:00
parent 9bc0d2c020
commit c1cabdc5d2
2 changed files with 192 additions and 92 deletions

View File

@@ -13,6 +13,7 @@ on:
paths:
- 'code/**'
- 'helm/**'
- 'scripts/**'
- '.gitea/workflows/__APP_NAME__-build.yaml'
workflow_dispatch: {}
@@ -204,99 +205,19 @@ jobs:
echo "$KUBECONFIG_B64" | base64 -d > "${HOME}/.kube/config"
chmod 600 "${HOME}/.kube/config"
- name: Esperar rancher-webhook ready (RANCHER-WEBHOOK-RACE-RECOVERY)
# Race condition durante el bootstrap del cluster tenant: el
# `rancher-webhook` Deployment en cattle-system aún no tiene endpoints
# cuando el primer `helm upgrade --install` intenta crear el namespace
# `apps`, lo que dispara el webhook
# `rancher.cattle.io.namespaces.create-non-kubesystem` y aborta el
# release con `no endpoints available for service rancher-webhook`.
# Paridad con el template web-backend (este paso faltaba en rest-api).
run: |
# `kubectl wait` falla con NotFound si el Deployment aún no existe:
# durante el bootstrap del cluster tenant, `rancher-webhook` puede no
# haberse creado todavía cuando corre este step. Primero esperamos a
# que el objeto APAREZCA (poll), luego a que esté Available.
until kubectl get deployment rancher-webhook -n cattle-system >/dev/null 2>&1; do
echo "Esperando a que el Deployment rancher-webhook exista en cattle-system..."
sleep 5
done
kubectl wait deployment rancher-webhook \
-n cattle-system \
--for=condition=Available \
--timeout=600s
- name: Recuperar release Helm atascado (TENANT-BUILD-NO-CONCURRENCY-GUARD)
# Red de seguridad ADEMÁS del guard `concurrency`: si un run previo quedó a
# mitad de una operación Helm (cancelado, runner reiniciado, o carrera
# histórica anterior a este fix), el release queda en un estado `pending-*`
# y el siguiente `helm upgrade --install` aborta. Lo detectamos y recuperamos
# antes de desplegar.
# Fail-safe: SOLO actúa sobre estados `pending-*`/`uninstalling`; un release
# `deployed`, `failed` o inexistente NO se toca. Si el parseo no encuentra
# STATUS (formato inesperado) cae al branch no-op → comportamiento idéntico
# al actual, nunca peor.
run: |
# `helm status` de un release inexistente (first-deploy frío) sale con
# exit≠0; bajo el shell del runner (`bash -e -o pipefail`) eso abortaría
# el step ANTES del case. `|| true` lo neutraliza → STATUS="" → branch no-op.
STATUS="$(helm status __APP_NAME__ -n apps 2>/dev/null | sed -n 's/^STATUS: //p')" || true
echo "Estado actual del release __APP_NAME__: ${STATUS:-<no existe>}"
case "$STATUS" in
pending-install|uninstalling)
# Nunca hubo una revisión desplegada con éxito → no se puede rollback.
# `helm uninstall` limpia el secret del release trabado (equivale al
# destrabado manual del 2026-06-10) sin riesgo de datos: el primer deploy
# aún no levantó la app.
echo "Release en '${STATUS}' (sin revisión estable) → helm uninstall para limpiar."
helm uninstall __APP_NAME__ -n apps --wait --timeout 2m || true
;;
pending-upgrade|pending-rollback)
# Hubo una revisión estable previa → rollback a la última desplegada
# (preserva la app viva; el upgrade siguiente reintenta la nueva imagen).
echo "Release en '${STATUS}' → helm rollback a la última revisión estable."
helm rollback __APP_NAME__ 0 -n apps --wait --timeout 2m || true
;;
*)
echo "Release en estado estable o inexistente → sin recuperación necesaria."
;;
esac
- name: Helm upgrade --install
# ── Deploy del tenant — lógica factorizada a script reusable (ADR-095 §B2-D2) ─
# La secuencia completa del deploy (wait-webhook → recovery-release → helm
# upgrade --install → rollout → smoke) vive en scripts/tenant-first-deploy.sh,
# IDÉNTICO byte-a-byte al de web-backend (fuente única, CS-7). Este template no
# tiene manifests/addonclaim.yaml → el script salta el bloque AddonClaim por
# presencia de archivo. HELM_TIMEOUT=5m preserva el timeout previo de rest-api.
# helm y el kubeconfig ya quedaron listos en los steps previos (setup de entorno).
- name: Deploy del tenant (tenant-first-deploy.sh)
env:
APP_NAME: __APP_NAME__
IMAGE_TAG: ${{ needs.build.outputs.image_tag }}
TENANT_ID: ${{ vars.TENANT_ID }}
TENANT_ID_NODASHES: ${{ vars.TENANT_ID_NODASHES }}
TENANT_TIER: ${{ vars.TENANT_TIER }}
IMAGE_TAG: ${{ needs.build.outputs.image_tag }}
# ADR-054: namespace funcional fijo en cluster tenant — el cluster ya es el sandbox.
run: |
helm upgrade --install __APP_NAME__ ./helm/__APP_NAME__ \
--namespace apps \
--create-namespace \
--set image.tag=${IMAGE_TAG} \
--set tenantId=${TENANT_ID} \
--set tenantIdNodashes=${TENANT_ID_NODASHES} \
--set tier=${TENANT_TIER} \
--wait --timeout 5m
- name: Verificar rollout
run: |
kubectl -n apps rollout status deploy/__APP_NAME__ --timeout=3m
- name: Smoke check post-deploy
# FQDN en formato subdominio (ADR-067 / ADR-082): <app>.<tenant-uuid>.apps...
# Coincide con el host del Ingress del cluster tenant (helm/APP_NAME/values.yaml)
# y con el wildcard A record *.{tenant-uuid}.apps.coralware.cloud que crea tenant-manager.
env:
INGRESS_HOST: __APP_NAME__.${{ vars.TENANT_ID }}.apps.coralware.cloud
run: |
for i in $(seq 1 12); do
if wget -q -O - --timeout=10 "https://${INGRESS_HOST}/health" | grep -q '"status":"ok"'; then
echo "Smoke OK: /health responde 200"
exit 0
fi
echo "Intento ${i}/12 — /health aún no responde, esperando 5s…"
sleep 5
done
echo "ERROR: /health no respondió 200 dentro del timeout"
exit 1
HELM_TIMEOUT: 5m
run: bash scripts/tenant-first-deploy.sh