From db71cc92ee8b5c3c7453567f4f2fb43da6162f79 Mon Sep 17 00:00:00 2001 From: tristan Date: Mon, 6 Apr 2026 15:12:17 +0200 Subject: [PATCH] docs : spec phase 2a deploiement de version et versions disponibles Co-Authored-By: Claude Opus 4.6 (1M context) --- ...26-04-06-phase2a-deploy-versions-design.md | 155 ++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 docs/superpowers/specs/2026-04-06-phase2a-deploy-versions-design.md diff --git a/docs/superpowers/specs/2026-04-06-phase2a-deploy-versions-design.md b/docs/superpowers/specs/2026-04-06-phase2a-deploy-versions-design.md new file mode 100644 index 0000000..ff01b54 --- /dev/null +++ b/docs/superpowers/specs/2026-04-06-phase2a-deploy-versions-design.md @@ -0,0 +1,155 @@ +# Phase 2a — Deploiement de version + Versions disponibles + +## Contexte + +Central gere les applications du SI Malio. La phase 1 a mis en place le CRUD des applications et environnements en BDD. Cette phase ajoute la capacite de deployer une version sur un environnement et de lister les versions disponibles sur le registry Gitea. + +Chaque app a un `deploy.sh` qui prend un tag en argument, pull l'image Docker, lance les migrations, et gere le mode maintenance. Le script tourne sur la machine host. Central tourne en Docker et accede au host via le socket Docker monte. + +## Architecture + +### Variable d'environnement + +`GITEA_API_TOKEN` : token global Gitea avec acces lecture aux packages. Configure dans `.env` (backend Symfony). Non stocke en BDD. + +`GITEA_API_URL` : URL de base de l'API Gitea (ex: `https://gitea.malio.fr`). Configure dans `.env`. + +### Service GiteaRegistryService + +Classe PHP dans `src/Service/GiteaRegistryService.php`. + +Responsabilite : appeler l'API Gitea pour lister les tags d'une image container. + +API Gitea : `GET {GITEA_API_URL}/api/v1/packages/{owner}/container/{package}` avec header `Authorization: token {GITEA_API_TOKEN}`. + +- Input : `registryImage` de l'Application (ex: `gitea.malio.fr/malio-dev/sirh`) — on extrait `owner` (`malio-dev`) et `package` (`sirh`) depuis cette string. +- Output : liste de tags tries par date de creation (plus recent en premier), chaque tag avec son nom et sa date. +- Gestion d'erreur : si l'API est inaccessible ou le token invalide, renvoyer une erreur claire. + +### Service DeployService + +Classe PHP dans `src/Service/DeployService.php`. + +Responsabilite : executer le script de deploy d'un environnement. + +- Input : entite `Environment` + tag a deployer +- Execute `deployScriptPath` avec le tag en argument via `Symfony\Component\Process\Process` +- Timeout : 300 secondes (5 min max pour un deploy) +- Capture stdout + stderr +- Output : objet avec `success` (bool), `output` (string), `exitCode` (int) + +Le process tourne dans le container Central. Le `deploy.sh` est accessible car les dossiers des apps sont montes dans le container. Le script utilise `docker compose` qui fonctionne grace au socket Docker monte. + +### Endpoints API + +| Route | Methode | Description | Securite | +|-------|---------|-------------|----------| +| `GET /api/applications/{slug}/tags` | GET | Liste les tags disponibles sur le registry Gitea | ROLE_ADMIN | +| `POST /api/environments/{id}/deploy` | POST | Lance un deploy, body: `{ "tag": "v1.2.3" }` | ROLE_ADMIN | + +#### GET /api/applications/{slug}/tags + +Provider custom `TagListProvider` dans `src/State/`. +- Charge l'Application par slug +- Appelle `GiteaRegistryService` avec le `registryImage` +- Retourne la liste des tags + +Response : +```json +{ + "tags": [ + { "name": "v1.2.3", "date": "2026-04-05T10:00:00Z" }, + { "name": "v1.2.2", "date": "2026-04-01T08:00:00Z" }, + { "name": "latest", "date": "2026-04-05T10:00:00Z" } + ] +} +``` + +#### POST /api/environments/{id}/deploy + +Processor custom `DeployProcessor` dans `src/State/`. +- Charge l'Environment par id +- Valide que le tag est fourni +- Appelle `DeployService` +- Retourne le resultat + +Response succes : +```json +{ + "success": true, + "output": "==> Deploying sirh:v1.2.3...\n...\n==> Deployed v1.2.3", + "tag": "v1.2.3" +} +``` + +Response echec : +```json +{ + "success": false, + "output": "Error: ...", + "tag": "v1.2.3" +} +``` + +### Docker + +#### docker-compose.yml (dev) + +Ajouter au service `php` : +```yaml +volumes: + - /var/run/docker.sock:/var/run/docker.sock +``` + +Note : en dev les deploy.sh ne sont pas forcement accessibles depuis le container (chemins host). Le deploy ne fonctionnera pleinement qu'en prod. En dev on peut tester la liste des tags et le mecanisme, mais le deploy lui-meme pourra echouer (script introuvable). C'est acceptable. + +#### docker-compose.yml (prod) + +Ajouter au service `app` : +```yaml +volumes: + - /var/run/docker.sock:/var/run/docker.sock + - /var/www/sirh/deploy:/var/www/sirh/deploy:ro + - /var/www/lesstime/deploy:/var/www/lesstime/deploy:ro + - /var/www/inventory/deploy:/var/www/inventory/deploy:ro +``` + +Le socket Docker + les dossiers deploy montes en read-only (le deploy.sh est execute, pas modifie). Le script execute `docker compose` qui passe par le socket. + +Installer `docker-cli` dans le Dockerfile prod pour que les commandes `docker compose` fonctionnent depuis le container. + +### Frontend + +#### Modal de deploy + +Sur la page detail (`/applications/{slug}`), chaque environnement affiche un bouton "Deployer". + +Clic sur "Deployer" → ouvre une modal `AppModal` avec : +- Un select (ou liste) des tags disponibles, charges depuis `GET /api/applications/{slug}/tags` +- Loading skeleton pendant le chargement des tags +- Bouton "Deployer" qui POST sur `/api/environments/{id}/deploy` +- Pendant le deploy : le bouton passe en loading, on attend la reponse +- A la fin : affichage du resultat dans la modal + - Succes : message vert + output du script dans un bloc `
`
+  - Echec : message rouge + output du script dans un bloc `
`
+
+#### Service frontend
+
+`frontend/services/deploy.ts` :
+- `getAvailableTags(slug: string)` : GET les tags
+- `deploy(envId: number, tag: string)` : POST le deploy
+
+`frontend/services/dto/deploy.ts` :
+- Type `Tag` : `{ name: string, date: string }`
+- Type `DeployResult` : `{ success: boolean, output: string, tag: string }`
+
+#### i18n
+
+Nouvelles cles dans `fr.json` pour la modal de deploy (titre, select, boutons, messages succes/echec).
+
+## Hors scope
+
+- Streaming temps reel du log de deploy
+- Historique des deployments
+- Rollback
+- Version actuellement deployee (affichage)