fix(ci): guard concurrency + recuperación de release pending-install en helm-deploy (TENANT-BUILD-NO-CONCURRENCY-GUARD)
Sin guard `concurrency:` múltiples dispatches del repo del tenant corrían helm upgrade en paralelo sobre el mismo release → 'another operation in progress' → release trabado en pending-install → primer deploy nunca completa (vivido E2E 2026-06-10, tenant 9e6babb0). Causa raíz del first-deploy flaky (runs 3418/3419). - concurrency workflow-level (group por repo, cancel-in-progress:false: encola, no cancela — cancelar a mitad de helm install es lo que CREA el pending-install) - step de recuperación: detecta pending-install/uninstalling→uninstall, pending-upgrade/pending-rollback→rollback, antes del helm upgrade. Fail-safe: solo toca estados pending-*, no toca deployed/failed/inexistente. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -18,6 +18,19 @@ on:
|
|||||||
- '.gitea/workflows/__APP_NAME__-build.yaml'
|
- '.gitea/workflows/__APP_NAME__-build.yaml'
|
||||||
workflow_dispatch: {}
|
workflow_dispatch: {}
|
||||||
|
|
||||||
|
# ── Serialización de deploys (TENANT-BUILD-NO-CONCURRENCY-GUARD) ──────────────
|
||||||
|
# Sin este guard, múltiples dispatches del mismo repo (scaffold `on:push` +
|
||||||
|
# tenant-manager fase 1/fase 2 + re-dispatch por rotación de kubeconfig + smoke)
|
||||||
|
# corren `helm upgrade --install` EN PARALELO sobre el MISMO release → Helm aborta
|
||||||
|
# con "another operation (install/upgrade/rollback) is in progress" y deja el
|
||||||
|
# release trabado en `pending-install` → el primer deploy del tenant nunca
|
||||||
|
# completa (vivido E2E 2026-06-10, tenant 9e6babb0; destrabado a mano borrando el
|
||||||
|
# secret del release). Los runs se ENCOLAN, NO se cancelan: cancelar un run a mitad
|
||||||
|
# de `helm install` es justo lo que CREA el estado `pending-install`.
|
||||||
|
concurrency:
|
||||||
|
group: deploy-${{ gitea.repository }}
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
# ── Gate de credenciales de build (GOLDEN-PATH-BUILD-DEPLOY-ORDER-RACE) ───
|
# ── Gate de credenciales de build (GOLDEN-PATH-BUILD-DEPLOY-ORDER-RACE) ───
|
||||||
# Los secrets HARBOR_ROBOT_USER/TOKEN los siembra tenant-manager en su fase 1
|
# Los secrets HARBOR_ROBOT_USER/TOKEN los siembra tenant-manager en su fase 1
|
||||||
@@ -234,6 +247,39 @@ jobs:
|
|||||||
--for=condition=Available \
|
--for=condition=Available \
|
||||||
--timeout=600s
|
--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: |
|
||||||
|
STATUS="$(helm status __APP_NAME__ -n apps 2>/dev/null | sed -n 's/^STATUS: //p')"
|
||||||
|
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
|
- name: Helm upgrade --install
|
||||||
env:
|
env:
|
||||||
TENANT_ID: ${{ vars.TENANT_ID }}
|
TENANT_ID: ${{ vars.TENANT_ID }}
|
||||||
|
|||||||
Reference in New Issue
Block a user