ADR-0014 : Provisioning GitOps CI-driven et cycle de vie complet des apps¶
Statut¶
Accepted - Date : 2026-06-09 - Ticket : 4K-59
Contexte¶
Avant ce changement, le provisioning ArgoCD (création des manifestes argocd/<app>/ et des values apps/<app>/ dans cnp-gitops) était effectué par le backend Python au moment du scaffold, via backend/gitops/provisioner.py appelé dans app_service.py.
Cela créait une race condition systématique : ArgoCD découvrait l'application immédiatement après le commit d'injection CI, avec image.tag: none, avant que la première image Docker soit buildée. Résultat : ImagePullBackoff immédiat, nécessitant une intervention manuelle (resync ArgoCD après le premier build).
Par ailleurs, la suppression d'une app ne nettoyait que la base de données — les manifestes ArgoCD et le projet GitLab scaffoldé restaient orphelins.
Décision¶
1. Provisioning déplacé dans la CI (update-gitops idempotent)¶
Le job update-gitops de cnp-ci-modules est rendu idempotent : à chaque exécution, il crée les fichiers argocd/<app>/<env>.yaml et apps/<app>/values-<env>.yaml dans cnp-gitops s'ils n'existent pas encore, puis met à jour le tag image.
ArgoCD ne découvre donc l'application qu'après le premier run de update-gitops, qui ne s'exécute lui-même qu'après le push Docker. La race condition est structurellement impossible.
Ce mécanisme remplace provisioner.py, qui est supprimé.
2. Scoping du tag par branche¶
Le job update-gitops provisionne toujours les deux environnements (dev et prod) pour garantir que les manifestes ArgoCD existent dès le premier CI, mais n'écrit le tag image que dans l'environnement correspondant à la branche :
main/master→ mise à jour devalues-prod.yamlrelease-dev-*→ mise à jour devalues-dev.yaml
3. skip_first_deploy inchangé dans son effet¶
L'option skip_first_deploy au scaffold contrôle toujours le message du commit d'injection :
false(défaut) →"ci: inject CNP pipeline"→ CI s'exécute →update-gitopsprovisionne + déploietrue→"ci: inject CNP pipeline [skip ci]"→ CI skippée → ArgoCD ne découvre pas l'app jusqu'au prochain push manuel
4. Suppression enrichie¶
L'endpoint DELETE /api/v1/apps/{id} effectue désormais trois opérations en séquence :
- Cleanup GitOps : supprime
argocd/<app>/etapps/<app>/danscnp-gitopsvia l'API Commits GitLab (atomic) - Suppression du projet GitLab : uniquement si
origin = scaffolded(les repos importés ne sont pas supprimés) - Suppression en base
Les échecs des étapes 1 et 2 sont loggués mais n'empêchent pas la suppression en base — l'app disparaît du portail même en cas d'artefact GitLab orphelin.
Conséquences¶
Positif : - Race condition ImagePullBackoff éliminée structurellement — ArgoCD ne voit l'app que quand une image valide existe - Suppression propre : pas de manifestes ni de repos orphelins après delete - provisioner.py supprimé — moins de surface de code, responsabilité CI/backend mieux délimitée - Le provisioning est rejoué automatiquement si cnp-gitops est en retard ou corrompu (idempotent)
Négatif / Dette : - apk add yq installé à l'exécution dans update-gitops (réseau APK requis) — à bake dans une image cnp-ci-tools dédiée (prévu) - Les échecs de cleanup GitLab/GitOps sont silencieux côté utilisateur — amélioration UX prévue (retour d'état dans la réponse DELETE) - Le provisioning ne se déclenche que sur main et release-dev-* (règles du job update-gitops) — un scaffold suivi d'un push sur une autre branche ne provisionne pas ArgoCD
Références¶
- ADR-0005 : délimitation CI / GitOps
- ADR-0011 : injection CI et comportement
skip_first_deploy