diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index 2096e51..fb1ed48 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -1,4 +1,4 @@ -name: Build & Deploy +name: Deploy via Portainer on: push: @@ -8,32 +8,11 @@ jobs: deploy: runs-on: self-hosted steps: - - name: Checkout + - name: Trigger Portainer stack redeploy run: | - git config --global --add safe.directory "$GITHUB_WORKSPACE" - if [ -d "$GITHUB_WORKSPACE/.git" ]; then - git -C "$GITHUB_WORKSPACE" fetch --all - git -C "$GITHUB_WORKSPACE" reset --hard "$GITHUB_SHA" - else - git clone "http://192.168.5.171:3000/$GITHUB_REPOSITORY.git" "$GITHUB_WORKSPACE" - git -C "$GITHUB_WORKSPACE" checkout "$GITHUB_SHA" + HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X POST "${{ secrets.PORTAINER_WEBHOOK }}") + if [ "$HTTP_CODE" != "200" ] && [ "$HTTP_CODE" != "204" ]; then + echo "Portainer webhook failed (HTTP $HTTP_CODE)" + exit 1 fi - - - name: Build image - run: docker build -t 3d-pricing:latest "$GITHUB_WORKSPACE" - - - name: Redeploy - run: | - docker rm -f 3d-pricing 2>/dev/null || true - docker run -d \ - --name 3d-pricing \ - --restart unless-stopped \ - -p 5010:5000 \ - -v /opt/3d-pricing-data:/data \ - -e DATABASE_PATH=/data/pricing.db \ - 3d-pricing:latest - - - name: Healthcheck - run: | - sleep 5 - curl -f http://localhost:5010/ || (echo "App not responding!" && exit 1) + echo "Redeploy triggered (HTTP $HTTP_CODE)" diff --git a/DEPLOY.md b/DEPLOY.md new file mode 100644 index 0000000..1881ee0 --- /dev/null +++ b/DEPLOY.md @@ -0,0 +1,205 @@ +# Déploiement — Git + Portainer + CI/CD + +## Vue d'ensemble + +``` +PC (WSL) → git push → Gitea (192.168.5.171:3000) + ↓ webhook (Gitea Actions) + Act Runner (serveur Portainer) + ↓ curl webhook + Portainer → git pull → docker compose up --build + ↓ + Conteneur 3d-pricing (port 5010) +``` + +--- + +## 1. Git — initialiser et pousser le code + +Depuis WSL sur ton PC : + +```bash +cd /mnt/c/Users/jbper/Claude/3d-pricing + +# Init git si pas encore fait +git init +git branch -M main + +# Connecter au repo Gitea (créer le repo vide sur Gitea d'abord) +git remote add origin http://192.168.5.171:3000/TON_USER/3d-pricing.git + +# Premier push +git add -A +git commit -m "init: 3d-pricing app" +git push -u origin main +``` + +> Créer le repo sur Gitea : **+ → New Repository** → nom `3d-pricing` → ne pas cocher "Initialize" + +--- + +## 2. Gitea Actions — activer + +### 2a. Activer dans app.ini + +```bash +# Trouver app.ini dans le conteneur Gitea +docker exec gitea find / -name app.ini 2>/dev/null + +# Éditer (exemple si monté en volume) +# Ajouter dans app.ini : +[actions] +ENABLED = true +``` + +Redémarrer : +```bash +docker restart gitea +``` + +### 2b. Activer sur le repo + +Gitea → ton repo → **Settings → General → cocher "Actions"** → Save + +### 2c. Récupérer un token runner + +Gitea → **Site Administration (clé à molette) → Actions → Runners → Create new Runner** + +Copier le **Registration Token**. + +--- + +## 3. Act Runner — déployer sur le serveur Portainer + +Sur le **serveur Portainer** : + +```bash +mkdir -p /opt/gitea-act-runner +cd /opt/gitea-act-runner + +# Créer docker-compose.yml +cat > docker-compose.yml << 'EOF' +services: + runner: + image: gitea/act_runner:latest + container_name: gitea-act-runner + restart: unless-stopped + environment: + - GITEA_INSTANCE_URL=http://192.168.5.171:3000 + - GITEA_RUNNER_REGISTRATION_TOKEN=${RUNNER_TOKEN} + - GITEA_RUNNER_NAME=portainer-server + - GITEA_RUNNER_LABELS=self-hosted,linux,docker + volumes: + - ./data:/data +EOF + +# Créer le fichier .env avec le token copié à l'étape 2c +echo "RUNNER_TOKEN=COLLER_LE_TOKEN_ICI" > .env + +# Démarrer +docker compose up -d + +# Vérifier (attendre ~10s) +docker logs gitea-act-runner +# → doit afficher "Runner registered successfully" +``` + +Vérifier dans Gitea → Site Administration → Actions → Runners → statut **Online**. + +--- + +## 4. Portainer — déployer le stack depuis Git + +### 4a. Créer le stack + +Portainer → **Stacks → Add stack** +- Name : `3d-pricing` +- Build method : **Git Repository** +- Repository URL : `http://192.168.5.171:3000/TON_USER/3d-pricing` +- Repository reference : `refs/heads/main` +- Compose path : `docker-compose.yml` +- Authentication : cocher si repo privé → entrer username + mot de passe Gitea + +Cliquer **Deploy the stack**. + +### 4b. Activer le webhook GitOps + +Une fois le stack déployé : + +Portainer → ton stack → **GitOps updates → Enable** +- Interval : laisser vide (on déclenche via webhook, pas par polling) +- Copier la **Webhook URL** générée (format `http://PORTAINER_IP:9000/api/stacks/webhooks/xxxxxxxx`) + +### 4c. Vérifier + +L'app doit répondre sur `http://SERVEUR_PORTAINER:5010` + +--- + +## 5. CI/CD — connecter Gitea Actions → Portainer webhook + +### 5a. Ajouter le secret dans Gitea + +Gitea → ton repo → **Settings → Actions → Secrets → Add secret** +- Name : `PORTAINER_WEBHOOK` +- Value : l'URL copiée à l'étape 4b + +### 5b. Le workflow est déjà en place + +Fichier `.gitea/workflows/deploy.yml` déjà dans le repo : +```yaml +name: Deploy via Portainer +on: + push: + branches: [main] +jobs: + deploy: + runs-on: self-hosted + steps: + - name: Trigger Portainer stack redeploy + run: | + HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X POST "${{ secrets.PORTAINER_WEBHOOK }}") + if [ "$HTTP_CODE" != "200" ] && [ "$HTTP_CODE" != "204" ]; then + echo "Portainer webhook failed (HTTP $HTTP_CODE)" + exit 1 + fi + echo "Redeploy triggered (HTTP $HTTP_CODE)" +``` + +--- + +## 6. Tester le pipeline complet + +```bash +# Depuis WSL +cd /mnt/c/Users/jbper/Claude/3d-pricing +git add -A +git commit -m "test: pipeline CI/CD" +git push +``` + +Puis surveiller : +1. **Gitea → ton repo → Actions** → job doit passer vert +2. **Portainer → Stacks → 3d-pricing** → heure de dernier déploiement mise à jour +3. `http://SERVEUR_PORTAINER:5010` → app répond + +--- + +## Résumé des ports et URLs + +| Service | URL | +|---|---| +| Gitea | http://192.168.5.171:3000 | +| Portainer | http://SERVEUR_PORTAINER:9000 | +| 3d-pricing | http://SERVEUR_PORTAINER:5010 | + +## Données persistantes + +La base SQLite est dans le volume Docker nommé **`3d-pricing-data`**. +Visible dans Portainer → **Volumes → 3d-pricing-data**. + +Backup manuel : +```bash +docker run --rm -v 3d-pricing-data:/data -v $(pwd):/backup alpine \ + cp /data/pricing.db /backup/pricing_backup_$(date +%Y%m%d).db +``` diff --git a/docker-compose.yml b/docker-compose.yml index d387658..c8fcb98 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,6 +6,9 @@ services: ports: - "5010:5000" volumes: - - ./data:/data + - 3d-pricing-data:/data environment: - DATABASE_PATH=/data/pricing.db + +volumes: + 3d-pricing-data: