351 lines
12 KiB
PowerShell
351 lines
12 KiB
PowerShell
# Deployment Checklist Script for Miracles In Motion
|
|
# This script verifies all prerequisites are met before deployment
|
|
|
|
param(
|
|
[Parameter(Mandatory=$false)]
|
|
[string]$ResourceGroupName = "rg-miraclesinmotion-prod",
|
|
|
|
[Parameter(Mandatory=$false)]
|
|
[string]$StaticWebAppName = "",
|
|
|
|
[Parameter(Mandatory=$false)]
|
|
[string]$FunctionAppName = "",
|
|
|
|
[Parameter(Mandatory=$false)]
|
|
[switch]$SkipCloudflare = $false,
|
|
|
|
[Parameter(Mandatory=$false)]
|
|
[switch]$SkipStripe = $false
|
|
)
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
# Colors for output
|
|
function Write-ColorOutput($ForegroundColor) {
|
|
$fc = $host.UI.RawUI.ForegroundColor
|
|
$host.UI.RawUI.ForegroundColor = $ForegroundColor
|
|
if ($args) {
|
|
Write-Output $args
|
|
}
|
|
$host.UI.RawUI.ForegroundColor = $fc
|
|
}
|
|
|
|
Write-ColorOutput Green "🚀 Deployment Prerequisites Checklist"
|
|
Write-Output "=========================================="
|
|
Write-Output ""
|
|
|
|
$allChecksPassed = $true
|
|
$checks = @()
|
|
|
|
# Function to add check result
|
|
function Add-Check {
|
|
param(
|
|
[string]$Name,
|
|
[bool]$Passed,
|
|
[string]$Message = ""
|
|
)
|
|
|
|
$checks += @{
|
|
Name = $Name
|
|
Passed = $Passed
|
|
Message = $Message
|
|
}
|
|
|
|
if (-not $Passed) {
|
|
$script:allChecksPassed = $false
|
|
}
|
|
}
|
|
|
|
# 1. Azure CLI Check
|
|
Write-ColorOutput Cyan "1. Checking Azure CLI..."
|
|
try {
|
|
$azVersion = az version --output json | ConvertFrom-Json
|
|
Add-Check "Azure CLI" $true "Version: $($azVersion.'azure-cli')"
|
|
Write-ColorOutput Green " ✅ Azure CLI installed"
|
|
} catch {
|
|
Add-Check "Azure CLI" $false "Azure CLI not found. Install from: https://docs.microsoft.com/cli/azure/install-azure-cli"
|
|
Write-ColorOutput Red " ❌ Azure CLI not found"
|
|
}
|
|
Write-Output ""
|
|
|
|
# 2. Azure Login Check
|
|
Write-ColorOutput Cyan "2. Checking Azure login status..."
|
|
try {
|
|
$account = az account show --output json 2>$null | ConvertFrom-Json
|
|
if ($account) {
|
|
Add-Check "Azure Login" $true "Logged in as: $($account.user.name)"
|
|
Write-ColorOutput Green " ✅ Logged in to Azure"
|
|
Write-Output " Subscription: $($account.name)"
|
|
Write-Output " Tenant ID: $($account.tenantId)"
|
|
} else {
|
|
throw "Not logged in"
|
|
}
|
|
} catch {
|
|
Add-Check "Azure Login" $false "Not logged in to Azure. Run: az login"
|
|
Write-ColorOutput Red " ❌ Not logged in to Azure"
|
|
}
|
|
Write-Output ""
|
|
|
|
# 3. Resource Group Check
|
|
Write-ColorOutput Cyan "3. Checking resource group..."
|
|
try {
|
|
$rg = az group show --name $ResourceGroupName --output json 2>$null | ConvertFrom-Json
|
|
if ($rg) {
|
|
Add-Check "Resource Group" $true "Resource group exists: $($rg.name)"
|
|
Write-ColorOutput Green " ✅ Resource group exists"
|
|
Write-Output " Location: $($rg.location)"
|
|
} else {
|
|
throw "Resource group not found"
|
|
}
|
|
} catch {
|
|
Add-Check "Resource Group" $false "Resource group not found: $ResourceGroupName"
|
|
Write-ColorOutput Red " ❌ Resource group not found"
|
|
}
|
|
Write-Output ""
|
|
|
|
# 4. Static Web App Check
|
|
Write-ColorOutput Cyan "4. Checking Static Web App..."
|
|
if ([string]::IsNullOrEmpty($StaticWebAppName)) {
|
|
# Try to find Static Web App
|
|
$swa = az staticwebapp list --resource-group $ResourceGroupName --output json 2>$null | ConvertFrom-Json | Select-Object -First 1
|
|
if ($swa) {
|
|
$StaticWebAppName = $swa.name
|
|
}
|
|
}
|
|
|
|
if (-not [string]::IsNullOrEmpty($StaticWebAppName)) {
|
|
try {
|
|
$swa = az staticwebapp show --name $StaticWebAppName --resource-group $ResourceGroupName --output json 2>$null | ConvertFrom-Json
|
|
if ($swa) {
|
|
Add-Check "Static Web App" $true "Static Web App exists: $($swa.name)"
|
|
Write-ColorOutput Green " ✅ Static Web App exists"
|
|
Write-Output " URL: https://$($swa.defaultHostname)"
|
|
} else {
|
|
throw "Static Web App not found"
|
|
}
|
|
} catch {
|
|
Add-Check "Static Web App" $false "Static Web App not found: $StaticWebAppName"
|
|
Write-ColorOutput Red " ❌ Static Web App not found"
|
|
}
|
|
} else {
|
|
Add-Check "Static Web App" $false "Static Web App name not specified"
|
|
Write-ColorOutput Red " ❌ Static Web App name not specified"
|
|
}
|
|
Write-Output ""
|
|
|
|
# 5. Function App Check
|
|
Write-ColorOutput Cyan "5. Checking Function App..."
|
|
if ([string]::IsNullOrEmpty($FunctionAppName)) {
|
|
# Try to find Function App
|
|
$fa = az functionapp list --resource-group $ResourceGroupName --output json 2>$null | ConvertFrom-Json | Select-Object -First 1
|
|
if ($fa) {
|
|
$FunctionAppName = $fa.name
|
|
}
|
|
}
|
|
|
|
if (-not [string]::IsNullOrEmpty($FunctionAppName)) {
|
|
try {
|
|
$fa = az functionapp show --name $FunctionAppName --resource-group $ResourceGroupName --output json 2>$null | ConvertFrom-Json
|
|
if ($fa) {
|
|
Add-Check "Function App" $true "Function App exists: $($fa.name)"
|
|
Write-ColorOutput Green " ✅ Function App exists"
|
|
Write-Output " URL: https://$($fa.defaultHostName)"
|
|
} else {
|
|
throw "Function App not found"
|
|
}
|
|
} catch {
|
|
Add-Check "Function App" $false "Function App not found: $FunctionAppName"
|
|
Write-ColorOutput Red " ❌ Function App not found"
|
|
}
|
|
} else {
|
|
Add-Check "Function App" $false "Function App name not specified"
|
|
Write-ColorOutput Red " ❌ Function App name not specified"
|
|
}
|
|
Write-Output ""
|
|
|
|
# 6. Key Vault Check
|
|
Write-ColorOutput Cyan "6. Checking Key Vault..."
|
|
try {
|
|
$kv = az keyvault list --resource-group $ResourceGroupName --output json 2>$null | ConvertFrom-Json | Select-Object -First 1
|
|
if ($kv) {
|
|
Add-Check "Key Vault" $true "Key Vault exists: $($kv.name)"
|
|
Write-ColorOutput Green " ✅ Key Vault exists"
|
|
|
|
# Check for required secrets
|
|
$requiredSecrets = @("stripe-secret-key", "azure-client-id", "azure-tenant-id")
|
|
$missingSecrets = @()
|
|
|
|
foreach ($secret in $requiredSecrets) {
|
|
try {
|
|
$secretValue = az keyvault secret show --vault-name $kv.name --name $secret --output json 2>$null | ConvertFrom-Json
|
|
if (-not $secretValue) {
|
|
$missingSecrets += $secret
|
|
}
|
|
} catch {
|
|
$missingSecrets += $secret
|
|
}
|
|
}
|
|
|
|
if ($missingSecrets.Count -eq 0) {
|
|
Write-ColorOutput Green " ✅ Required secrets present"
|
|
} else {
|
|
Write-ColorOutput Yellow " ⚠️ Missing secrets: $($missingSecrets -join ', ')"
|
|
}
|
|
} else {
|
|
throw "Key Vault not found"
|
|
}
|
|
} catch {
|
|
Add-Check "Key Vault" $false "Key Vault not found"
|
|
Write-ColorOutput Red " ❌ Key Vault not found"
|
|
}
|
|
Write-Output ""
|
|
|
|
# 7. Cosmos DB Check
|
|
Write-ColorOutput Cyan "7. Checking Cosmos DB..."
|
|
try {
|
|
$cosmos = az cosmosdb list --resource-group $ResourceGroupName --output json 2>$null | ConvertFrom-Json | Select-Object -First 1
|
|
if ($cosmos) {
|
|
Add-Check "Cosmos DB" $true "Cosmos DB exists: $($cosmos.name)"
|
|
Write-ColorOutput Green " ✅ Cosmos DB exists"
|
|
} else {
|
|
throw "Cosmos DB not found"
|
|
}
|
|
} catch {
|
|
Add-Check "Cosmos DB" $false "Cosmos DB not found"
|
|
Write-ColorOutput Red " ❌ Cosmos DB not found"
|
|
}
|
|
Write-Output ""
|
|
|
|
# 8. Application Insights Check
|
|
Write-ColorOutput Cyan "8. Checking Application Insights..."
|
|
try {
|
|
$ai = az monitor app-insights component show --app $ResourceGroupName --output json 2>$null | ConvertFrom-Json
|
|
if (-not $ai) {
|
|
# Try alternative method
|
|
$ai = az resource list --resource-group $ResourceGroupName --resource-type "Microsoft.Insights/components" --output json 2>$null | ConvertFrom-Json | Select-Object -First 1
|
|
}
|
|
if ($ai) {
|
|
Add-Check "Application Insights" $true "Application Insights exists"
|
|
Write-ColorOutput Green " ✅ Application Insights exists"
|
|
} else {
|
|
throw "Application Insights not found"
|
|
}
|
|
} catch {
|
|
Add-Check "Application Insights" $false "Application Insights not found"
|
|
Write-ColorOutput Red " ❌ Application Insights not found"
|
|
}
|
|
Write-Output ""
|
|
|
|
# 9. Azure AD App Registration Check
|
|
Write-ColorOutput Cyan "9. Checking Azure AD App Registration..."
|
|
try {
|
|
$appReg = az ad app list --display-name "Miracles In Motion Web App" --output json 2>$null | ConvertFrom-Json | Select-Object -First 1
|
|
if ($appReg) {
|
|
Add-Check "Azure AD App Registration" $true "App Registration exists: $($appReg.appId)"
|
|
Write-ColorOutput Green " ✅ Azure AD App Registration exists"
|
|
Write-Output " App ID: $($appReg.appId)"
|
|
|
|
# Check redirect URIs
|
|
if ($appReg.web.redirectUris) {
|
|
Write-Output " Redirect URIs: $($appReg.web.redirectUris.Count)"
|
|
}
|
|
} else {
|
|
throw "App Registration not found"
|
|
}
|
|
} catch {
|
|
Add-Check "Azure AD App Registration" $false "Azure AD App Registration not found"
|
|
Write-ColorOutput Red " ❌ Azure AD App Registration not found"
|
|
}
|
|
Write-Output ""
|
|
|
|
# 10. Cloudflare Check
|
|
if (-not $SkipCloudflare) {
|
|
Write-ColorOutput Cyan "10. Checking Cloudflare configuration..."
|
|
try {
|
|
# Check DNS resolution
|
|
$dnsResult = Resolve-DnsName -Name "miraclesinmotion.org" -ErrorAction SilentlyContinue
|
|
if ($dnsResult) {
|
|
Add-Check "Cloudflare DNS" $true "DNS resolution working"
|
|
Write-ColorOutput Green " ✅ DNS resolution working"
|
|
} else {
|
|
Add-Check "Cloudflare DNS" $false "DNS resolution failed"
|
|
Write-ColorOutput Red " ❌ DNS resolution failed"
|
|
}
|
|
} catch {
|
|
Add-Check "Cloudflare DNS" $false "Could not verify DNS"
|
|
Write-ColorOutput Yellow " ⚠️ Could not verify DNS"
|
|
}
|
|
Write-Output ""
|
|
}
|
|
|
|
# 11. Stripe Check
|
|
if (-not $SkipStripe) {
|
|
Write-ColorOutput Cyan "11. Checking Stripe configuration..."
|
|
try {
|
|
if ($kv) {
|
|
$stripeKey = az keyvault secret show --vault-name $kv.name --name "stripe-secret-key" --output json 2>$null | ConvertFrom-Json
|
|
if ($stripeKey -and $stripeKey.value -like "sk_live_*") {
|
|
Add-Check "Stripe Configuration" $true "Stripe keys configured"
|
|
Write-ColorOutput Green " ✅ Stripe keys configured"
|
|
} else {
|
|
Add-Check "Stripe Configuration" $false "Stripe keys not configured or not production keys"
|
|
Write-ColorOutput Yellow " ⚠️ Stripe keys not configured or not production keys"
|
|
}
|
|
} else {
|
|
Add-Check "Stripe Configuration" $false "Key Vault not available"
|
|
Write-ColorOutput Yellow " ⚠️ Key Vault not available"
|
|
}
|
|
} catch {
|
|
Add-Check "Stripe Configuration" $false "Could not verify Stripe configuration"
|
|
Write-ColorOutput Yellow " ⚠️ Could not verify Stripe configuration"
|
|
}
|
|
Write-Output ""
|
|
}
|
|
|
|
# 12. Environment Variables Check
|
|
Write-ColorOutput Cyan "12. Checking environment variables..."
|
|
$envFile = ".env.production"
|
|
if (Test-Path $envFile) {
|
|
Add-Check "Environment File" $true "Environment file exists"
|
|
Write-ColorOutput Green " ✅ Environment file exists"
|
|
} else {
|
|
Add-Check "Environment File" $false "Environment file not found: $envFile"
|
|
Write-ColorOutput Yellow " ⚠️ Environment file not found"
|
|
}
|
|
Write-Output ""
|
|
|
|
# Summary
|
|
Write-Output ""
|
|
Write-ColorOutput Cyan "=========================================="
|
|
Write-ColorOutput Cyan "Summary"
|
|
Write-ColorOutput Cyan "=========================================="
|
|
Write-Output ""
|
|
|
|
$passedChecks = ($checks | Where-Object { $_.Passed -eq $true }).Count
|
|
$totalChecks = $checks.Count
|
|
|
|
Write-Output "Passed: $passedChecks / $totalChecks"
|
|
Write-Output ""
|
|
|
|
foreach ($check in $checks) {
|
|
if ($check.Passed) {
|
|
Write-ColorOutput Green "✅ $($check.Name)"
|
|
} else {
|
|
Write-ColorOutput Red "❌ $($check.Name)"
|
|
if ($check.Message) {
|
|
Write-Output " $($check.Message)"
|
|
}
|
|
}
|
|
}
|
|
|
|
Write-Output ""
|
|
|
|
if ($allChecksPassed) {
|
|
Write-ColorOutput Green "✅ All checks passed! Ready for deployment."
|
|
exit 0
|
|
} else {
|
|
Write-ColorOutput Red "❌ Some checks failed. Please fix the issues before deploying."
|
|
exit 1
|
|
}
|
|
|