Files
rpa_vision_v3/visual_workflow_builder/backend/manage.py
Dom a27b74cf22 v1.0 - Version stable: multi-PC, détection UI-DETR-1, 3 modes exécution
- Frontend v4 accessible sur réseau local (192.168.1.40)
- Ports ouverts: 3002 (frontend), 5001 (backend), 5004 (dashboard)
- Ollama GPU fonctionnel
- Self-healing interactif
- Dashboard confiance

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 11:23:51 +01:00

200 lines
7.0 KiB
Python

#!/usr/bin/env python3
"""
Script de gestion des migrations de base de données VWB
Usage:
python manage.py init # Initialiser les migrations (une seule fois)
python manage.py migrate # Créer une nouvelle migration
python manage.py upgrade # Appliquer les migrations pendantes
python manage.py downgrade # Annuler la dernière migration
python manage.py stamp # Marquer une révision comme appliquée
python manage.py current # Afficher la révision actuelle
python manage.py history # Afficher l'historique des migrations
python manage.py backup # Sauvegarder la base de données
python manage.py status # Afficher le status complet
Exemple de workflow de migration:
1. Modifier les modèles dans db/models.py
2. python manage.py migrate "Description du changement"
3. Vérifier le fichier de migration généré dans migrations/versions/
4. python manage.py upgrade
"""
import sys
import os
import shutil
import subprocess
from datetime import datetime
# Chemin vers le backend
BACKEND_DIR = os.path.dirname(os.path.abspath(__file__))
VENV_PYTHON = '/home/dom/ai/rpa_vision_v3/venv_v3/bin/python'
VENV_FLASK = '/home/dom/ai/rpa_vision_v3/venv_v3/bin/flask'
# Variables d'environnement pour Flask
ENV = os.environ.copy()
ENV['FLASK_APP'] = 'app.py'
def run_flask_db(args):
"""Exécute une commande flask db"""
cmd = [VENV_FLASK, 'db'] + args
result = subprocess.run(cmd, cwd=BACKEND_DIR, env=ENV, capture_output=True, text=True)
# Filtrer les warnings connus
output = result.stdout + result.stderr
for line in output.split('\n'):
if line.strip() and not any(skip in line for skip in [
'FutureWarning', 'pynvml', 'use_fast', 'Workflow ignoré',
'ScreenState non disponible', 'Server initialized'
]):
print(line)
return result.returncode == 0
def find_database():
"""Trouve le fichier de base de données SQLite"""
instance_dir = os.path.join(BACKEND_DIR, 'instance')
if os.path.exists(instance_dir):
for f in os.listdir(instance_dir):
if f.endswith('.db') and not f.startswith('.'):
return os.path.join(instance_dir, f)
return None
def backup_database():
"""Sauvegarde la base de données avant une migration"""
instance_dir = os.path.join(BACKEND_DIR, 'instance')
db_path = find_database()
if db_path and os.path.exists(db_path):
db_name = os.path.basename(db_path).replace('.db', '')
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
backup_dir = os.path.join(instance_dir, 'backups')
os.makedirs(backup_dir, exist_ok=True)
backup_path = os.path.join(backup_dir, f'{db_name}_{timestamp}.db')
shutil.copy2(db_path, backup_path)
print(f"✅ Base de données sauvegardée: {backup_path}")
# Garder seulement les 10 dernières sauvegardes
backups = sorted([f for f in os.listdir(backup_dir) if f.endswith('.db')])
if len(backups) > 10:
for old_backup in backups[:-10]:
os.remove(os.path.join(backup_dir, old_backup))
print(f" 🗑️ Ancienne sauvegarde supprimée: {old_backup}")
return backup_path
else:
print("⚠️ Pas de base de données existante à sauvegarder")
return None
def show_status():
"""Affiche le status complet des migrations"""
migrations_dir = os.path.join(BACKEND_DIR, 'migrations')
instance_dir = os.path.join(BACKEND_DIR, 'instance')
db_path = find_database()
print("=" * 50)
print("Status des Migrations VWB")
print("=" * 50)
print(f"Dossier backend: {BACKEND_DIR}")
print(f"Dossier migrations: {'✅ Existe' if os.path.exists(migrations_dir) else '❌ Non initialisé'}")
print(f"Base de données: {'' + db_path if db_path else '❌ Non créée'}")
if os.path.exists(migrations_dir):
versions_dir = os.path.join(migrations_dir, 'versions')
if os.path.exists(versions_dir):
migrations = sorted([f for f in os.listdir(versions_dir) if f.endswith('.py') and not f.startswith('__')])
print(f"\nMigrations disponibles ({len(migrations)}):")
for m in migrations:
print(f" 📄 {m}")
# Backups
backup_dir = os.path.join(instance_dir, 'backups')
if os.path.exists(backup_dir):
backups = sorted([f for f in os.listdir(backup_dir) if f.endswith('.db')])
if backups:
print(f"\nSauvegardes ({len(backups)}):")
for b in backups[-5:]: # Afficher les 5 dernières
print(f" 💾 {b}")
print("\nRévision actuelle de la base:")
run_flask_db(['current'])
def main():
if len(sys.argv) < 2:
print(__doc__)
sys.exit(1)
command = sys.argv[1].lower()
if command == 'init':
print("🔧 Initialisation des migrations...")
if run_flask_db(['init']):
print("✅ Migrations initialisées")
print(" Prochaine étape: python manage.py migrate 'Initial migration'")
else:
print("❌ Échec de l'initialisation")
elif command == 'migrate':
message = ' '.join(sys.argv[2:]) if len(sys.argv) > 2 else f"Migration {datetime.now().strftime('%Y%m%d_%H%M%S')}"
print(f"📝 Création de la migration: {message}")
backup_database()
if run_flask_db(['migrate', '-m', message]):
print("✅ Migration créée")
print(" Prochaine étape: python manage.py upgrade")
else:
print("❌ Échec de la création de migration")
elif command == 'upgrade':
revision = sys.argv[2] if len(sys.argv) > 2 else 'head'
print(f"⬆️ Application des migrations jusqu'à: {revision}")
backup_database()
if run_flask_db(['upgrade', revision]):
print("✅ Migrations appliquées")
else:
print("❌ Échec de l'upgrade")
elif command == 'downgrade':
revision = sys.argv[2] if len(sys.argv) > 2 else '-1'
print(f"⬇️ Annulation des migrations: {revision}")
backup_database()
if run_flask_db(['downgrade', revision]):
print("✅ Downgrade effectué")
else:
print("❌ Échec du downgrade")
elif command == 'stamp':
revision = sys.argv[2] if len(sys.argv) > 2 else 'head'
print(f"🏷️ Marquage de la révision: {revision}")
if run_flask_db(['stamp', revision]):
print("✅ Révision marquée")
else:
print("❌ Échec du stamp")
elif command == 'current':
print("📍 Révision actuelle:")
run_flask_db(['current'])
elif command == 'history':
print("📜 Historique des migrations:")
run_flask_db(['history'])
elif command == 'backup':
backup_database()
elif command == 'status':
show_status()
else:
print(f"❌ Commande inconnue: {command}")
print(__doc__)
sys.exit(1)
if __name__ == '__main__':
main()