CI & images
Build/push des images vers ghcr.io et redeploy des stacks Portainer — preprod continue, prod manuelle.
Le déploiement est séparé en deux environnements, tous deux sur Docker Swarm :
- Preprod (continue) —
.github/workflows/deploy-preprod.yml: toutpushsurmaintouchant la plateforme construit les images:latest-preprodet redéploie la stackgrace-preprod. - Prod (manuelle) —
.github/workflows/deploy-prod.yml: déclenché à la main (workflow_dispatch), construit les images:latestet redéploie la stackgrace.
Les deux appellent le même workflow réutilisable .github/workflows/_build-deploy.yml
(build + push des images, puis webhook Portainer) — preprod et prod partagent donc exactement la
même logique de build et ne dérivent jamais.
Déclenchement
| Environnement | Déclencheur | Tag mobile | Stack | Secret webhook |
|---|---|---|---|---|
| Preprod | push sur main (platform/backend|mcp|frontend|docs/**) ou workflow_dispatch | latest-preprod | grace-preprod | PORTAINER_WEBHOOK_URL_PREPROD |
| Prod | workflow_dispatch uniquement | latest | grace | PORTAINER_WEBHOOK_URL_PROD |
Aucun push sur main ne part en prod : seul le déclenchement manuel de deploy-prod le fait.
Matrice d'images
Chaque image est construite en parallèle (matrice), sur un runner self-hosted, avec cache gha :
| Image | Contexte | Dockerfile |
|---|---|---|
grace-backend | . | platform/backend/Dockerfile (build-arg CATALOG_TAG) |
grace-mcp | platform/mcp | platform/mcp/Dockerfile |
grace-frontend | platform/frontend | platform/frontend/Dockerfile (build-args VITE_API_BASE=/api, VITE_DOCS_BASE) |
grace-docs | platform/docs | platform/docs/Dockerfile (site Fumadocs, Next standalone) |
VITE_DOCS_BASE est baké au build et diffère selon l'environnement :
https://docs-preprod.grace.hoppr.tech en preprod, https://docs.grace.hoppr.tech en prod.
Chaque image est taguée par son tag mobile d'environnement et sha-<sha> :
ghcr.io/hoppr-tech/grace-<name>:latest-preprod # ou :latest en prod
ghcr.io/hoppr-tech/grace-<name>:sha-<github.sha>Redeploy
Une fois les images poussées, le job redeploy déclenche le webhook Portainer de la stack
cible (PORTAINER_WEBHOOK_URL_PREPROD ou PORTAINER_WEBHOOK_URL_PROD, secrets repo) : la stack
re-pull les images. Si le secret n'est pas défini, le redeploy est ignoré (warning).
Release (prod)
Après un déploiement prod sain, deploy-prod coupe aussi une release (job release,
needs: prod) : git-cliff calcule la version depuis les commits conventionnels (cliff.toml),
crée le tag + la GitHub Release et annonce sur Slack (SLACK_WEBHOOK_URL). Passer l'input
cut_release=false pour redéployer :latest sans couper de version (ex. re-pull après un
correctif infra, sans nouveau commit releasable).
Service de documentation
Le site de documentation est servi par le service docs de chaque stack, exposé via Traefik
(docs.grace.hoppr.tech en prod, docs-preprod.grace.hoppr.tech en preprod) :
traefik.http.routers.grace-docs.rule=Host(`docs.grace.hoppr.tech`)
traefik.http.routers.grace-docs.entrypoints=websecure
traefik.http.routers.grace-docs.tls.certresolver=letsencrypt
traefik.http.services.grace-docs.loadbalancer.server.port=3000Le site est public pour l'instant. Pour le restreindre à une identité Google, ajouter le middleware partagé
google-auth(traefik.http.routers.grace-docs.middlewares=google-auth) une fois le client OAuth Google configuré avec le bonredirect_uripourdocs.grace.hoppr.tech.