modules/devops/Write-MigrationScript.ps1
|
param( [string]$ProjectName, [string]$OrmMode, [string]$DbProvider, [string]$OutputPath ) . (Join-Path (Split-Path $MyInvocation.MyCommand.Path) "..\core\Utils.ps1") # Migration script sadece EFCore veya Hybrid modda üretilir if ($OrmMode -notmatch "EFCore|Hybrid") { return } $migratePs1Content = @' #Requires -Version 5.1 # EF Core Migration Helper — {P} # Kullanim: .\migrate.ps1 [-MigrationName <ad>] [-Revert] param( [string]$MigrationName = "Initial", [switch]$Revert ) # Self-healing dotnet-ef tool check $dotnetEfInstalled = dotnet tool list -g | Select-String "dotnet-ef" if (-not $dotnetEfInstalled) { Write-Host "dotnet-ef araci kuruluyor..." -ForegroundColor Yellow dotnet tool install --global dotnet-ef } $userProfile = [System.Environment]::GetFolderPath('UserProfile') $globalToolsPath = Join-Path $userProfile ".dotnet\tools" if ($env:PATH -notlike "*$globalToolsPath*") { $env:PATH = "$env:PATH;$globalToolsPath" } # Resolve relative paths using PSScriptRoot $scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path $dockerDir = Split-Path $scriptDir -Parent $projectRootDir = Split-Path $dockerDir -Parent $backendDir = Join-Path $projectRootDir "{P}-backend" if (-not (Test-Path $backendDir)) { $backendDir = $projectRootDir } $persistenceProj = Join-Path $backendDir "src\{P}.Persistence" $startupProj = Join-Path $backendDir "src\{P}.WebApi" if ($Revert) { Write-Host "Son migration geri aliniyor..." -ForegroundColor Yellow dotnet ef database update 0 ` --project $persistenceProj ` --startup-project $startupProj Write-Host "Tum migrasyonlar siliniyor..." -ForegroundColor Yellow dotnet ef migrations remove ` --project $persistenceProj ` --startup-project $startupProj Write-Host "Tamamlandi." -ForegroundColor Green } else { Write-Host "Migration olusturuluyor: $MigrationName" -ForegroundColor Cyan dotnet ef migrations add $MigrationName ` --project $persistenceProj ` --startup-project $startupProj ` --output-dir Migrations Write-Host "Veritabani guncelleniyor..." -ForegroundColor Cyan dotnet ef database update ` --project $persistenceProj ` --startup-project $startupProj Write-Host "Tamamlandi." -ForegroundColor Green } '@.Replace("{P}", $ProjectName) $migrateShContent = @' #!/bin/bash # EF Core Migration Helper — {P} # Kullanim: ./migrate.sh [MigrationName] [--revert] MIGRATION_NAME=${1:-Initial} # Self-healing dotnet-ef check if ! command -v dotnet-ef &> /dev/null then echo "dotnet-ef araci kuruluyor..." dotnet tool install --global dotnet-ef export PATH="$PATH:$HOME/.dotnet/tools" fi # Resolve paths dynamically using BASH_SOURCE SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" DOCKER_DIR="$( dirname "$SCRIPT_DIR" )" PROJECT_ROOT_DIR="$( dirname "$DOCKER_DIR" )" BACKEND_DIR="$PROJECT_ROOT_DIR/{P}-backend" if [ ! -d "$BACKEND_DIR" ]; then BACKEND_DIR="$PROJECT_ROOT_DIR" fi PERSISTENCE_PROJ="$BACKEND_DIR/src/{P}.Persistence" STARTUP_PROJ="$BACKEND_DIR/src/{P}.WebApi" if [ "$2" = "--revert" ]; then echo "Son migration geri aliniyor..." dotnet ef database update 0 \ --project "$PERSISTENCE_PROJ" \ --startup-project "$STARTUP_PROJ" dotnet ef migrations remove \ --project "$PERSISTENCE_PROJ" \ --startup-project "$STARTUP_PROJ" echo "Tamamlandi." else echo "Migration olusturuluyor: $MIGRATION_NAME" dotnet ef migrations add "$MIGRATION_NAME" \ --project "$PERSISTENCE_PROJ" \ --startup-project "$STARTUP_PROJ" \ --output-dir Migrations echo "Veritabani guncelleniyor..." dotnet ef database update \ --project "$PERSISTENCE_PROJ" \ --startup-project "$STARTUP_PROJ" echo "Tamamlandi." fi '@.Replace("{P}", $ProjectName) $dbFolder = if ($DbProvider -eq "Postgres") { "postgresql" } else { "sqlserver" } $targetDir = Join-Path $OutputPath "$ProjectName-docker\$dbFolder" if (-not $Global:DryRun -and -not (Test-Path $targetDir)) { New-Item -ItemType Directory -Path $targetDir -Force | Out-Null } Write-CoreFile (Join-Path $targetDir "migrate.ps1") $migratePs1Content Write-CoreFile (Join-Path $targetDir "migrate.sh") $migrateShContent # Automatic Initial Migration Generation for EFCore & Hybrid modes if (-not $Global:DryRun) { $userProfile = [System.Environment]::GetFolderPath('UserProfile') $globalToolsPath = Join-Path $userProfile ".dotnet\tools" if ($env:PATH -notlike "*$globalToolsPath*") { $env:PATH = "$env:PATH;$globalToolsPath" } $efCheck = Get-Command "dotnet-ef" -ErrorAction SilentlyContinue if (-not $efCheck) { try { dotnet tool install --global dotnet-ef --erroraction SilentlyContinue | Out-Null } catch {} } $backendDir = Join-Path $OutputPath "$ProjectName-backend" if (-not (Test-Path $backendDir)) { $backendDir = $OutputPath } $persistenceProjPath = Join-Path $backendDir "src\$ProjectName.Persistence\$ProjectName.Persistence.csproj" $webApiProjPath = Join-Path $backendDir "src\$ProjectName.WebApi\$ProjectName.WebApi.csproj" $migrationsDir = Join-Path $backendDir "src\$ProjectName.Persistence\Migrations" $migrationSuccess = $false try { dotnet restore $webApiProjPath --nologo -v q | Out-Null dotnet build $webApiProjPath -c Debug --nologo -v q | Out-Null $res = dotnet ef migrations add InitialCreate --project $persistenceProjPath --startup-project $webApiProjPath --output-dir Migrations 2>&1 $createdFiles = Get-ChildItem -Path $migrationsDir -Filter "*InitialCreate*.cs" -ErrorAction SilentlyContinue if ($createdFiles -and $createdFiles.Count -gt 0) { $migrationSuccess = $true } } catch {} # Static fallback generation if dotnet-ef tool failed or unavailable if (-not $migrationSuccess) { if (-not (Test-Path $migrationsDir)) { New-Item -ItemType Directory -Path $migrationsDir -Force | Out-Null } $snapshotContent = @' // <auto-generated /> using System; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using {P}.Persistence.Context; #nullable disable namespace {P}.Persistence.Migrations { [DbContext(typeof(AppDbContext))] partial class AppDbContextModelSnapshot : ModelSnapshot { protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder .HasAnnotation("ProductVersion", "10.0.0"); modelBuilder.ApplyConfigurationsFromAssembly(typeof(AppDbContext).Assembly); #pragma warning restore 612, 618 } } } '@.Replace("{P}", $ProjectName) $initialCreateContent = @' using System; using Microsoft.EntityFrameworkCore.Migrations; #nullable disable namespace {P}.Persistence.Migrations { /// <inheritdoc /> public partial class InitialCreate : Migration { /// <inheritdoc /> protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.CreateTable( name: "Users", columns: table => new { Id = table.Column<int>(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), Username = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false), PasswordHash = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false), Email = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true), Role = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: false, defaultValue: "User"), IsActive = table.Column<bool>(type: "bit", nullable: false, defaultValue: true), IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false), DeletedAt = table.Column<DateTime>(type: "datetime2", nullable: true), CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false), UpdatedAt = table.Column<DateTime>(type: "datetime2", nullable: false) }, constraints: table => { table.PrimaryKey("PK_Users", x => x.Id); }); migrationBuilder.CreateTable( name: "Products", columns: table => new { Id = table.Column<int>(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), Name = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false), Price = table.Column<decimal>(type: "decimal(18,2)", nullable: false, defaultValue: 0m), IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false), DeletedAt = table.Column<DateTime>(type: "datetime2", nullable: true), CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false), UpdatedAt = table.Column<DateTime>(type: "datetime2", nullable: false) }, constraints: table => { table.PrimaryKey("PK_Products", x => x.Id); }); } /// <inheritdoc /> protected override void Down(MigrationBuilder migrationBuilder) { migrationBuilder.DropTable(name: "Products"); migrationBuilder.DropTable(name: "Users"); } } } '@.Replace("{P}", $ProjectName) $designerContent = @' // <auto-generated /> using System; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using {P}.Persistence.Context; #nullable disable namespace {P}.Persistence.Migrations { [DbContext(typeof(AppDbContext))] [Migration("20260101000000_InitialCreate")] partial class InitialCreate { /// <inheritdoc /> protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder .HasAnnotation("ProductVersion", "10.0.0"); modelBuilder.ApplyConfigurationsFromAssembly(typeof(AppDbContext).Assembly); #pragma warning restore 612, 618 } } } '@.Replace("{P}", $ProjectName) Write-CoreFile (Join-Path $migrationsDir "AppDbContextModelSnapshot.cs") $snapshotContent Write-CoreFile (Join-Path $migrationsDir "20260101000000_InitialCreate.cs") $initialCreateContent Write-CoreFile (Join-Path $migrationsDir "20260101000000_InitialCreate.Designer.cs") $designerContent } } |