Ver código fonte

fix: migration remote_instance_id via sqlite3 direct avant import app

app.py schedule les jobs au démarrage (Job.query) — si la colonne
n'existe pas encore en DB, l'import explose. On lit DB_PATH depuis
le fichier de config et on fait l'ALTER TABLE via sqlite3 brut
avant tout import de SQLAlchemy/app.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Cédric Hansen 1 mês atrás
pai
commit
6f199a1aa4
1 arquivos alterados com 32 adições e 20 exclusões
  1. 32 20
      sources/init_db.py

+ 32 - 20
sources/init_db.py

@@ -1,31 +1,43 @@
 #!/usr/bin/env python3
 """Initialise (ou migre) la base de données SQLite. Appelé par les scripts install et upgrade."""
 import os
+import sqlite3
 import sys
 
-if len(sys.argv) > 1:
-    os.environ["BACKUPMANAGER_CONFIG"] = sys.argv[1]
+config_path = sys.argv[1] if len(sys.argv) > 1 else None
+if config_path:
+    os.environ["BACKUPMANAGER_CONFIG"] = config_path
 
+# Lire DB_PATH directement depuis le fichier de config (sans importer app/SQLAlchemy)
+# pour pouvoir migrer le schéma AVANT que l'import de app ne tente de requêter la DB.
+_cfg = {}
+if config_path and os.path.exists(config_path):
+    with open(config_path) as _f:
+        exec(compile(_f.read(), config_path, "exec"), _cfg)
+db_path = _cfg.get("DB_PATH") or os.path.join(
+    os.path.dirname(os.path.abspath(__file__)), "backupmanager.db"
+)
+
+# Migrations SQLite directes — avant tout import de SQLAlchemy/app
+if os.path.exists(db_path):
+    _conn = sqlite3.connect(db_path)
+    _cur = _conn.execute("PRAGMA table_info(jobs)")
+    existing_cols = {row[1] for row in _cur.fetchall()}
+
+    migrations = [
+        ("destination_id",    "ALTER TABLE jobs ADD COLUMN destination_id INTEGER REFERENCES destinations(id)"),
+        ("remote_instance_id","ALTER TABLE jobs ADD COLUMN remote_instance_id INTEGER REFERENCES remote_instances(id)"),
+    ]
+    for col, sql in migrations:
+        if col not in existing_cols:
+            _conn.execute(sql)
+            _conn.commit()
+            print(f"Migration : colonne {col} ajoutée à jobs.")
+    _conn.close()
+
+# Import de app après les migrations — SQLAlchemy peut désormais requêter la DB
 from app import app, db
-from sqlalchemy import text
 
 with app.app_context():
     db.create_all()
-
-    # Migrations manuelles pour les colonnes ajoutées après la création initiale
-    with db.engine.connect() as conn:
-        existing = [row[1] for row in conn.execute(text("PRAGMA table_info(jobs)"))]
-        if "destination_id" not in existing:
-            conn.execute(text(
-                "ALTER TABLE jobs ADD COLUMN destination_id INTEGER REFERENCES destinations(id)"
-            ))
-            conn.commit()
-            print("Migration : colonne destination_id ajoutée à jobs.")
-        if "remote_instance_id" not in existing:
-            conn.execute(text(
-                "ALTER TABLE jobs ADD COLUMN remote_instance_id INTEGER REFERENCES remote_instances(id)"
-            ))
-            conn.commit()
-            print("Migration : colonne remote_instance_id ajoutée à jobs.")
-
     print("Base de données initialisée.")