# Deploy SOLUTION_ERP lên IIS Windows Server. # Chạy trên target server với admin privilege. # # Usage: # .\scripts\deploy-iis.ps1 -Artifact "C:\Deploy\solution-erp-20260421.zip" -Site "SolutionErpApi" # # Workflow: # 1. Stop app pool # 2. Backup current wwwroot # 3. Extract artifact → publish path # 4. Run EF migration (dotnet SolutionErp.Api.dll -- --migrate-only) # 5. Start app pool # 6. Health check /health/ready — rollback nếu fail param( [Parameter(Mandatory=$true)] [string]$Artifact, [Parameter(Mandatory=$true)] [string]$Site, [string]$PublishPath = "C:\inetpub\solution-erp\api", [string]$AppPoolName = "SolutionErpApi", [string]$HealthUrl = "https://localhost/health/ready", [int]$HealthTimeoutSec = 30 ) $ErrorActionPreference = 'Stop' Import-Module WebAdministration function Write-Step($msg) { Write-Host "==> $msg" -ForegroundColor Cyan } Write-Step "Deploy $Artifact -> $PublishPath" # 1. Check prereqs if (-not (Test-Path $Artifact)) { throw "Artifact khong ton tai: $Artifact" } if (-not (Test-Path $PublishPath)) { New-Item -ItemType Directory -Force -Path $PublishPath | Out-Null } # 2. Stop app pool Write-Step "Stop app pool $AppPoolName" if (Test-Path "IIS:\AppPools\$AppPoolName") { Stop-WebAppPool -Name $AppPoolName -ErrorAction SilentlyContinue Start-Sleep -Seconds 3 } else { Write-Warning "App pool $AppPoolName chua ton tai. Tao bang cach:" Write-Host " New-WebAppPool -Name '$AppPoolName'" -ForegroundColor Yellow Write-Host " Set-ItemProperty IIS:\AppPools\$AppPoolName -Name managedRuntimeVersion -Value ''" -ForegroundColor Yellow throw "App pool missing" } # 3. Backup current $BackupDir = "C:\inetpub\solution-erp\backups\api-$(Get-Date -Format 'yyyyMMdd-HHmmss')" if (Test-Path "$PublishPath\SolutionErp.Api.dll") { Write-Step "Backup current -> $BackupDir" New-Item -ItemType Directory -Force -Path $BackupDir | Out-Null Copy-Item -Path "$PublishPath\*" -Destination $BackupDir -Recurse -Force } else { Write-Host " (Khong co build cu, skip backup)" } # 4. Clean + extract new artifact Write-Step "Clean + extract $Artifact" Get-ChildItem -Path $PublishPath -Recurse -Force | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue Expand-Archive -Path $Artifact -DestinationPath $PublishPath -Force # 5. Apply EF migrations (call dotnet SolutionErp.Api.dll với arg --migrate-only — Phase 5 impl) Write-Step "Apply EF migrations" Push-Location $PublishPath try { # Note: Program.cs check `args.Contains("--no-db-init")`. Default khi start IIS KHONG co arg # → migrations tu chay khi app boot len. Neu muon run migration truoc khi app start: # dotnet SolutionErp.Api.dll --migrate-only (TODO: thêm --migrate-only flag trong Program.cs) Write-Host " (skip — migrations chay tu dong khi app start lan dau)" } finally { Pop-Location } # 6. Start app pool Write-Step "Start app pool" Start-WebAppPool -Name $AppPoolName # 7. Health check loop Write-Step "Health check $HealthUrl (timeout ${HealthTimeoutSec}s)" $deadline = (Get-Date).AddSeconds($HealthTimeoutSec) $ok = $false while ((Get-Date) -lt $deadline) { try { $resp = Invoke-WebRequest -Uri $HealthUrl -UseBasicParsing -SkipCertificateCheck -TimeoutSec 5 if ($resp.StatusCode -eq 200) { $ok = $true; break } } catch { Start-Sleep -Seconds 2 } } if ($ok) { Write-Host "`nDeploy SUCCESS" -ForegroundColor Green } else { Write-Warning "`nHealth check FAIL. Rollback thu cong:" Write-Host " Stop-WebAppPool $AppPoolName" Write-Host " Copy-Item $BackupDir\* $PublishPath\* -Recurse -Force" Write-Host " Start-WebAppPool $AppPoolName" exit 1 }