#Requires -Version 5.1 param([string]$Tag) Set-StrictMode -Version Latest $ErrorActionPreference = 'Continue' $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path $EnvFile = Join-Path $ScriptDir "..\\.env" if (-not (Test-Path $EnvFile)) { Write-Error "ERROR: $EnvFile not found."; exit 1 } $config = @{} foreach ($line in Get-Content $EnvFile) { if ($line -match '^\s*$' -or $line -match '^\s*#') { continue } if ($line -match '^([^=]+)=(.*)$') { $config[$Matches[1].Trim()] = $Matches[2].Trim() } } $GCP_PROJECT_ID = if ($config['GCP_PROJECT_ID']) { $config['GCP_PROJECT_ID'] } else { '' } $GCP_REGION = if ($config['GCP_REGION']) { $config['GCP_REGION'] } else { '' } $GCP_REPOSITORY = if ($config['GCP_REPOSITORY']) { $config['GCP_REPOSITORY'] } else { '' } $SERVICE_NAME = if ($config['SERVICE_NAME']) { $config['SERVICE_NAME'] } else { '' } $MONGODB_DATABASE_NAME = if ($config['MONGODB_DATABASE_NAME']) { $config['MONGODB_DATABASE_NAME'] } else { 'HtmxAppDb' } if (-not $GCP_PROJECT_ID) { Write-Error "GCP_PROJECT_ID not set"; exit 1 } if (-not $GCP_REGION) { Write-Error "GCP_REGION not set"; exit 1 } if (-not $GCP_REPOSITORY) { Write-Error "GCP_REPOSITORY not set"; exit 1 } if (-not $SERVICE_NAME) { Write-Error "SERVICE_NAME not set"; exit 1 } gcloud secrets describe mongodb-connection-string --project=$GCP_PROJECT_ID 2>$null | Out-Null if ($LASTEXITCODE -ne 0) { Write-Host ">>> Required secrets not configured." $ans = Read-Host " Run 03-create-secrets.ps1 now? [y/N]" if ($ans -match '^[Yy]$') { & (Join-Path $ScriptDir "03-create-secrets.ps1") gcloud secrets describe mongodb-connection-string --project=$GCP_PROJECT_ID 2>$null | Out-Null if ($LASTEXITCODE -ne 0) { Write-Error "Secret setup failed."; exit 1 } } else { Write-Error "Run 03-create-secrets.ps1 first."; exit 1 } } $bindings = gcloud secrets get-iam-policy mongodb-connection-string --project=$GCP_PROJECT_ID --flatten='bindings[].members' --filter='bindings.role=roles/secretmanager.secretAccessor' --format='value(bindings.members)' 2>$null if ([string]::IsNullOrWhiteSpace($bindings)) { Write-Error "No service account has secretAccessor access. Run 03-create-secrets.ps1 first." exit 1 } if (-not $Tag) { try { $Tag = (git rev-parse --short HEAD 2>$null).Trim() } catch { } if ([string]::IsNullOrWhiteSpace($Tag)) { $Tag = (Get-Date -Format "yyyyMMdd-HHmmss") } } $IMAGE = "$GCP_REGION-docker.pkg.dev/$GCP_PROJECT_ID/$GCP_REPOSITORY/htmx-demo-app:$Tag" $contextDir = Split-Path -Parent (Split-Path -Parent $ScriptDir) Write-Host "================================================================" Write-Host " Htmx -> Cloud Run deployment" Write-Host "================================================================" Write-Host " Project: $GCP_PROJECT_ID" Write-Host " Region: $GCP_REGION" Write-Host " Service: $SERVICE_NAME" Write-Host " Image: $IMAGE" Write-Host "================================================================" Write-Host "" docker info 2>$null | Out-Null if ($LASTEXITCODE -ne 0) { Write-Error "Docker is not running. Start Docker Desktop first." exit 1 } Write-Host ">>> Building Docker image..." $env:DOCKER_BUILDKIT = "1" docker build -t $IMAGE -f "$contextDir\GCR\Dockerfile" $contextDir if ($LASTEXITCODE -ne 0) { Write-Error "Docker build failed."; exit 1 } Write-Host ">>> Image built: $IMAGE" Write-Host "" Write-Host ">>> Pushing to Artifact Registry..." docker push $IMAGE if ($LASTEXITCODE -ne 0) { Write-Error "Docker push failed."; exit 1 } Write-Host ">>> Push complete." Write-Host "" Write-Host ">>> Deploying to Cloud Run..." gcloud run services update $SERVICE_NAME --project=$GCP_PROJECT_ID --region=$GCP_REGION --image=$IMAGE --set-env-vars=MONGODB_DATABASE_NAME=$MONGODB_DATABASE_NAME --set-secrets=ConnectionStrings__DefaultConnection=mongodb-connection-string:latest --allow-unauthenticated 2>$null if ($LASTEXITCODE -ne 0) { Write-Host " Service not found, creating..." gcloud run deploy $SERVICE_NAME --project=$GCP_PROJECT_ID --region=$GCP_REGION --image=$IMAGE --set-env-vars=MONGODB_DATABASE_NAME=$MONGODB_DATABASE_NAME --set-secrets=ConnectionStrings__DefaultConnection=mongodb-connection-string:latest --allow-unauthenticated 2>$null if ($LASTEXITCODE -ne 0) { Write-Error "Deployment failed."; exit 1 } } Write-Host ">>> Deployment complete." $SERVICE_URL = (gcloud run services describe $SERVICE_NAME --region=$GCP_REGION --project=$GCP_PROJECT_ID --format='value(status.url)' 2>$null).Trim() Write-Host "" Write-Host "================================================================" Write-Host " Done! Service URL: $SERVICE_URL" Write-Host "================================================================"