Files
Htmx/GCR/run-all.ps1
T

186 lines
5.9 KiB
PowerShell

#Requires -Version 5.1
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
param(
[switch]$Yes
)
$RootDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$EnvFile = Join-Path $RootDir ".env"
function Confirm-Run {
param(
[string]$Label,
[string]$ScriptPath
)
if ($Yes) {
Write-Host "[x] $Label not done yet. Running $ScriptPath (-Yes enabled)..."
& $ScriptPath
return
}
$answer = Read-Host "[x] $Label not done yet. Run now? [y/N]"
if ($answer -match '^[Yy]$') {
& $ScriptPath
}
}
function Get-EnvConfig {
if (-not (Test-Path $EnvFile)) {
throw "GCR/.env not found. Copy GCR/.env.example to GCR/.env first."
}
$cfg = @{}
foreach ($line in Get-Content $EnvFile) {
if ($line -match '^\s*$' -or $line -match '^\s*#') { continue }
if ($line -match '^([^=]+)=(.*)$') {
$cfg[$Matches[1].Trim()] = $Matches[2].Trim()
}
}
foreach ($key in @('GCP_PROJECT_ID', 'GCP_REGION', 'GCP_REPOSITORY', 'SERVICE_NAME')) {
if (-not $cfg[$key]) {
throw "$key is not set in GCR/.env"
}
}
return $cfg
}
function Test-GcloudInstalled {
return [bool](Get-Command gcloud -ErrorAction SilentlyContinue)
}
function Test-Login {
param([hashtable]$Cfg)
$activeAccount = (gcloud auth list --filter=status:ACTIVE --format="value(account)" 2>$null | Select-Object -First 1)
$currentProject = (gcloud config get-value project 2>$null)
$currentRegion = (gcloud config get-value run/region 2>$null)
$dockerCfg = if ($env:DOCKER_CONFIG) { Join-Path $env:DOCKER_CONFIG "config.json" } else { Join-Path $HOME ".docker\config.json" }
$dockerOk = $false
if (Test-Path $dockerCfg) {
$dockerOk = (Select-String -Path $dockerCfg -Pattern "\"$($Cfg['GCP_REGION'])-docker.pkg.dev\"" -SimpleMatch -Quiet)
}
return (-not [string]::IsNullOrWhiteSpace($activeAccount)) -and
($currentProject.Trim() -eq $Cfg['GCP_PROJECT_ID']) -and
($currentRegion.Trim() -eq $Cfg['GCP_REGION']) -and
$dockerOk
}
function Test-ProjectSetup {
param([hashtable]$Cfg)
$billingEnabled = (gcloud billing projects describe $Cfg['GCP_PROJECT_ID'] --format="value(billingEnabled)" 2>$null)
if ($billingEnabled -ne 'True') { return $false }
try {
gcloud artifacts repositories describe $Cfg['GCP_REPOSITORY'] --location=$Cfg['GCP_REGION'] --project=$Cfg['GCP_PROJECT_ID'] 2>$null | Out-Null
} catch {
return $false
}
foreach ($api in @('run.googleapis.com', 'artifactregistry.googleapis.com', 'secretmanager.googleapis.com', 'cloudresourcemanager.googleapis.com')) {
$enabled = gcloud services list --enabled --project=$Cfg['GCP_PROJECT_ID'] --format="value(config.name)" 2>$null | Select-String -Pattern "^$([regex]::Escape($api))$"
if (-not $enabled) { return $false }
}
return $true
}
function Test-SecretsSetup {
param([hashtable]$Cfg)
try {
gcloud secrets describe mongodb-connection-string --project=$Cfg['GCP_PROJECT_ID'] 2>$null | Out-Null
} catch {
return $false
}
$serviceAccount = "serviceAccount:$($Cfg['GCP_PROJECT_ID'])@appspot.gserviceaccount.com"
$binding = gcloud secrets get-iam-policy mongodb-connection-string `
--project=$Cfg['GCP_PROJECT_ID'] `
--flatten="bindings[].members" `
--filter="bindings.role=roles/secretmanager.secretAccessor AND bindings.members=$serviceAccount" `
--format="value(bindings.members)" 2>$null
return ($binding -match [regex]::Escape($serviceAccount))
}
function Test-DeployDone {
param([hashtable]$Cfg)
try {
gcloud run services describe $Cfg['SERVICE_NAME'] --region=$Cfg['GCP_REGION'] --project=$Cfg['GCP_PROJECT_ID'] 2>$null | Out-Null
return $true
} catch {
return $false
}
}
function Write-Done {
param([string]$Text)
Write-Host "[v] $Text"
}
Write-Host "================================================================"
Write-Host " Htmx deployment flow runner (Windows)"
Write-Host "================================================================"
if (-not (Test-Path $EnvFile)) {
Write-Host "[x] Step 0: GCR/.env is missing"
Write-Host " Copy GCR/.env.example to GCR/.env and fill required values."
exit 1
}
Write-Done "Step 0: .env exists"
$cfg = Get-EnvConfig
if (Test-GcloudInstalled) {
Write-Done "Step 1: gcloud installed"
} else {
Confirm-Run "Step 1: gcloud install" (Join-Path $RootDir "scripts\00-install-gcloud.ps1")
}
if (Test-Login $cfg) {
Write-Done "Step 2: login + docker auth configured"
} else {
Confirm-Run "Step 2: login" (Join-Path $RootDir "scripts\01-login.ps1")
}
if (Test-ProjectSetup $cfg) {
Write-Done "Step 3: project setup complete"
} else {
Confirm-Run "Step 3: project setup" (Join-Path $RootDir "scripts\02-setup-project.ps1")
}
if (Test-SecretsSetup $cfg) {
Write-Done "Step 4: secrets created and access granted"
} else {
Confirm-Run "Step 4: secrets setup" (Join-Path $RootDir "scripts\03-create-secrets.ps1")
}
if (Test-DeployDone $cfg) {
Write-Done "Step 5: service is already deployed"
} else {
Confirm-Run "Step 5: deploy" (Join-Path $RootDir "scripts\04-deploy.ps1")
}
Write-Host ""
Write-Host "================================================================"
Write-Host " Final verification"
Write-Host "================================================================"
if (Test-GcloudInstalled) { Write-Done "Step 1" } else { Write-Host "[x] Step 1" }
if (Test-Login $cfg) { Write-Done "Step 2" } else { Write-Host "[x] Step 2" }
if (Test-ProjectSetup $cfg) { Write-Done "Step 3" } else { Write-Host "[x] Step 3" }
if (Test-SecretsSetup $cfg) { Write-Done "Step 4" } else { Write-Host "[x] Step 4" }
if (Test-DeployDone $cfg) { Write-Done "Step 5" } else { Write-Host "[x] Step 5" }
Write-Host ""
Write-Host "Tip: run .\GCR\run-all.ps1 -Yes to auto-run missing steps without prompts."