2026-01-27 16:21:58 +00:00
|
|
|
<#
|
|
|
|
|
.SYNOPSIS
|
|
|
|
|
Starts the Likwid development environment.
|
|
|
|
|
.DESCRIPTION
|
|
|
|
|
Starts PostgreSQL (via Podman), backend (Rust/Axum), and frontend (Astro).
|
|
|
|
|
Use dev-stop.ps1 to stop all services.
|
|
|
|
|
#>
|
|
|
|
|
[CmdletBinding()]
|
|
|
|
|
param()
|
|
|
|
|
|
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
|
|
|
|
|
|
# Paths
|
|
|
|
|
$root = Split-Path -Parent $PSScriptRoot
|
|
|
|
|
$stateDir = Join-Path $PSScriptRoot '.dev'
|
|
|
|
|
$stateFile = Join-Path $stateDir 'state.json'
|
|
|
|
|
$backendLog = Join-Path $stateDir 'backend.log'
|
|
|
|
|
$frontendLog = Join-Path $stateDir 'frontend.log'
|
|
|
|
|
|
|
|
|
|
New-Item -ItemType Directory -Force -Path $stateDir | Out-Null
|
|
|
|
|
|
|
|
|
|
# Environment
|
|
|
|
|
if (-not $env:POSTGRES_USER) { $env:POSTGRES_USER = 'likwid' }
|
|
|
|
|
if (-not $env:POSTGRES_PASSWORD) { $env:POSTGRES_PASSWORD = 'likwid' }
|
|
|
|
|
if (-not $env:POSTGRES_DB) { $env:POSTGRES_DB = 'likwid' }
|
2026-02-02 10:30:15 +00:00
|
|
|
if (-not $env:JWT_SECRET) { $env:JWT_SECRET = 'dev_jwt_secret_not_for_production' }
|
2026-01-27 16:21:58 +00:00
|
|
|
$env:DATABASE_URL = "postgres://$($env:POSTGRES_USER):$($env:POSTGRES_PASSWORD)@127.0.0.1:5432/$($env:POSTGRES_DB)"
|
|
|
|
|
|
|
|
|
|
# Check if already running
|
|
|
|
|
if (Test-Path $stateFile) {
|
|
|
|
|
$state = Get-Content -Raw $stateFile | ConvertFrom-Json -ErrorAction SilentlyContinue
|
|
|
|
|
if ($state -and $state.backendPid) {
|
|
|
|
|
$p = Get-Process -Id $state.backendPid -ErrorAction SilentlyContinue
|
|
|
|
|
if ($p) {
|
|
|
|
|
Write-Host "Already running (backend PID $($state.backendPid)). Run dev-stop.ps1 first."
|
|
|
|
|
exit 0
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Start Podman machine if needed
|
|
|
|
|
try {
|
|
|
|
|
$machines = podman machine list --format json 2>$null | ConvertFrom-Json
|
|
|
|
|
$running = $machines | Where-Object { $_.Running -eq $true }
|
|
|
|
|
if (-not $running) {
|
|
|
|
|
Write-Host "Starting Podman machine..."
|
|
|
|
|
podman machine start ($machines | Select-Object -First 1).Name 2>$null
|
|
|
|
|
}
|
|
|
|
|
} catch {
|
|
|
|
|
Write-Host "Podman machine check failed (may already be running)"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Start PostgreSQL container
|
|
|
|
|
Write-Host "Starting PostgreSQL..."
|
|
|
|
|
$composeFile = Join-Path $root 'compose/dev.yml'
|
2026-01-31 13:29:51 +00:00
|
|
|
|
2026-02-01 13:26:56 +00:00
|
|
|
$composeExitCode = 0
|
|
|
|
|
try {
|
|
|
|
|
podman-compose -f $composeFile up -d 2>$null
|
|
|
|
|
$composeExitCode = $LASTEXITCODE
|
|
|
|
|
} catch {
|
|
|
|
|
$composeExitCode = $LASTEXITCODE
|
|
|
|
|
}
|
2026-01-31 13:29:51 +00:00
|
|
|
if ($composeExitCode -ne 0) {
|
2026-02-01 13:26:56 +00:00
|
|
|
$containerExistsExitCode = 0
|
|
|
|
|
try {
|
|
|
|
|
podman container exists likwid-postgres 2>$null
|
|
|
|
|
$containerExistsExitCode = $LASTEXITCODE
|
|
|
|
|
} catch {
|
|
|
|
|
$containerExistsExitCode = $LASTEXITCODE
|
|
|
|
|
}
|
2026-01-31 13:29:51 +00:00
|
|
|
if ($containerExistsExitCode -ne 0) {
|
|
|
|
|
throw "Failed to start PostgreSQL via podman-compose (exit code: $composeExitCode)."
|
|
|
|
|
}
|
|
|
|
|
Write-Host "Warning: podman-compose returned exit code $composeExitCode, but likwid-postgres exists. Continuing."
|
|
|
|
|
}
|
2026-01-27 16:21:58 +00:00
|
|
|
|
|
|
|
|
# Wait for PostgreSQL to be ready
|
|
|
|
|
$maxWait = 30
|
|
|
|
|
for ($i = 0; $i -lt $maxWait; $i++) {
|
|
|
|
|
$pg = netstat -ano 2>$null | Select-String ':5432.*LISTENING'
|
|
|
|
|
if ($pg) { break }
|
|
|
|
|
Start-Sleep -Seconds 1
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-01 12:28:01 +00:00
|
|
|
Write-Host "Running database migrations..."
|
|
|
|
|
Push-Location (Join-Path $root 'backend')
|
|
|
|
|
try {
|
2026-02-01 13:26:56 +00:00
|
|
|
sqlx migrate run --ignore-missing
|
2026-02-01 12:28:01 +00:00
|
|
|
if ($LASTEXITCODE -ne 0) {
|
|
|
|
|
throw "Failed to run database migrations (sqlx migrate run)."
|
|
|
|
|
}
|
|
|
|
|
} finally {
|
|
|
|
|
Pop-Location
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-27 16:21:58 +00:00
|
|
|
# Start backend
|
|
|
|
|
Write-Host "Starting backend..."
|
|
|
|
|
$backend = Start-Process -FilePath 'cmd.exe' `
|
|
|
|
|
-ArgumentList '/c', 'cargo', 'run', '2>&1' `
|
|
|
|
|
-WorkingDirectory (Join-Path $root 'backend') `
|
|
|
|
|
-PassThru -WindowStyle Hidden `
|
|
|
|
|
-RedirectStandardOutput $backendLog
|
|
|
|
|
|
|
|
|
|
# Start frontend
|
|
|
|
|
Write-Host "Starting frontend..."
|
|
|
|
|
$frontend = Start-Process -FilePath 'cmd.exe' `
|
2026-01-28 23:44:25 +00:00
|
|
|
-ArgumentList '/c', "set PUBLIC_API_BASE=http://127.0.0.1:3000&& npm run dev", '2>&1' `
|
2026-01-27 16:21:58 +00:00
|
|
|
-WorkingDirectory (Join-Path $root 'frontend') `
|
|
|
|
|
-PassThru -WindowStyle Hidden `
|
|
|
|
|
-RedirectStandardOutput $frontendLog
|
|
|
|
|
|
|
|
|
|
# Save state
|
|
|
|
|
@{
|
|
|
|
|
backendPid = $backend.Id
|
|
|
|
|
frontendPid = $frontend.Id
|
|
|
|
|
startedAt = (Get-Date).ToString('o')
|
|
|
|
|
} | ConvertTo-Json | Set-Content -Encoding UTF8 $stateFile
|
|
|
|
|
|
|
|
|
|
# Brief wait for startup
|
|
|
|
|
Start-Sleep -Seconds 3
|
|
|
|
|
|
|
|
|
|
# Status report
|
|
|
|
|
Write-Host ""
|
|
|
|
|
Write-Host "=== Likwid Dev Environment ==="
|
|
|
|
|
if (-not $backend.HasExited) {
|
|
|
|
|
Write-Host "Backend: Running (PID $($backend.Id)) - http://127.0.0.1:3000"
|
|
|
|
|
} else {
|
|
|
|
|
Write-Host "Backend: FAILED - check $backendLog"
|
|
|
|
|
}
|
|
|
|
|
if (-not $frontend.HasExited) {
|
|
|
|
|
Write-Host "Frontend: Running (PID $($frontend.Id)) - http://localhost:4321"
|
|
|
|
|
} else {
|
|
|
|
|
Write-Host "Frontend: FAILED - check $frontendLog"
|
|
|
|
|
}
|
|
|
|
|
Write-Host "PostgreSQL: Running on port 5432"
|
|
|
|
|
Write-Host ""
|
|
|
|
|
Write-Host "Logs: $stateDir"
|
|
|
|
|
Write-Host "Stop: .\scripts\dev-stop.ps1"
|