Files
aza/AzA march 2026/deploy/run_backend_local_with_env.ps1

206 lines
5.9 KiB
PowerShell
Raw Normal View History

2026-03-25 22:03:39 +01:00
<#
AZA Step 12 Fix: Start LOCAL backend with tokens from deploy\.env (no manual edits)
What it does:
- Loads deploy\.env
- Sets process env: MEDWORK_API_TOKENS / MEDWORK_API_TOKEN (as present in .env)
- Attempts to start uvicorn with common app module paths:
1) app:app
2) backend.main:app
3) main:app
- Binds to 127.0.0.1:8000
Run from project root:
powershell -ExecutionPolicy Bypass -File .\deploy\run_backend_local_with_env.ps1
Then re-run authorized test:
cd .\deploy
powershell -ExecutionPolicy Bypass -File .\authorized_test.ps1
#>
[CmdletBinding()]
param(
[string]$EnvFile = ".\deploy\.env",
[string]$BindHost = "127.0.0.1",
[int]$Port = 8000
)
function Load-DotEnv([string]$Path) {
if (-not (Test-Path -LiteralPath $Path)) {
throw "Missing .env file at: $Path"
}
$map = @{}
Get-Content -LiteralPath $Path | ForEach-Object {
$line = $_.Trim()
if ($line.Length -eq 0) { return }
if ($line.StartsWith("#")) { return }
$idx = $line.IndexOf("=")
if ($idx -lt 1) { return }
$k = $line.Substring(0, $idx).Trim()
$v = $line.Substring($idx + 1).Trim()
if (($v.StartsWith('"') -and $v.EndsWith('"')) -or ($v.StartsWith("'") -and $v.EndsWith("'"))) {
$v = $v.Substring(1, $v.Length - 2)
}
$map[$k] = $v
}
return $map
}
Write-Host "[AZA] Start local backend with env from $EnvFile"
try {
$envMap = Load-DotEnv $EnvFile
} catch {
Write-Host "$($_.Exception.Message)"
exit 1
}
if ($envMap.ContainsKey("MEDWORK_API_TOKENS")) {
$env:MEDWORK_API_TOKENS = $envMap["MEDWORK_API_TOKENS"]
Write-Host " MEDWORK_API_TOKENS: set"
} elseif ($envMap.ContainsKey("MEDWORK_API_TOKEN")) {
$env:MEDWORK_API_TOKEN = $envMap["MEDWORK_API_TOKEN"]
Write-Host " MEDWORK_API_TOKEN: set"
} else {
Write-Host "❌ No MEDWORK_API_TOKENS or MEDWORK_API_TOKEN found in $EnvFile"
exit 1
}
# AZA secret key requirement:
# Prefer AZA_SECRET_KEY from .env; otherwise enable dev-mode auto-generated key.
if ($envMap.ContainsKey("AZA_SECRET_KEY") -and $envMap["AZA_SECRET_KEY"].Trim().Length -ge 32) {
$env:AZA_SECRET_KEY = $envMap["AZA_SECRET_KEY"]
Write-Host " AZA_SECRET_KEY: set (from .env)"
} else {
$env:AZA_ENV = "dev"
Write-Host " AZA_ENV: dev (AZA_SECRET_KEY not present/too short in .env)"
}
# Optional: keep build leak-free if your backend uses AZA_BUILD
if ($envMap.ContainsKey("AZA_BUILD")) {
$env:AZA_BUILD = $envMap["AZA_BUILD"]
}
Write-Host " Binding: http://$BindHost`:$Port"
Write-Host ""
$preferredTarget = "workforce_planner.api.app:app"
$candidates = @($preferredTarget, "app:app", "backend.main:app", "main:app")
function Try-Start([string]$target) {
Write-Host "Trying: uvicorn $target --host $BindHost --port $Port"
# Use python -m uvicorn to avoid PATH issues
& python -m uvicorn $target --host $BindHost --port $Port
if ($LASTEXITCODE -eq 0) { return $true }
return $false
}
Write-Host "NOTE: This will run the server in the foreground. Leave this window open while testing."
Write-Host ""
function Try-StartFile([string]$filePath) {
Write-Host "Trying: python $filePath"
& python $filePath
if ($LASTEXITCODE -eq 0) { return $true }
return $false
}
function To-ModulePath([string]$filePath) {
$p = $filePath.Replace("\", "/")
if ($p.StartsWith("./")) { $p = $p.Substring(2) }
if ($p.EndsWith(".py")) { $p = $p.Substring(0, $p.Length - 3) }
return ($p -replace "/", ".")
}
function Repo-FastApiCandidates {
$paths = @(
"main.py",
"backend\main.py",
"backend\app.py",
"server.py",
"api.py",
"asgi.py",
"app.py",
"app\main.py",
"src\main.py",
"src\backend\main.py",
"aza_backend\main.py",
"aza\main.py"
)
$found = @()
foreach ($p in $paths) {
if (Test-Path -LiteralPath $p) { $found += $p }
}
# If nothing found, do a shallow-ish search (PS5.1 compatible) for common entry filenames
if ($found.Count -eq 0) {
$filters = @("main.py","app.py","server.py","api.py","asgi.py")
try {
$root = (Resolve-Path .).Path
$all = Get-ChildItem -Path . -Recurse -File -ErrorAction SilentlyContinue |
Where-Object { $filters -contains $_.Name }
foreach ($fi in $all) {
# approximate depth by counting separators in relative path
$rel = Resolve-Path $fi.FullName -Relative
$sepCount = ($rel.ToString().Split(@("\","/")) | Where-Object { $_ -ne "." -and $_ -ne "" }).Count - 1
if ($sepCount -le 3) {
$found += $rel
}
}
} catch { }
}
# de-dup
return ($found | Select-Object -Unique)
}
# 1) Try preferred known target first (your repo)
Write-Host "Preferred target: $preferredTarget"
Write-Host ""
foreach ($t in $candidates) {
$ok = Try-Start $t
if ($ok) { exit 0 }
Write-Host " (failed) $t"
Write-Host ""
}
# 2) Try repo-discovered file candidates
$files = Repo-FastApiCandidates
Write-Host "Discovered candidate backend files: $($files.Count)"
if ($files.Count -gt 0) {
$files | ForEach-Object { Write-Host " - $_" }
} else {
Write-Host " (none found within ~3 levels for: main.py/app.py/server.py/api.py/asgi.py)"
}
Write-Host ""
if ($files.Count -gt 0) {
foreach ($f in $files) {
# First: try running the file directly (in case it self-starts uvicorn)
$okFile = Try-StartFile $f
if ($okFile) { exit 0 }
Write-Host " (failed) python $f"
Write-Host ""
# Second: try uvicorn with module:app
$mod = To-ModulePath $f
$target = "$mod`:app"
$ok = Try-Start $target
if ($ok) { exit 0 }
Write-Host " (failed) $target"
Write-Host ""
}
}
Write-Host "FAIL Could not start uvicorn with known module targets."
Write-Host "Checked module candidates:"
$candidates | ForEach-Object { Write-Host " - $_" }
if ($files -and $files.Count -gt 0) {
Write-Host "Checked discovered files:"
$files | ForEach-Object { Write-Host " - $_" }
}
Write-Host ""
Write-Host "Next patch will hard-wire the correct module path once you paste the existing local start command/log line."
exit 1