# CI/CD — Pipelines Gitea Actions Bonsai API et Bonsai Webapp disposent chacune de trois workflows Gitea Actions : `ci.yml`, `release.yml` et `rollback.yml`. **Luz** dispose d'un workflow `release.yml` à déclencheur automatique sur `main`. Le runner Gitea s'exécute sur le même serveur que les applications et a accès direct au socket Docker (`/var/run/docker.sock`), ce qui lui permet de piloter les conteneurs sans passer par SSH. --- ## Workflow CI (`ci.yml`) **Déclencheur** : tout `push` sur n'importe quelle branche, et toute pull request vers `main`. ### Bonsai API | Étape | Ce qu'elle fait | |---|---| | **Checkout** | Clone le dépôt | | **Cache Java 25** | Vérifie si le JDK est déjà présent dans le cache du runner. Si oui, le téléchargement est sauté (~11 min économisées) | | **Install Java 25** | *(seulement si cache absent)* Télécharge et extrait le JDK 25 (Temurin, build Alpine) dans `/opt/` | | **Set up Java 25** | Exporte `JAVA_HOME` et ajoute le JDK au `PATH` pour les étapes suivantes | | **Run tests** | Lance `./gradlew test` — la suite de tests échoue le workflow si un test est rouge | | **Upload test report** | *(seulement en cas d'échec)* Publie le rapport HTML de Gradle comme artifact téléchargeable dans l'interface Gitea | ### Bonsai Webapp | Étape | Ce qu'elle fait | |---|---| | **Checkout** | Clone le dépôt | | **Setup Node.js** | Installe Node.js 22 et active le cache npm automatique | | **Install dependencies** | Lance `npm ci` pour une installation reproductible (utilise le cache npm si disponible) | | **Run tests with coverage** | Lance `npm test -- --watch=false` — exécute Vitest avec rapport de couverture | --- ## Workflow Release (`release.yml`) **Déclencheur** : publication d'une release Gitea (bouton "Publish release" sur un tag `vX.Y.Z`). ### Bonsai API | Étape | Ce qu'elle fait | |---|---| | **Checkout** | Clone le dépôt avec l'historique complet (`fetch-depth: 0`) — nécessaire pour le merge vers `main` | | **Cache Java 25** | Même logique que le CI | | **Install Java 25** | *(si cache absent)* Installe le JDK | | **Set up Java 25** | Configure `JAVA_HOME` et `PATH` | | **Bump version in build.gradle** | Remplace la version dans `build.gradle` par le tag de la release (ex. `v1.2.3` → `1.2.3`). Modification locale uniquement, non commitée | | **Build JAR** | Lance `./gradlew build -x test` pour produire le JAR avec la bonne version. Les tests sont skippés (déjà passés en CI) | | **Set up Docker Buildx** | Active Buildx pour le build multi-plateforme avec support du cache registry | | **Login to Gitea registry** | Authentifie le runner sur `git.goutailler-olivier.com` avec le token `RELEASE_TOKEN` | | **Set lowercase repo name** | Normalise le nom du repo en minuscules (requis par Docker) | | **Build and push** | Build l'image Docker et la pousse avec deux tags : `vX.Y.Z` (archive) et `latest` (production). Utilise le cache registry pour accélérer les builds suivants | | **Backup database before deployment** | Via le socket Docker, exécute `pg_dump` dans le conteneur `bonsai-api-db` et sauvegarde le dump compressé dans `/opt/backups/bonsai-api/`. **Bloque le déploiement si le backup échoue.** Conserve les 10 derniers backups | | **Trigger production deployment** | Appelle le webhook Watchtower — Watchtower détecte la nouvelle image `:latest` et redémarre le conteneur API | | **Merge release to main** | Restore `build.gradle` (pour annuler la modification locale), puis merge la branche de release dans `main` avec un commit de merge `--no-ff` | | **Bump version to next SNAPSHOT on develop** | Incrémente le patch sur `develop` (ex. `1.2.3` → `1.2.4-SNAPSHOT`) et pousse le commit | ### Bonsai Webapp | Étape | Ce qu'elle fait | |---|---| | **Checkout** | Clone le dépôt | | **Set up Docker Buildx** | Active Buildx avec cache registry | | **Login to Gitea registry** | Authentifie le runner | | **Set lowercase repo name** | Normalise le nom du repo | | **Bump version in package.json** | Met à jour le champ `version` dans `package.json` avec le tag de release | | **Build and push** | Build l'image Docker (inclut le `npm run build` via le Dockerfile) et pousse `vX.Y.Z` + `latest` | | **Trigger production deployment** | Appelle le webhook Watchtower | | **Merge release to main** | Merge la branche de release dans `main` | | **Bump version to next SNAPSHOT on develop** | Incrémente le patch sur `develop` dans `package.json` | --- ## Workflow Rollback (`rollback.yml`) **Déclencheur** : manuel via **Actions → Rollback → Run workflow** dans l'interface Gitea. **Paramètres** : - `version` *(obligatoire)* — version cible, ex. `v1.2.3` - `restore_db` *(API seulement, défaut : `no`)* — `yes` pour restaurer aussi la base de données | Étape | Ce qu'elle fait | |---|---| | **Login to Gitea registry** | Authentifie le runner sur le registry | | **Set lowercase repo name** | Normalise le nom du repo | | **Retag version as latest** | Pull l'image `vX.Y.Z`, la retague en `latest` et la repousse — Watchtower déploiera cette version | | **Restore database backup** | *(si `restore_db=yes`)* Arrête le conteneur API, supprime et recrée la base de données, restaure le dump compressé correspondant à la version cible depuis `/opt/backups/bonsai-api/` | | **Trigger production deployment** | Appelle le webhook Watchtower pour redéployer avec l'image rétrogradée | > **Voir aussi** : [Mise à jour des applications](Mise-a-jour-Applications) pour la procédure de rollback complète et la gestion des backups. --- ## Workflow Release Luz (`release.yml`) **Déclencheur** : tout `push` sur `main`. **Versionnage automatique** : le workflow lit le dernier tag `vX.Y.Z`, incrémente le patch (`Z+1`) et crée un nouveau tag. Si aucun tag n'existe, démarre à `v0.1.0`. | Étape | Ce qu'elle fait | |---|---| | **Tests & couverture** | *(job `test`)* Lance `npm ci` puis `npm test -- --watch=false` — bloque la release si les tests échouent | | **Checkout** | Clone avec `fetch-depth: 0` pour récupérer tous les tags | | **Calculate next version** | Calcule le prochain tag en incrémentant le patch du dernier tag | | **Bump version in package.json** | Met à jour le champ `version`, commite et pousse sur `main` | | **Set up Docker Buildx** | Active Buildx avec cache registry | | **Login to Gitea registry** | Authentifie le runner sur `git.goutailler-olivier.com` avec `RELEASE_TOKEN` | | **Build and push** | Build l'image Docker et pousse `vX.Y.Z` + `latest` avec cache registry | | **Create Gitea release** | Crée la release sur Gitea via l'API avec le tag calculé | --- ## Secrets requis | Secret | Utilisé par | Rôle | |---|---|---| | `RELEASE_TOKEN` | `release.yml`, `rollback.yml` | Token Gitea avec accès en écriture au registry et au dépôt (push sur `main` et `develop`) | | `WATCHTOWER_TOKEN` | `release.yml`, `rollback.yml` | Token Bearer pour l'API HTTP de Watchtower | --- ## Infrastructure du runner Le runner (`gitea-runner`) est configuré dans `Infra/gitea/gitea-compose.yml` avec : - **Label** `ubuntu-latest:host` — les jobs s'exécutent directement dans le conteneur runner - **Socket Docker monté** (`/var/run/docker.sock`) — accès direct aux conteneurs de l'hôte sans SSH - **Dossier backups monté** (`/opt/backups`) — les backups écrits par le runner sont persistés sur l'hôte