# Script d'audit des migrations Flyway vs Entités JPA # Auteur: Lions Dev # Date: 2026-03-13 $ErrorActionPreference = "Stop" $projectRoot = $PSScriptRoot Write-Host "`n╔══════════════════════════════════════════════════════════╗" -ForegroundColor Cyan Write-Host "║ Audit Migrations Flyway vs Entités JPA - UnionFlow ║" -ForegroundColor Cyan Write-Host "╚══════════════════════════════════════════════════════════╝`n" -ForegroundColor Cyan # 1. Extraire toutes les entités et leurs noms de tables Write-Host "[1/4] Extraction des entités JPA..." -ForegroundColor Yellow $entityFiles = Get-ChildItem -Path "$projectRoot\src\main\java\dev\lions\unionflow\server\entity" -Filter "*.java" -Recurse | Where-Object { $_.Name -ne "package-info.java" } $entities = @{} foreach ($file in $entityFiles) { $content = Get-Content $file.FullName -Raw # Extraire le nom de la classe if ($content -match 'public\s+class\s+(\w+)') { $className = $Matches[1] # Extraire le nom de la table $tableName = $null if ($content -match '@Table\s*\(\s*name\s*=\s*"([^"]+)"') { $tableName = $Matches[1] } else { # Si pas de @Table explicite, utiliser le nom de la classe en snake_case $tableName = ($className -creplace '([A-Z])', '_$1').ToLower().TrimStart('_') } $entities[$className] = @{ TableName = $tableName FilePath = $file.FullName } } } Write-Host " → $($entities.Count) entités trouvées" -ForegroundColor Green # 2. Lister toutes les migrations Write-Host "`n[2/4] Analyse des migrations Flyway..." -ForegroundColor Yellow $migrations = Get-ChildItem -Path "$projectRoot\src\main\resources\db\migration" -Filter "V*.sql" | Sort-Object Name $allTables = @{} foreach ($migration in $migrations) { Write-Host " → $($migration.Name)" -ForegroundColor Gray $content = Get-Content $migration.FullName -Raw # Extraire toutes les CREATE TABLE $matches = [regex]::Matches($content, 'CREATE\s+TABLE\s+(IF\s+NOT\s+EXISTS\s+)?([a-z_]+)', [System.Text.RegularExpressions.RegexOptions]::IgnoreCase) foreach ($match in $matches) { $tableName = $match.Groups[2].Value if (-not $allTables.ContainsKey($tableName)) { $allTables[$tableName] = @() } $allTables[$tableName] += $migration.Name } } Write-Host " → $($allTables.Keys.Count) tables uniques trouvées dans les migrations" -ForegroundColor Green # 3. Comparaison Write-Host "`n[3/4] Comparaison Entités <-> Migrations..." -ForegroundColor Yellow $missingInMigrations = @() $missingInEntities = @() $ok = @() foreach ($entity in $entities.Keys) { $tableName = $entities[$entity].TableName if ($allTables.ContainsKey($tableName)) { $ok += @{ Entity = $entity Table = $tableName Migrations = $allTables[$tableName] -join ", " } } else { $missingInMigrations += @{ Entity = $entity Table = $tableName } } } foreach ($table in $allTables.Keys) { $found = $false foreach ($entity in $entities.Keys) { if ($entities[$entity].TableName -eq $table) { $found = $true break } } if (-not $found) { $missingInEntities += @{ Table = $table Migrations = $allTables[$table] -join ", " } } } # 4. Rapport Write-Host "`n[4/4] Génération du rapport..." -ForegroundColor Yellow $report = @" # Rapport d'Audit - Migrations Flyway vs Entités JPA Date: $(Get-Date -Format "yyyy-MM-dd HH:mm:ss") ## Résumé - **Entités JPA**: $($entities.Count) - **Tables dans migrations**: $($allTables.Keys.Count) - **OK (match)**: $($ok.Count) - **⚠️ Entités sans table**: $($missingInMigrations.Count) - **⚠️ Tables sans entité**: $($missingInEntities.Count) --- ## ✅ Entités avec table correspondante ($($ok.Count)) | Entité | Table | Migration(s) | |--------|-------|--------------| "@ foreach ($item in $ok | Sort-Object { $_.Entity }) { $report += "`n| $($item.Entity) | $($item.Table) | $($item.Migrations) |" } if ($missingInMigrations.Count -gt 0) { $report += @" --- ## ⚠️ Entités SANS table dans les migrations ($($missingInMigrations.Count)) **ACTION REQUISE**: Ces entités existent dans le code mais n'ont pas de table dans les migrations! | Entité | Table attendue | |--------|----------------| "@ foreach ($item in $missingInMigrations | Sort-Object { $_.Table }) { $report += "`n| $($item.Entity) | ``$($item.Table)`` |" } } if ($missingInEntities.Count -gt 0) { $report += @" --- ## ⚠️ Tables SANS entité correspondante ($($missingInEntities.Count)) **ACTION REQUISE**: Ces tables existent dans les migrations mais n'ont pas d'entité Java! **Recommandation**: Supprimer ces tables des migrations ou créer les entités manquantes. | Table | Migration(s) | |-------|--------------| "@ foreach ($item in $missingInEntities | Sort-Object { $_.Table }) { $report += "`n| ``$($item.Table)`` | $($item.Migrations) |" } } $report += @" --- ## Duplications de CREATE TABLE "@ $duplicates = $allTables.GetEnumerator() | Where-Object { $_.Value.Count -gt 1 } if ($duplicates.Count -gt 0) { $report += "**ACTION REQUISE**: Ces tables sont créées dans plusieurs migrations!`n`n" $report += "| Table | Migrations |`n" $report += "|-------|------------|`n" foreach ($dup in $duplicates | Sort-Object { $_.Key }) { $report += "| ``$($dup.Key)`` | $($dup.Value -join ", ") |`n" } } else { $report += "✅ Aucune duplication détectée.`n" } $report += @" --- ## Recommandations 1. **Supprimer les tables obsolètes**: Tables sans entité doivent être supprimées des migrations 2. **Créer les tables manquantes**: Ajouter les CREATE TABLE pour les entités sans table 3. **Éliminer les duplications**: Garder seulement une version de chaque CREATE TABLE (de préférence avec IF NOT EXISTS) 4. **Nettoyer V1**: Supprimer toutes les sections redondantes (CREATE/DROP/CREATE) 5. **Vérifier les FK**: S'assurer que toutes les clés étrangères référencent des tables existantes --- *Généré par audit-migrations.ps1 - Lions Dev* "@ # Sauvegarder le rapport $reportPath = "$projectRoot\AUDIT_MIGRATIONS.md" $report | Out-File -FilePath $reportPath -Encoding UTF8 Write-Host "`n✅ Rapport sauvegardé: $reportPath" -ForegroundColor Green # Afficher le résumé Write-Host "`n╔══════════════════════════════════════════════════════════╗" -ForegroundColor Cyan Write-Host "║ RÉSUMÉ ║" -ForegroundColor Cyan Write-Host "╚══════════════════════════════════════════════════════════╝" -ForegroundColor Cyan Write-Host " Entités JPA: $($entities.Count)" -ForegroundColor White Write-Host " Tables migrations: $($allTables.Keys.Count)" -ForegroundColor White Write-Host " ✅ OK: $($ok.Count)" -ForegroundColor Green if ($missingInMigrations.Count -gt 0) { Write-Host " ⚠️ Entités sans table: $($missingInMigrations.Count)" -ForegroundColor Yellow } if ($missingInEntities.Count -gt 0) { Write-Host " ⚠️ Tables sans entité: $($missingInEntities.Count)" -ForegroundColor Yellow } if ($duplicates.Count -gt 0) { Write-Host " ⚠️ Duplications: $($duplicates.Count)" -ForegroundColor Red } Write-Host "`nOuvrir le rapport complet? (Y/N)" -ForegroundColor Cyan $answer = Read-Host if ($answer -eq "Y" -or $answer -eq "y") { Start-Process $reportPath }