This commit is contained in:
master
2026-02-04 19:59:20 +02:00
parent 557feefdc3
commit 5548cf83bf
1479 changed files with 53557 additions and 40339 deletions

337
scripts/setup.ps1 Normal file
View File

@@ -0,0 +1,337 @@
#!/usr/bin/env pwsh
<#
.SYNOPSIS
Automated developer environment setup for Stella Ops (Windows).
.DESCRIPTION
Validates prerequisites, starts infrastructure, builds solutions and Docker images,
and launches the full platform.
.PARAMETER SkipBuild
Skip .NET solution builds.
.PARAMETER InfraOnly
Only start infrastructure containers (PostgreSQL, Valkey, SeaweedFS, Rekor, Zot).
.PARAMETER ImagesOnly
Only build Docker images (skip infra start and .NET build).
.PARAMETER SkipImages
Skip Docker image builds.
#>
[CmdletBinding()]
param(
[switch]$SkipBuild,
[switch]$InfraOnly,
[switch]$ImagesOnly,
[switch]$SkipImages
)
$ErrorActionPreference = 'Stop'
$Root = git rev-parse --show-toplevel 2>$null
if (-not $Root) {
Write-Error 'Not inside a git repository. Run this script from within the Stella Ops repo.'
exit 1
}
$Root = $Root.Trim()
$ComposeDir = Join-Path $Root 'devops/compose'
# ─── Helpers ────────────────────────────────────────────────────────────────
function Write-Step([string]$msg) {
Write-Host "`n>> $msg" -ForegroundColor Cyan
}
function Write-Ok([string]$msg) {
Write-Host " [OK] $msg" -ForegroundColor Green
}
function Write-Warn([string]$msg) {
Write-Host " [WARN] $msg" -ForegroundColor Yellow
}
function Write-Fail([string]$msg) {
Write-Host " [FAIL] $msg" -ForegroundColor Red
}
function Test-Command([string]$cmd) {
return [bool](Get-Command $cmd -ErrorAction SilentlyContinue)
}
# ─── 1. Check prerequisites ────────────────────────────────────────────────
function Test-Prerequisites {
Write-Step 'Checking prerequisites'
$allGood = $true
# dotnet
if (Test-Command 'dotnet') {
$v = (dotnet --version 2>$null)
if ($v -match '^10\.') {
Write-Ok "dotnet $v"
} else {
Write-Fail "dotnet $v found, but 10.x is required"
$allGood = $false
}
} else {
Write-Fail 'dotnet SDK not found. Install .NET 10 SDK.'
$allGood = $false
}
# node
if (Test-Command 'node') {
$v = (node --version 2>$null).TrimStart('v')
$major = [int]($v -split '\.')[0]
if ($major -ge 20) {
Write-Ok "node $v"
} else {
Write-Fail "node $v found, but 20+ is required"
$allGood = $false
}
} else {
Write-Fail 'node not found. Install Node.js 20+.'
$allGood = $false
}
# npm
if (Test-Command 'npm') {
$v = (npm --version 2>$null)
$major = [int]($v -split '\.')[0]
if ($major -ge 10) {
Write-Ok "npm $v"
} else {
Write-Fail "npm $v found, but 10+ is required"
$allGood = $false
}
} else {
Write-Fail 'npm not found.'
$allGood = $false
}
# docker
if (Test-Command 'docker') {
$v = (docker --version 2>$null)
Write-Ok "docker: $v"
} else {
Write-Fail 'docker not found. Install Docker Desktop.'
$allGood = $false
}
# docker compose
$composeOk = $false
try {
$null = docker compose version 2>$null
if ($LASTEXITCODE -eq 0) { $composeOk = $true }
} catch {}
if ($composeOk) {
Write-Ok 'docker compose available'
} else {
Write-Fail 'docker compose not available. Ensure Docker Desktop includes Compose V2.'
$allGood = $false
}
# git
if (Test-Command 'git') {
Write-Ok "git $(git --version 2>$null)"
} else {
Write-Fail 'git not found.'
$allGood = $false
}
if (-not $allGood) {
Write-Error 'Prerequisites not met. Install missing tools and re-run.'
exit 1
}
}
# ─── 2. Check hosts file ───────────────────────────────────────────────────
function Test-HostsFile {
Write-Step 'Checking hosts file for stella-ops.local entries'
$hostsPath = 'C:\Windows\System32\drivers\etc\hosts'
if (Test-Path $hostsPath) {
$content = Get-Content $hostsPath -Raw
if ($content -match 'stella-ops\.local') {
Write-Ok 'stella-ops.local entries found in hosts file'
} else {
Write-Warn 'stella-ops.local entries NOT found in hosts file.'
Write-Host ' Add the hosts block from docs/dev/DEV_ENVIRONMENT_SETUP.md section 2' -ForegroundColor Yellow
Write-Host ' to C:\Windows\System32\drivers\etc\hosts (run editor as Administrator)' -ForegroundColor Yellow
}
} else {
Write-Warn "Cannot read hosts file at $hostsPath"
}
}
# ─── 3. Ensure .env ────────────────────────────────────────────────────────
function Initialize-EnvFile {
Write-Step 'Ensuring .env file exists'
$envFile = Join-Path $ComposeDir '.env'
$envExample = Join-Path $ComposeDir 'env/stellaops.env.example'
if (Test-Path $envFile) {
Write-Ok ".env already exists at $envFile"
} elseif (Test-Path $envExample) {
Copy-Item $envExample $envFile
Write-Ok "Copied $envExample -> $envFile"
Write-Warn 'Review .env and change POSTGRES_PASSWORD at minimum.'
} else {
Write-Fail "Neither .env nor env/stellaops.env.example found in $ComposeDir"
exit 1
}
}
# ─── 4. Start infrastructure ───────────────────────────────────────────────
function Start-Infrastructure {
Write-Step 'Starting infrastructure containers (docker-compose.dev.yml)'
Push-Location $ComposeDir
try {
docker compose -f docker-compose.dev.yml up -d
if ($LASTEXITCODE -ne 0) {
Write-Fail 'Failed to start infrastructure containers.'
exit 1
}
Write-Host ' Waiting for containers to become healthy...' -ForegroundColor Gray
$maxWait = 120
$elapsed = 0
while ($elapsed -lt $maxWait) {
$ps = docker compose -f docker-compose.dev.yml ps --format json 2>$null
if ($ps) {
$allHealthy = $true
# docker compose ps --format json outputs one JSON object per line
foreach ($line in $ps -split "`n") {
$line = $line.Trim()
if (-not $line) { continue }
try {
$svc = $line | ConvertFrom-Json
if ($svc.Health -and $svc.Health -ne 'healthy') {
$allHealthy = $false
}
} catch {}
}
if ($allHealthy -and $elapsed -gt 5) {
Write-Ok 'All infrastructure containers healthy'
return
}
}
Start-Sleep -Seconds 5
$elapsed += 5
}
Write-Warn "Timed out waiting for healthy status after ${maxWait}s. Check with: docker compose -f docker-compose.dev.yml ps"
}
finally {
Pop-Location
}
}
# ─── 5. Build .NET solutions ───────────────────────────────────────────────
function Build-Solutions {
Write-Step 'Building all .NET solutions'
$buildScript = Join-Path $Root 'scripts/build-all-solutions.ps1'
if (Test-Path $buildScript) {
& $buildScript
if ($LASTEXITCODE -ne 0) {
Write-Fail '.NET solution build failed.'
exit 1
}
Write-Ok '.NET solutions built successfully'
} else {
Write-Warn "Build script not found at $buildScript. Skipping .NET build."
}
}
# ─── 6. Build Docker images ────────────────────────────────────────────────
function Build-Images {
Write-Step 'Building Docker images'
$buildScript = Join-Path $Root 'devops/docker/build-all.ps1'
if (Test-Path $buildScript) {
& $buildScript
if ($LASTEXITCODE -ne 0) {
Write-Fail 'Docker image build failed.'
exit 1
}
Write-Ok 'Docker images built successfully'
} else {
Write-Warn "Build script not found at $buildScript. Skipping image build."
}
}
# ─── 7. Start full platform ────────────────────────────────────────────────
function Start-Platform {
Write-Step 'Starting full Stella Ops platform'
Push-Location $ComposeDir
try {
docker compose -f docker-compose.stella-ops.yml up -d
if ($LASTEXITCODE -ne 0) {
Write-Fail 'Failed to start platform services.'
exit 1
}
Write-Ok 'Platform services started'
}
finally {
Pop-Location
}
}
# ─── 8. Smoke test ─────────────────────────────────────────────────────────
function Test-Smoke {
Write-Step 'Running smoke tests'
$endpoints = @(
@{ Name = 'PostgreSQL'; Cmd = { docker exec stellaops-dev-postgres pg_isready -U stellaops 2>$null; $LASTEXITCODE -eq 0 } },
@{ Name = 'Valkey'; Cmd = { $r = docker exec stellaops-dev-valkey valkey-cli ping 2>$null; $r -eq 'PONG' } }
)
foreach ($ep in $endpoints) {
try {
$ok = & $ep.Cmd
if ($ok) { Write-Ok $ep.Name } else { Write-Warn "$($ep.Name) not responding" }
} catch {
Write-Warn "$($ep.Name) check failed: $_"
}
}
}
# ─── Main ───────────────────────────────────────────────────────────────────
Write-Host '=============================================' -ForegroundColor Cyan
Write-Host ' Stella Ops Developer Environment Setup' -ForegroundColor Cyan
Write-Host '=============================================' -ForegroundColor Cyan
Test-Prerequisites
Test-HostsFile
if ($ImagesOnly) {
Build-Images
Write-Host "`nDone (images only)." -ForegroundColor Green
exit 0
}
Initialize-EnvFile
Start-Infrastructure
if ($InfraOnly) {
Test-Smoke
Write-Host "`nDone (infra only). Infrastructure is running." -ForegroundColor Green
exit 0
}
if (-not $SkipBuild) {
Build-Solutions
}
if (-not $SkipImages) {
Build-Images
}
Start-Platform
Test-Smoke
Write-Host "`n=============================================" -ForegroundColor Green
Write-Host ' Setup complete!' -ForegroundColor Green
Write-Host ' Platform: https://stella-ops.local' -ForegroundColor Green
Write-Host ' Docs: docs/dev/DEV_ENVIRONMENT_SETUP.md' -ForegroundColor Green
Write-Host '=============================================' -ForegroundColor Green