Files
Forge-Engine/.gitea/workflows/deploy.yml
T
williamandClaude Sonnet 5 8e8a159e88
Build and deploy / test-python (push) Failing after 4s
Build and deploy / test-js (push) Successful in 12s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped
Corrige la CI : les jobs de test tournent dans "container" au lieu d'un docker run imbriqué
Le job "test" échouait ("Could not open requirements file:
requirements-dev.txt") : docker run -v "$PWD":/app lancé DEPUIS un
runner qui exécute déjà le job dans son propre conteneur (Docker-
outside-of-Docker) ne peut pas monter "$PWD" — ce chemin vit dans le
conteneur du job, pas sur l'hôte où tourne le vrai démon Docker sollicité
par ce docker run imbriqué ; /app se retrouvait donc vide dans le
conteneur imbriqué.

Corrigé en utilisant la clé "container" (standard Gitea/GitHub Actions) :
le job tourne DIRECTEMENT dans l'image voulue, le checkout dépose les
fichiers dans son propre système de fichiers, aucun montage de volume à
faire. Un seul job "test" ne peut avoir qu'UNE image : scindé en
test-python (python:3.13-slim) et test-js (node:20-slim, pour les tests
node:test de static/js/play/__tests__/), build-and-push dépend des deux.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-30 16:04:10 +02:00

111 lines
4.6 KiB
YAML

name: Build and deploy
on:
push:
branches: [main, dev]
# Le job "test" tourne sur CHAQUE push (main et dev) : jusqu'ici aucune
# étape de CI n'exécutait la suite de tests, rien n'empêchait un commit
# cassé d'atteindre la production (voir l'audit qualité de la Phase 0 du
# plan). "build-and-push"/"deploy", eux, restent réservés à main (via le
# filtre "if" sur gitea.ref) — un push sur dev ne doit jamais redéployer
# la prod, seulement faire tourner les tests.
# Secrets à configurer dans Gitea (Paramètres du dépôt > Actions > Secrets) :
# REGISTRY_HOST adresse du registre d'images (ex: gitea.exemple.com)
# REGISTRY_IMAGE chemin complet de l'image (ex: gitea.exemple.com/mon-compte/forge-engine)
# REGISTRY_USER utilisateur pour "docker login" sur ce registre
# REGISTRY_TOKEN jeton d'accès (scope package:write) pour ce registre
# DEPLOY_HOST adresse du serveur de production
# DEPLOY_USER utilisateur SSH sur ce serveur
# DEPLOY_SSH_KEY clé privée SSH (au format PEM) autorisée sur ce serveur
# DEPLOY_PATH dossier sur le serveur où vit docker-compose.prod.yml (ex: /home/deploy/forge-engine)
#
# Utilise directement docker/ssh/scp en ligne de commande plutôt que des
# actions du marketplace, pour ne pas dépendre de la disponibilité de
# github.com / du miroir gitea.com depuis le runner self-hosted.
jobs:
# Le job tourne DIRECTEMENT dans le conteneur (clé "container", standard
# Gitea/GitHub Actions) plutôt que de lancer un `docker run` imbriqué
# depuis le runner — un essai précédent (docker run -v "$PWD":/app ...)
# échouait avec "Could not open requirements file" : sur un runner qui
# exécute déjà le job dans un conteneur (Docker-outside-of-Docker), "$PWD"
# ne correspond à aucun chemin que le démon Docker de l'HÔTE peut monter,
# /app se retrouvait donc vide dans le conteneur imbriqué. Avec "container",
# le checkout dépose directement les fichiers dans le système de fichiers
# du conteneur du job, aucun montage de volume à faire soi-même.
test-python:
runs-on: ubuntu-latest
container:
image: python:3.13-slim
steps:
- uses: actions/checkout@v4
- name: Installer les dépendances Python (dev)
run: pip install --quiet -r requirements-dev.txt
- name: Tests Python (pytest)
run: python -m pytest tests/ -q
test-js:
runs-on: ubuntu-latest
container:
image: node:20-slim
steps:
- uses: actions/checkout@v4
- name: Tests JS (node:test — logique pure de static/js/play/, voir le plan de modularisation)
run: node --test static/js/play/__tests__/*.test.js
build-and-push:
needs: [test-python, test-js]
if: gitea.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Connexion au registre d'images
run: echo "${{ secrets.REGISTRY_TOKEN }}" | docker login "${{ secrets.REGISTRY_HOST }}" -u "${{ secrets.REGISTRY_USER }}" --password-stdin
- name: Build de l'image
run: |
docker build \
-t "${{ secrets.REGISTRY_IMAGE }}:${{ gitea.sha }}" \
-t "${{ secrets.REGISTRY_IMAGE }}:latest" \
.
- name: Publication de l'image
run: |
docker push "${{ secrets.REGISTRY_IMAGE }}:${{ gitea.sha }}"
docker push "${{ secrets.REGISTRY_IMAGE }}:latest"
deploy:
needs: build-and-push
if: gitea.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Préparation de la clé SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.DEPLOY_SSH_KEY }}" > ~/.ssh/deploy_key
chmod 600 ~/.ssh/deploy_key
ssh-keyscan -H "${{ secrets.DEPLOY_HOST }}" >> ~/.ssh/known_hosts
- name: Envoi du docker-compose.prod.yml sur le serveur
run: |
scp -i ~/.ssh/deploy_key docker-compose.prod.yml \
"${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }}:${{ secrets.DEPLOY_PATH }}/docker-compose.prod.yml"
- name: Pull et redémarrage sur le serveur
run: |
ssh -i ~/.ssh/deploy_key "${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }}" '
set -e
cd "${{ secrets.DEPLOY_PATH }}"
echo "REGISTRY_IMAGE=${{ secrets.REGISTRY_IMAGE }}" > .env
echo "IMAGE_TAG=${{ gitea.sha }}" >> .env
docker login "${{ secrets.REGISTRY_HOST }}" -u "${{ secrets.REGISTRY_USER }}" -p "${{ secrets.REGISTRY_TOKEN }}"
docker compose -f docker-compose.prod.yml pull
docker compose -f docker-compose.prod.yml up -d
docker image prune -f
'