<# .PARAMETER CheckOnly Download and verify the prod DB without building or deploying. #> param([switch]$CheckOnly) $ErrorActionPreference = "Stop" # Load .env from script directory $envFile = Join-Path $PSScriptRoot ".env" if (Test-Path $envFile) { Get-Content $envFile | Where-Object { $_ -match '^\s*[^#]\S+=\S' } | ForEach-Object { $k, $v = $_ -split '=', 2 [System.Environment]::SetEnvironmentVariable($k.Trim(), $v.Trim(), 'Process') } } $ACR = "koogleacr" $APP = "ka-note" $RG = "rg-koogle-prod" $IMAGE = "$ACR.azurecr.io/${APP}:latest" # Read current version (don't bump yet -- only after DB check passes) $versionFile = Join-Path $PSScriptRoot "VERSION" $current = (Get-Content $versionFile -Raw).Trim() if ($CheckOnly) { $VERSION = $current } else { $parts = $current -split '\.' $parts[2] = [int]$parts[2] + 1 $VERSION = $parts -join '.' } $checkLabel = if ($CheckOnly) { " [check-only]" } else { "" } Write-Host "=== Version: $VERSION$checkLabel ===" -ForegroundColor Yellow Write-Host "=== Backup DB from Prod ===" -ForegroundColor Cyan $KuduToken = az account get-access-token --resource "https://management.azure.com" --query accessToken -o tsv if ($LASTEXITCODE -ne 0) { throw "Failed to get Azure access token" } $KuduDbUrl = "https://${APP}.scm.azurewebsites.net/api/vfs/data/ka-note.db" $BackupDir = Join-Path $PSScriptRoot "backups" $null = New-Item -ItemType Directory -Path $BackupDir -Force $BackupFile = Join-Path $BackupDir ("ka-note-pre-deploy-$VERSION.db") Write-Host " Downloading ka-note.db from prod..." -ForegroundColor DarkGray try { Invoke-WebRequest -Uri $KuduDbUrl ` -Headers @{ Authorization = "Bearer $KuduToken" } ` -OutFile $BackupFile -UseBasicParsing } catch { throw "Kudu DB download failed: $_" } $DbSize = (Get-Item $BackupFile).Length Write-Host " Downloaded: $([math]::Round($DbSize/1KB,1)) KB" -ForegroundColor DarkGray if ($DbSize -lt 4096) { throw "DB backup is suspiciously small ($DbSize bytes) - aborting deploy" } # Verify with sqlite3 (must be in PATH) $IntegrityResult = & sqlite3 $BackupFile "PRAGMA integrity_check;" 2>&1 if ($LASTEXITCODE -ne 0 -or $IntegrityResult -ne 'ok') { throw "DB integrity_check FAILED: $IntegrityResult - aborting deploy. Backup saved at $BackupFile" } Write-Host " integrity_check: ok ($([math]::Round($DbSize/1KB,1)) KB)" -ForegroundColor Green if ($CheckOnly) { Write-Host "" Write-Host "=== Check passed -- no deploy performed ===" -ForegroundColor Green Write-Host " Backup: $BackupFile" -ForegroundColor DarkGray Write-Host "" exit 0 } # Bump version now that DB check passed Set-Content $versionFile $VERSION -Encoding UTF8 -NoNewline Write-Host "=== Generate migrations ===" -ForegroundColor Cyan Push-Location server npx drizzle-kit generate Pop-Location if ($LASTEXITCODE -ne 0) { throw "Migration generation failed" } Write-Host "=== Login to ACR ===" -ForegroundColor Cyan $token = (az acr login --name $ACR --expose-token --output tsv --query accessToken) if ($LASTEXITCODE -ne 0) { throw "ACR token fetch failed" } $token | docker login "$ACR.azurecr.io" --username 00000000-0000-0000-0000-000000000000 --password-stdin if ($LASTEXITCODE -ne 0) { throw "ACR login failed" } Write-Host "=== Build Docker image ===" -ForegroundColor Cyan docker build -t $IMAGE ` --build-arg VITE_AZURE_CLIENT_ID=$env:AZURE_CLIENT_ID ` --build-arg VITE_AZURE_TENANT_ID=$env:AZURE_TENANT_ID ` --build-arg APP_VERSION=$VERSION ` . if ($LASTEXITCODE -ne 0) { throw "Docker build failed" } Write-Host "=== Push to ACR ===" -ForegroundColor Cyan docker push $IMAGE if ($LASTEXITCODE -ne 0) { throw "Docker push failed" } Write-Host "=== Set App Service environment ===" -ForegroundColor Cyan az webapp config appsettings set --name $APP --resource-group $RG --settings ` AZURE_CLIENT_ID=$env:AZURE_CLIENT_ID ` AZURE_TENANT_ID=$env:AZURE_TENANT_ID | Out-Null Write-Host "=== Graceful DB shutdown ===" -ForegroundColor Cyan $AppUrl = "https://$APP.azurewebsites.net" if ($env:KA_NOTE_DEPLOY_API_KEY) { try { $shutdownResult = Invoke-RestMethod -Uri "$AppUrl/api/admin/shutdown" -Method POST ` -Headers @{ Authorization = "Bearer $env:KA_NOTE_DEPLOY_API_KEY" } ` -UseBasicParsing -TimeoutSec 10 Write-Host " Shutdown response: $($shutdownResult.message)" -ForegroundColor DarkGray Start-Sleep -Seconds 3 } catch { Write-Host " Shutdown call failed (continuing anyway): $_" -ForegroundColor Yellow } } else { Write-Host " KA_NOTE_DEPLOY_API_KEY not set, skipping graceful shutdown" -ForegroundColor Yellow } Write-Host "=== Restart App Service ===" -ForegroundColor Cyan az webapp restart --name $APP --resource-group $RG Write-Host "=== Done! $VERSION deployed ===" -ForegroundColor Green Write-Host "Check: https://$APP.azurewebsites.net"