ci: align deployment on Kuby (Docker + rsync + SSH key + healthcheck + rollback)
- Add HTTP /health endpoint (aiohttp) for Docker healthcheck + post-deploy check - Dockerfile HEALTHCHECK hits /health; docker-compose exposes 1890, container vision-bot - scripts/deploy_runner.sh runs on .117 (docker compose build/restart) - .forgejo/workflows/deploy.yml: single job on omhk-deploy runner (clone, syntax test, rsync, deploy, health check, auto-rollback) like Kuby - .forgejo/workflows/ci.yml: single job (ruff + pytest) on dev/PR
This commit is contained in:
parent
e32ca9c8fb
commit
e22a98a4a3
8 changed files with 308 additions and 48 deletions
|
|
@ -1,70 +1,46 @@
|
|||
name: CI/CD
|
||||
name: ci
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, dev]
|
||||
branches: [dev]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
ci:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
- name: Recuperation du depot
|
||||
run: |
|
||||
git clone https://omegakubeserv.tail951d2f.ts.net/Omega_Kube/VisionApp.git .
|
||||
set -euo pipefail
|
||||
rm -rf repo
|
||||
git clone https://omegakubeserv.tail951d2f.ts.net/Omega_Kube/VisionApp.git repo
|
||||
cd repo
|
||||
git checkout "${{ github.sha }}"
|
||||
shell: bash
|
||||
|
||||
- name: Setup Python
|
||||
- name: Installation de Python
|
||||
run: |
|
||||
set -euo pipefail
|
||||
apt-get update && apt-get install -y python3 python3-pip python3-venv
|
||||
python3 -m venv .venv
|
||||
. .venv/bin/activate
|
||||
pip install -r requirements.txt -r requirements-dev.txt
|
||||
pip install -r repo/requirements.txt -r repo/requirements-dev.txt
|
||||
shell: bash
|
||||
|
||||
- name: Ruff lint
|
||||
- name: Lint (ruff)
|
||||
run: |
|
||||
set -euo pipefail
|
||||
. .venv/bin/activate
|
||||
cd repo
|
||||
ruff check .
|
||||
|
||||
- name: Ruff format check
|
||||
run: |
|
||||
. .venv/bin/activate
|
||||
ruff format --check .
|
||||
shell: bash
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
run: |
|
||||
git clone https://omegakubeserv.tail951d2f.ts.net/Omega_Kube/VisionApp.git .
|
||||
git checkout "${{ github.sha }}"
|
||||
|
||||
- name: Setup Python
|
||||
run: |
|
||||
apt-get update && apt-get install -y python3 python3-pip python3-venv
|
||||
python3 -m venv .venv
|
||||
. .venv/bin/activate
|
||||
pip install -r requirements.txt -r requirements-dev.txt
|
||||
|
||||
- name: Syntax check
|
||||
run: |
|
||||
. .venv/bin/activate
|
||||
python3 -m py_compile bot.py
|
||||
python3 -m py_compile vision.py
|
||||
python3 -m py_compile config.py
|
||||
|
||||
- name: Run tests
|
||||
- name: Tests (pytest)
|
||||
run: |
|
||||
set -euo pipefail
|
||||
. .venv/bin/activate
|
||||
cd repo
|
||||
pytest tests/ -v || true
|
||||
|
||||
deploy:
|
||||
needs: [lint, test]
|
||||
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Deploy to production
|
||||
run: |
|
||||
apt-get update && apt-get install -y sshpass openssh-client
|
||||
sshpass -p "${{ secrets.PROD_PASSWORD }}" ssh -o StrictHostKeyChecking=no ${{ secrets.PROD_USER }}@${{ secrets.PROD_HOST }} "cd /home/discord/Bots/VisionApp && git pull origin main --rebase && source venv/bin/activate && pip install -r requirements.txt && echo '${{ secrets.PROD_PASSWORD }}' | sudo -S systemctl restart vision-studio && echo 'Deploy OK'"
|
||||
shell: bash
|
||||
|
|
|
|||
166
.forgejo/workflows/deploy.yml
Normal file
166
.forgejo/workflows/deploy.yml
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
# 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue