# 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 }