diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml index 480739d..0d85b1b 100644 --- a/.forgejo/workflows/ci.yml +++ b/.forgejo/workflows/ci.yml @@ -2,7 +2,7 @@ name: ci on: push: - branches: [dev] + branches: [main, dev] pull_request: branches: [main] diff --git a/.forgejo/workflows/deploy.yml b/.forgejo/workflows/deploy.yml deleted file mode 100644 index d07ca77..0000000 --- a/.forgejo/workflows/deploy.yml +++ /dev/null @@ -1,166 +0,0 @@ -# ═══════════════════════════════════════════════════════════════════════════ -# Vision Studio — Deploiement automatique via Forgejo Actions -# -# Declencheur : push sur `main`. -# Runner : forgejo-runner self-hosted (label omhk-deploy, sur .22). -# Cible : 192.168.1.117 -> conteneur Docker `vision-bot` -# (/home/discord/Bots/VisionApp, bind-mount .:/app). -# -# Pipeline : syntaxe -> rsync -> deploy -> health check -> rollback auto. -# Calque du deploy.yml de Kuby. -# ═══════════════════════════════════════════════════════════════════════════ -name: deploy - -on: - push: - branches: [main] - -jobs: - deploy: - runs-on: omhk-deploy - steps: - # ═══ CLONE ═════════════════════════════════════════════════════════ - - name: Recuperation du depot (clone interne Forgejo) - run: | - set -euo pipefail - rm -rf repo - git clone --depth 20 "http://192.168.1.22:3000/Omega_Kube/VisionApp.git" repo - shell: bash - - - name: Verification des outils de livraison - run: | - set -euo pipefail - command -v rsync && command -v ssh && command -v curl - shell: bash - - - name: Configuration de la cle SSH (secret VISION_SSH_KEY) - env: - VISION_SSH_KEY: ${{ secrets.VISION_SSH_KEY }} - run: | - set -euo pipefail - mkdir -p ~/.ssh - chmod 700 ~/.ssh - printf '%s\n' "$VISION_SSH_KEY" > ~/.ssh/id_vision - chmod 600 ~/.ssh/id_vision - ssh-keyscan -H 192.168.1.117 >> ~/.ssh/known_hosts 2>/dev/null - shell: bash - - # ═══ TEST SYNTAXE (sur .22, rapide) ══════════════════════════════ - - name: Test syntaxe Python - run: | - set -euo pipefail - cd repo - NPROC=$(nproc 2>/dev/null || echo 2) - ERR_FILE=$(mktemp) - find . -name "*.py" \ - -not -path "*/backups/*" \ - -not -path "*/__pycache__/*" \ - -not -path "*/.git/*" \ - -not -path "*/venv/*" \ - -not -path "*/.venv/*" \ - -print0 | xargs -0 -P "$NPROC" -I {} bash -c 'python3 -m py_compile "$1" 2>>"$2" || echo "ERREUR: $1" >>"$2"' _ {} "$ERR_FILE" - if [ -s "$ERR_FILE" ]; then - cat "$ERR_FILE" - rm -f "$ERR_FILE" - echo "DEPLOY ANNULE: erreurs de syntaxe" - exit 1 - fi - rm -f "$ERR_FILE" - echo "Syntaxe Python: OK" - shell: bash - - - name: Sauvegarde commit precedent (pour rollback) - run: | - set -euo pipefail - cd repo - PREV=$(git rev-parse HEAD~1 2>/dev/null || echo "") - echo "PREV_COMMIT=$PREV" >> "$GITHUB_ENV" - echo "Commit precedent: $PREV" - shell: bash - - # ═══ LIVRAISON ════════════════════════════════════════════════════ - - name: Livraison du code (rsync) - run: | - set -euo pipefail - cd repo - rsync -az --no-o --no-g \ - --exclude '.git/' --exclude '.env' --exclude '.env.*' \ - --exclude 'data/' --exclude 'logs/' --exclude '*.log' --exclude 'nohup.out' \ - --exclude '__pycache__/' --exclude 'venv/' --exclude '.venv/' \ - --exclude '*.db' --exclude '*.db-journal' --exclude '*.db-wal' --exclude '*.db-shm' \ - --exclude '.vscode/' --exclude '.idea/' \ - -e "ssh -i ~/.ssh/id_vision -o StrictHostKeyChecking=no -o UserKnownHostsFile=~/.ssh/known_hosts" \ - . \ - discord@192.168.1.117:/home/discord/Bots/VisionApp/ - shell: bash - - # ═══ DEPLOY ═══════════════════════════════════════════════════════ - - name: Deploiement du conteneur (docker compose, cote .117) - run: | - set -euo pipefail - cd repo - COMMIT="$(git rev-parse --short HEAD)" - CHANGED="$(git diff --name-only HEAD~20 HEAD 2>/dev/null || true)" - REBUILD="false" - if echo "$CHANGED" | grep -qE '(^|/)(requirements\.txt|Dockerfile)$'; then - REBUILD="true" - fi - ssh -i ~/.ssh/id_vision -o StrictHostKeyChecking=no -o UserKnownHostsFile=~/.ssh/known_hosts \ - discord@192.168.1.117 \ - "bash /home/discord/Bots/VisionApp/scripts/deploy_runner.sh main '${COMMIT}' '${REBUILD}'" - shell: bash - - # ═══ HEALTH CHECK ═════════════════════════════════════════════════ - - name: Health check post-deploy - id: health_check - run: | - set -euo pipefail - echo "Attente du demarrage du bot..." - for i in $(seq 1 10); do - sleep 3 - STATUS=$(curl -s -m 5 http://192.168.1.117:1890/health 2>/dev/null || echo "") - if echo "$STATUS" | grep -q '"status":"ok"'; then - echo "Health check OK (tentative $i)" - exit 0 - fi - echo "Tentative $i/10..." - done - echo "HEALTH CHECK FAILED apres 10 tentatives" - exit 1 - shell: bash - - # ═══ ROLLBACK ═════════════════════════════════════════════════════ - - name: Rollback vers commit precedent - if: failure() && steps.health_check.outcome == 'failure' - run: | - set -euo pipefail - if [ -z "${PREV_COMMIT:-}" ]; then - echo "Pas de commit precedent — rollback impossible" - exit 1 - fi - echo "═══ ROLLBACK vers ${PREV_COMMIT} ═══" - cd repo - git checkout "$PREV_COMMIT" - rsync -az --no-o --no-g \ - --exclude '.git/' --exclude '.env' --exclude '.env.*' \ - --exclude 'data/' --exclude 'logs/' --exclude '*.log' --exclude 'nohup.out' \ - --exclude '__pycache__/' --exclude 'venv/' --exclude '.venv/' \ - --exclude '*.db' --exclude '*.db-journal' --exclude '*.db-wal' --exclude '*.db-shm' \ - --exclude '.vscode/' --exclude '.idea/' \ - -e "ssh -i ~/.ssh/id_vision -o StrictHostKeyChecking=no -o UserKnownHostsFile=~/.ssh/known_hosts" \ - . \ - discord@192.168.1.117:/home/discord/Bots/VisionApp/ - ssh -i ~/.ssh/id_vision -o StrictHostKeyChecking=no -o UserKnownHostsFile=~/.ssh/known_hosts \ - discord@192.168.1.117 \ - "bash /home/discord/Bots/VisionApp/scripts/deploy_runner.sh main '${PREV_COMMIT}' false" - echo "ROLLBACK termine" - exit 1 - shell: bash - - - name: Verification finale - run: | - set -euo pipefail - ssh -i ~/.ssh/id_vision -o StrictHostKeyChecking=no -o UserKnownHostsFile=~/.ssh/known_hosts \ - discord@192.168.1.117 \ - "docker ps --filter name=vision-bot --format '{{.Names}} {{.Status}}' && curl -s -m 5 http://localhost:1890/health && echo" - shell: bash diff --git a/scripts/deploy_prod.sh b/scripts/deploy_prod.sh new file mode 100755 index 0000000..e867b12 --- /dev/null +++ b/scripts/deploy_prod.sh @@ -0,0 +1,53 @@ +#!/bin/bash +# ══════════════════════════════════════════════════════════════════════════════ +# Vision Studio — Deploy manuel vers pavillon80.changeip.org:444 +# +# Usage: ./scripts/deploy_prod.sh [branch] +# Défaut: main +# ══════════════════════════════════════════════════════════════════════════════ +set -euo pipefail + +BRANCH="${1:-main}" +HOST="discord@176.182.176.84" +PORT=444 +REMOTE_DIR="/home/discord/Bots/VisionApp" +SSH_OPTS="-o StrictHostKeyChecking=no -p $PORT" + +log() { echo "[deploy] $(date '+%F %T') $*"; } + +log "Deploy de la branche $BRANCH vers $HOST:$PORT..." + +# 1. Rsync du code +log "Rsync du code..." +rsync -az --no-o --no-g \ + --exclude '.git/' --exclude '.env' --exclude '.env.*' \ + --exclude 'data/' --exclude 'logs/' --exclude '*.log' --exclude 'nohup.out' \ + --exclude '__pycache__/' --exclude 'venv/' --exclude '.venv/' \ + --exclude '*.db' --exclude '*.db-journal' --exclude '*.db-wal' --exclude '*.db-shm' \ + --exclude '.vscode/' --exclude '.idea/' \ + -e "ssh $SSH_OPTS" \ + . "$HOST:$REMOTE_DIR/" + +# 2. Vérification syntaxe sur le serveur +log "Vérification syntaxe..." +ssh $SSH_OPTS "$HOST" "cd $REMOTE_DIR && find . -name '*.py' -not -path '*/__pycache__/*' -not -path '*/.git/*' -not -path '*/venv/*' | head -20 | xargs -I{} python3 -m py_compile {} 2>&1 | head -5" + +# 3. Rebuild + restart Docker +log "Rebuild Docker..." +ssh $SSH_OPTS "$HOST" "cd $REMOTE_DIR && docker compose build --no-cache vision 2>&1 | tail -3" + +log "Restart du conteneur..." +ssh $SSH_OPTS "$HOST" "cd $REMOTE_DIR && docker compose up -d --force-recreate vision 2>&1 | tail -3" + +# 4. Health check +log "Health check..." +sleep 8 +STATUS=$(ssh $SSH_OPTS "$HOST" "curl -s -m 5 http://localhost:1890/health 2>/dev/null || echo ''") +if echo "$STATUS" | grep -q '"status":"ok"'; then + log "✅ Deploy réussi — Health OK" + ssh $SSH_OPTS "$HOST" "docker logs --tail 5 vision-bot 2>&1" +else + log "❌ Health check échoué" + ssh $SSH_OPTS "$HOST" "docker logs --tail 20 vision-bot 2>&1" + exit 1 +fi