Files
Infra/CI-CD.md
T

7.3 KiB

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.31.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.31.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 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