# Del commit al despliegue: flujo GitOps El diagrama de abajo refleja el pipeline real (build → push imagen → promoción segura → commit del tag → sync de Argo CD). Después del diagrama hay un ejemplo con hashes de commit reales, tomado de un cambio real hecho sobre este mismo repo. ## Secuencia: un commit hasta quedar corriendo en el cluster ```mermaid sequenceDiagram actor Dev as Devops participant Gitea participant CI as Gitea Actions participant Reg as Gitea Registry participant Argo as Argo CD participant K8s as Cluster k3d Dev->>Gitea: push a fix/ Dev->>Gitea: abre PR → main Gitea->>Gitea: merge a main Gitea->>CI: dispara workflow (paths: workloads/**) CI->>CI: build de la imagen (Docker) CI->>Reg: push imagen vX.Y.Z CI->>CI: verifica promoción segura (HEAD == origin/main) CI->>Gitea: commit "chore(gitops): release vX.Y.Z" actualizando el manifiesto Argo->>Gitea: detecta el nuevo commit (poll/webhook) Argo->>K8s: sync (prune:true, selfHeal:true) K8s->>K8s: rollout del nuevo pod ``` ## Por qué esta separación (build vs. deploy) - El **pipeline de CI** solo construye y publica la imagen — nunca aplica nada directo al cluster. - El **commit al manifiesto** (`sed` sobre el tag de imagen) es lo único que representa "intención de desplegar" — y vive en el mismo repo Git que Argo CD vigila. - **Argo CD** es la única pieza con permisos de escritura sobre el cluster real. Nada fuera de GitOps toca `kubectl apply` en producción. - El paso de "promoción segura" (comparar `HEAD` contra `origin/main`) evita que un pipeline viejo sobreescriba el tag con una versión anterior si hubo un push más reciente mientras corría. ## Ejemplo real: un commit de principio a fin Fase 3b del ADR 0006 (facetas del sidebar del catálogo, ver `decisiones/0006-motor-busqueda-facetas.md`) recorrió el flujo completo dos veces seguidas el mismo día: | Paso | Commit / evento real | |---|---| | Feature | `83d448b` — `feat(ecommerce): facetas reales de Meilisearch en el sidebar del catalogo`, en `fix/adr0006-etapa2-fase3b-facetas-sidebar` | | Merge a `main` | `6b5450f` | | CI build+push | Gitea Actions task 258, imagen `gitea.cruzcloud.net/devops/ecommerce-frontend` | | Release commit (CD) | `951682a` — `chore: release v1.0.171 [skip ci]`, bump automático del tag en `frontend/patches/deployment.yaml` | | Sync de Argo CD | dos ciclos distintos: primero sincronizó contra `6b5450f` (el merge, todavía con el tag viejo), y en el ciclo siguiente detectó `951682a` y aplicó el tag nuevo | | Rollout | `frontend-deploy` con 2/2 réplicas en `v1.0.171` | El gate en vivo contra ese mismo cambio encontró un bug real (`estimatedTotalHits` en 0 con `limit=0` en Meilisearch) — el fix repitió el mismo ciclo completo: `884dbd1` → merge `ba3e6c7` → release `v1.0.172` → sync → rollout. Dos vueltas completas del diagrama de arriba en la misma sesión, cada una verificada contra el endpoint real antes de darla por cerrada. **Detalle no obvio:** Argo CD sincroniza el *merge commit* primero (todavía con la imagen vieja, porque el bump de tag es un commit *posterior* que hace el propio pipeline) y recién en un segundo ciclo de poll detecta el commit de release. Son dos sincronizaciones distintas, no una sola — hay que esperar ambas antes de asumir que el pod nuevo está corriendo. ## `selfHeal`, con la configuración real Todas las Applications de este repo comparten el mismo `syncPolicy` (`apps/ecommerce-app.yaml`): ```yaml syncPolicy: automated: prune: true selfHeal: true ``` Con `selfHeal: true`, si alguien corre `kubectl scale deployment frontend-deploy --replicas=1` directo contra el cluster (saltándose Git por completo), Argo CD no se queda en mostrar `OutOfSync` — en el siguiente ciclo de reconciliación vuelve a aplicar el manifiesto tal como está en `main` y el Deployment queda otra vez en las réplicas declaradas ahí. El cambio manual no se pierde silenciosamente: queda un instante como drift visible en la UI de Argo CD, pero nunca se vuelve el estado final. La única forma de que ese cambio persista es que exista en Git — lo mismo que describe [ADR 0002](../decisiones/0002-por-que-argocd-vs-manual.md).