Processus de Migration Amélioré - Aaperture
Ce document décrit le processus amélioré de gestion des migrations de base de données avec validation, backup automatique, logging et rollback.
📋 Vue d'ensemble
Le système de migration amélioré fournit :
- ✅ Validation automatique des migrations avant exécution
- ✅ Backup automatique avant migration en production
- ✅ Logging complet de toutes les migrations (statut, durée, erreurs)
- ✅ Rollback automatique en cas d'échec
- ✅ Monitoring des migrations (durée, taux de succès)
- ✅ Vérification de l'ordre des migrations
🏗️ Architecture
Table migration_logs
Toutes les migrations sont enregistrées dans la table migration_logs :
CREATE TABLE migration_logs (
id UUID PRIMARY KEY,
changeset_id TEXT NOT NULL, -- ID du changeset Liquibase
author TEXT NOT NULL, -- Auteur de la migration
filename TEXT NOT NULL, -- Nom du fichier de migration
status TEXT NOT NULL, -- 'in_progress', 'completed', 'failed', 'rolled_back'
error_message TEXT, -- Message d'erreur si échec
duration_ms INTEGER, -- Durée en millisecondes
backup_file TEXT, -- Fichier de backup créé avant migration
executed_at TIMESTAMPTZ, -- Date d'exécution
rolled_back_at TIMESTAMPTZ, -- Date de rollback (si applicable)
executed_by TEXT, -- Qui/quoi a exécuté la migration
metadata JSONB, -- Métadonnées supplémentaires
created_at TIMESTAMPTZ
);
Scripts de migration
migrate-improved.sh (recommandé)
Script amélioré avec toutes les fonctionnalités :
ENVIRONMENT=production ./infra/migrate-improved.sh
Fonctionnalités :
- ✅ Validation automatique
- ✅ Backup avant migration (production uniquement)
- ✅ Logging dans
migration_logs - ✅ Rollback automatique en cas d'échec
- ✅ Monitoring et reporting
Note : Le script
migrate.shbasique existe toujours mais est déprécié. Utilisezmigrate-improved.shpour toutes les migrations.
📝 Processus de migration
1. Création d'une migration
# Créer un nouveau dossier de migration
mkdir -p infra/liquibase/changes/0113_ma_nouvelle_migration
# Créer up.sql
cat > infra/liquibase/changes/0113_ma_nouvelle_migration/up.sql << EOF
-- Description de la migration
CREATE TABLE IF NOT EXISTS ma_table (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
name TEXT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
EOF
# Créer down.sql
cat > infra/liquibase/changes/0113_ma_nouvelle_migration/down.sql << EOF
-- Rollback de la migration
DROP TABLE IF EXISTS ma_table;
EOF
2. Ajout au changelog
Ajouter l'entrée dans infra/liquibase/changelog-master.yaml :
- changeSet:
id: 0113-ma-nouvelle-migration
author: aaperture
changes:
- sqlFile:
path: changes/0113_ma_nouvelle_migration/up.sql
relativeToChangelogFile: true
splitStatements: false
rollback:
- sqlFile:
path: changes/0113_ma_nouvelle_migration/down.sql
relativeToChangelogFile: true
splitStatements: false
3. Validation locale
# Valider la syntaxe SQL
cd infra
docker compose run --rm liquibase validate
# Ou utiliser le script amélioré
ENVIRONMENT=development ./migrate-improved.sh
4. Test sur staging
# Sur environnement de staging
ENVIRONMENT=staging ./infra/migrate-improved.sh
5. Migration en production
Le script amélioré s'exécute automatiquement dans le pipeline CI/CD :
# Dans .gitlab-ci.yml
ENVIRONMENT=production ./infra/migrate-improved.sh
Processus automatique :
- ✅ Validation des migrations
- ✅ Vérification de l'ordre
- ✅ Backup automatique de la DB
- ✅ Exécution des migrations
- ✅ Logging dans
migration_logs - ✅ Rollback automatique en cas d'échec
🔍 Monitoring
Requêtes SQL utiles
Dernière migration
SELECT * FROM migration_logs
ORDER BY executed_at DESC
LIMIT 1;
Migrations échouées
SELECT * FROM migration_logs
WHERE status = 'failed'
ORDER BY executed_at DESC;
Statistiques des migrations
SELECT
status,
COUNT(*) as count,
AVG(duration_ms) as avg_duration_ms,
MAX(executed_at) as last_execution
FROM migration_logs
GROUP BY status;
Migrations récentes
SELECT
changeset_id,
author,
status,
duration_ms,
executed_at,
error_message
FROM migration_logs
WHERE executed_at > NOW() - INTERVAL '7 days'
ORDER BY executed_at DESC;
🔄 Synchronisation depuis Liquibase
Vue d'ensemble
Si des migrations ont été exécutées directement avec Liquibase (sans passer par le système de logging amélioré), il est possible de synchroniser les logs depuis la table databasechangelog de Liquibase vers migration_logs.
Utilisation
Via l'interface admin
- Accéder à l'onglet "Migrations" dans le panneau d'administration
- Cliquer sur le bouton "Synchroniser depuis Liquibase"
- Le système importe automatiquement les migrations manquantes
Via l'API
# Endpoint admin (nécessite ADMIN_ACCESS)
POST /migrations/sync-from-liquibase
Réponse :
{
"message": "Synced 5 migration(s) from Liquibase",
"synced": 5
}
Fonctionnement
- Vérification : Le service vérifie si la table
databasechangelogexiste - Lecture : Lit tous les changesets exécutés (
exectype = 'EXECUTED') - Filtrage : Ignore les changesets déjà présents dans
migration_logs - Import : Crée les entrées correspondantes dans
migration_logsavec :changeset_id: ID du changeset Liquibaseauthor: Auteur du changesetfilename: Nom du fichier de migrationstatus:'completed'(puisque déjà exécuté)executed_at: Date d'exécution depuisdateexecutedexecuted_by:'liquibase-sync'
Cas d'usage
- Migration manuelle : Si une migration a été exécutée manuellement avec Liquibase
- Récupération après incident : Si les logs ont été perdus mais que les migrations sont toujours dans
databasechangelog - Synchronisation initiale : Lors de la mise en place du système de logging amélioré sur une base existante
Limitations
- Les migrations synchronisées n'ont pas de
duration_ms(non disponible dansdatabasechangelog) - Les migrations synchronisées n'ont pas de
backup_file(backup non effectué) - Seules les migrations avec
exectype = 'EXECUTED'sont synchronisées
Prévention des doublons
Le système vérifie automatiquement les changeset_id existants avant d'importer pour éviter les doublons.
🚨 Gestion des erreurs
Rollback automatique
Si une migration échoue, le script tente automatiquement un rollback :
- Détection de l'échec
- Tentative de rollback automatique
- Mise à jour du statut dans
migration_logs - Notification (si configuré)
Rollback manuel
Si le rollback automatique échoue :
# Rollback d'une migration
cd infra
docker compose run --rm liquibase rollbackCount 1
# Rollback jusqu'à un tag spécifique
docker compose run --rm liquibase rollback tag_name
Restauration depuis backup
Si une migration cause des problèmes :
-
Identifier le backup créé avant la migration :
SELECT backup_file FROM migration_logs
WHERE executed_at = '2024-01-01 10:00:00'; -
Restaurer le backup :
gunzip -c /path/to/backup/postgres-2024-01-01T10-00-00.sql.gz | \
psql -h localhost -U postgres -d aaperture -
Marquer la migration comme rollback :
UPDATE migration_logs
SET status = 'rolled_back', rolled_back_at = NOW()
WHERE id = 'migration-id';
📊 Bonnes pratiques
1. Toujours créer un down.sql
Chaque migration doit avoir un fichier de rollback :
-- up.sql
CREATE TABLE ma_table (...);
-- down.sql
DROP TABLE IF EXISTS ma_table;
2. Tester localement avant de commiter
# Créer une DB de test
createdb aaperture_test
# Tester la migration
ENVIRONMENT=development ./infra/migrate-improved.sh
3. Vérifier les dépendances
Assurez-vous que les migrations sont dans le bon ordre dans changelog-master.yaml.
4. Documenter les migrations complexes
Ajoutez des commentaires dans les fichiers SQL :
-- Migration: 0113-ma-nouvelle-migration
-- Description: Crée la table ma_table pour stocker...
-- Dependencies: Nécessite la migration 0112-create-migration-logs
-- Breaking changes: Aucun
5. Ne jamais modifier une migration déjà appliquée
Si une migration a été appliquée en production, créez une nouvelle migration pour corriger.
🔧 Configuration
Variables d'environnement
# Environnement (development, staging, production)
ENVIRONMENT=production
# Credentials DB (chargés depuis .env)
POSTGRES_DB=aaperture
POSTGRES_USER=postgres
POSTGRES_PASSWORD=secret
# Image Liquibase (définie dans CI/CD)
CI_REGISTRY_IMAGE=registry.gitlab.com/namespace/project
CI_COMMIT_SHORT_SHA=abc123
# Timeout pour migrations (seconds, défaut: 600 = 10 minutes)
MIGRATION_TIMEOUT=600
Note: Le script migrate-improved.sh applique automatiquement un timeout configurable via MIGRATION_TIMEOUT. Voir TIMEOUT_MANAGEMENT.md pour plus d'informations.
Intégration CI/CD
Le script amélioré est appelé automatiquement dans .gitlab-ci.yml :
# 4) Migrations
- |
ssh "$SERVER_USER@$SERVER_HOST" "\
set -eo pipefail; \
export APP_DIR='$APP_DIR'; \
export ENVIRONMENT='production'; \
export CI_REGISTRY='$CI_REGISTRY' CI_REGISTRY_IMAGE='$CI_REGISTRY_IMAGE' CI_COMMIT_SHORT_SHA='$CI_COMMIT_SHORT_SHA'; \
bash '$APP_DIR/infra/migrate-improved.sh'"
📈 Améliorations futures
- Interface admin pour visualiser les migrations - ✅ Complété
- Alertes automatiques en cas d'échec - ✅ Complété
- Tests automatisés de migration dans CI/CD - ✅ Complété
- Validation plus poussée (détection de migrations manquantes) - ✅ Complété
- Synchronisation depuis Liquibase - ✅ Complété
- Dashboard de monitoring des migrations
- Intégration avec le système de backup pour restaurer automatiquement
🔗 Références
- Liquibase Documentation
- Disaster Recovery Plan
- Backend Guidelines (documentation interne)
- Timeout Management - Gestion des timeouts pour migrations
- Environment Variables - Timeouts - Variables d'environnement pour timeouts