Files

90 lines
2.7 KiB
Python
Raw Permalink Normal View History

2026-08-03 10:02:12 +02:00
"""
Application séquentielle des migrations SQL du dossier `migrations/`
sur la base « bolsa ». À exécuter depuis la racine du projet :
python migrations/apply_migrations.py
Lit la configuration MySQL depuis les variables d'environnement (.env).
N'applique que les fichiers non déjà enregistrés dans la table
`__migrations__` (créée automatiquement).
"""
import os
import sys
from pathlib import Path
import pymysql
from dotenv import load_dotenv
load_dotenv()
MIGRATIONS_DIR = Path(__file__).parent
def get_connection():
return pymysql.connect(
host=os.environ.get("MYSQL_HOST", "db"),
port=int(os.environ.get("MYSQL_PORT", "3306")),
user=os.environ.get("MYSQL_USER", "jfgiraud"),
password=os.environ.get("MYSQL_PASSWORD", ""),
database=os.environ.get("MYSQL_DATABASE", "bolsa"),
charset="utf8mb4",
autocommit=False,
)
def main():
conn = get_connection()
try:
with conn.cursor() as cur:
cur.execute(
"CREATE TABLE IF NOT EXISTS `__migrations__` ("
" `id` int NOT NULL AUTO_INCREMENT,"
" `filename` varchar(255) NOT NULL,"
" `applied_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,"
" PRIMARY KEY (`id`),"
" UNIQUE KEY `idx_filename` (`filename`)"
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"
)
conn.commit()
cur.execute("SELECT filename FROM `__migrations__`")
applied = {row[0] for row in cur.fetchall()}
sql_files = sorted(
f for f in MIGRATIONS_DIR.glob("*.sql")
if f.name != "schema.sql"
)
if not sql_files:
print("Aucune migration à appliquer.")
return
for sql_file in sql_files:
if sql_file.name in applied:
print(f"[déjà appliquée] {sql_file.name}")
continue
print(f"[application] {sql_file.name}")
sql = sql_file.read_text(encoding="utf-8")
# Découpage sur les ';' pour exécuter instruction par instruction
statements = [s.strip() for s in sql.split(";") if s.strip()]
for stmt in statements:
cur.execute(stmt)
cur.execute(
"INSERT INTO `__migrations__` (filename) VALUES (%s)",
(sql_file.name,),
)
conn.commit()
print(f"[OK] {sql_file.name}")
except Exception as e:
conn.rollback()
print(f"[ERREUR] {e}", file=sys.stderr)
sys.exit(1)
finally:
conn.close()
if __name__ == "__main__":
main()