CI/CD : Forgejo Actions (pas GitLab - le dépôt vit sur Forgejo)
All checks were successful
CI / build-and-test (push) Successful in 2m34s
CI / deploy (push) Successful in 3m8s

- .forgejo/workflows/ci.yml : build + test cargo (workspace), build npm
  (app/) sur toute PR/push ; déploiement (main uniquement) : build
  release, scp + redémarrage systemd sur tripoli-edge et tripoli-api.
- Runner Forgejo Actions déployé en systemd (aucun n'existait avant) :
  socket Docker de l'hôte partagé avec les conteneurs de job plutôt
  qu'un docker:dind imbriqué et privilégié - plus léger sur une machine
  déjà partagée.
- Déploiement via un compte système "deploy" sans privilège : peut
  seulement déposer un binaire dans /opt/deploy-staging et lancer un
  script sudo dédié qui n'accepte que "tripoli-edge" ou "tripoli-api"
  comme argument. Aucune clé root dans le pipeline. Clé SSH de
  déploiement générée sur le serveur, jamais passée par cette
  conversation - stockée directement comme secret Forgejo Actions par
  l'utilisateur.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Adam Belkacemi 2026-09-17 13:30:36 +02:00
parent 7802c59931
commit c6aa75ba39
4 changed files with 143 additions and 0 deletions

45
ci/README.md Normal file
View file

@ -0,0 +1,45 @@
# CI/CD
Le brief demandait un `.gitlab-ci.yml`, mais ce dépôt vit sur **Forgejo**,
pas GitLab (voir le README racine) : l'équivalent réel est un workflow
**Forgejo Actions** (`.forgejo/workflows/ci.yml`), syntaxe compatible
GitHub Actions.
## Runner
Aucun runner Forgejo Actions n'existait sur ce serveur avant cette
phase. Déployé en systemd (`forgejo-runner.service`), conteneur
`code.forgejo.org/forgejo/runner:13.1`, socket Docker de l'hôte partagé
avec les conteneurs de job (`docker_host: "automount"` dans sa config)
plutôt qu'un `docker:dind` imbriqué et privilégié - plus léger sur une
machine à 3.7 Go déjà partagée, au prix d'une isolation plus faible
(un job de CI a accès au docker de l'hôte). Acceptable ici : instance
Forgejo mono-utilisateur, pas un service ouvert à des tiers.
## Déploiement : un compte dédié, pas root
Le pipeline ne se connecte jamais en root. Un utilisateur système
`deploy` existe uniquement pour :
1. recevoir le binaire compilé par `scp` dans `/opt/deploy-staging/` ;
2. lancer `sudo /usr/local/sbin/tripoli-deploy.sh <service>` - un
script sudo dédié (voir `/etc/sudoers.d/deploy` sur le serveur) qui
n'accepte que `tripoli-edge` ou `tripoli-api` comme argument, installe
le binaire à l'emplacement attendu et redémarre exactement ce
service. Rien d'autre n'est accessible via ce compte.
La clé privée correspondante est stockée comme secret Forgejo Actions
(`DEPLOY_SSH_KEY`), jamais dans ce dépôt.
## Workflow (`.forgejo/workflows/ci.yml`)
- `build-and-test` (toute PR et push) : installe Rust via rustup
(l'image du job, `node:20-bookworm`, a un rustc système trop ancien
pour ce code), `cargo build --workspace`, `cargo test --workspace`,
puis `npm ci && npm run build` pour le frontend.
- `deploy` (uniquement sur `main`, après succès du job précédent) :
build release, puis dépôt + redémarrage de `tripoli-edge` et
`tripoli-api` via le compte `deploy`.
`tripoli-netctl` et le labo `bird-lab` ne sont pas déployés par ce
pipeline : ce sont des outils de labo qu'on lance à la main, pas des
services qui tournent en continu.

24
ci/forgejo-runner.service Normal file
View file

@ -0,0 +1,24 @@
[Unit]
Description=forgejo-runner - runner Forgejo Actions pour tripoli.cloud
After=docker.service
Requires=docker.service
[Service]
Type=simple
Restart=on-failure
RestartSec=5
# --group-add : le gid du groupe "docker" sur l'hôte (docker.sock lui
# appartient) - sans ça, le processus (uid 1001, sans privilège) n'a
# pas le droit de s'en servir, même monté dans le conteneur.
ExecStart=/usr/bin/docker run --rm \
--name forgejo-runner \
--user 1001:1001 \
--group-add 983 \
-v /opt/forgejo-runner/data:/data \
-v /var/run/docker.sock:/var/run/docker.sock \
code.forgejo.org/forgejo/runner:13.1 \
forgejo-runner daemon --config /data/config.yml
ExecStop=/usr/bin/docker stop forgejo-runner
[Install]
WantedBy=multi-user.target