현재 작업 전체 반영
This commit is contained in:
parent
5560638e54
commit
c0dddab594
85 changed files with 11322 additions and 539 deletions
|
|
@ -14,6 +14,8 @@
|
|||
엔진 게이트웨이를 띄우지 않는다(AI 턴 생성 불가, UI만 테스트 시).
|
||||
.PARAMETER NoWeb
|
||||
vite 웹 서버를 띄우지 않는다(API만 필요할 때).
|
||||
.PARAMETER NoDb
|
||||
Docker Postgres 보장을 건너뛰고 in-memory degraded 기동을 허용한다.
|
||||
.EXAMPLE
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\dev-up.ps1
|
||||
#>
|
||||
|
|
@ -80,6 +82,78 @@ function Wait-Health([string]$url, [string]$label, [int]$timeoutSec = 40) {
|
|||
Write-Host " WARN $label 미응답 ($url) — .devlogs 로그 확인"; return $false
|
||||
}
|
||||
|
||||
function Read-EnvFileValue([string]$path, [string]$key) {
|
||||
if (!(Test-Path -LiteralPath $path)) { return $null }
|
||||
$pattern = ('^\s*{0}\s*=' -f [regex]::Escape($key))
|
||||
$line = Get-Content -LiteralPath $path -Encoding utf8 |
|
||||
Where-Object { $_ -match $pattern } |
|
||||
Select-Object -First 1
|
||||
if (-not $line) { return $null }
|
||||
$value = ($line -replace $pattern, '').Trim()
|
||||
$value = $value.Trim('"')
|
||||
$value = $value.Trim("'")
|
||||
return $value
|
||||
}
|
||||
|
||||
function Warn-ComposeEnvReadiness {
|
||||
$composeEnv = Join-Path $repo 'infra\.env'
|
||||
if (!(Test-Path -LiteralPath $composeEnv)) {
|
||||
Write-Host ' INFO infra\.env 없음 - docker compose 전체 스택은 .env 작성 후 사용.'
|
||||
return
|
||||
}
|
||||
$required = @(
|
||||
'POSTGRES_PASSWORD',
|
||||
'APP_DB_PASSWORD',
|
||||
'OPENAI_API_KEY',
|
||||
'SESSION_SECRET',
|
||||
'OAUTH_GOOGLE_CLIENT_ID',
|
||||
'OAUTH_GOOGLE_CLIENT_SECRET'
|
||||
)
|
||||
$missing = @()
|
||||
foreach ($key in $required) {
|
||||
$value = Read-EnvFileValue $composeEnv $key
|
||||
if ([string]::IsNullOrWhiteSpace($value)) { $missing += $key }
|
||||
}
|
||||
if ($missing.Count -gt 0) {
|
||||
Write-Host (' WARN infra\.env 필수값 누락: {0} - compose api/proxy 기동 전 보강 필요.' -f ($missing -join ', '))
|
||||
}
|
||||
}
|
||||
|
||||
function Test-DevDbRoleSafety([string]$ownerUser, [string]$dbName) {
|
||||
if ([string]::IsNullOrWhiteSpace($ownerUser) -or [string]::IsNullOrWhiteSpace($dbName)) { return }
|
||||
$sql = "SELECT rolname || ':' || rolsuper || ':' || rolbypassrls FROM pg_roles WHERE rolname IN ('vignette_app','vignette_owner') ORDER BY rolname;"
|
||||
$rows = & docker exec vignette-dev-db psql -U $ownerUser -d $dbName -At -c $sql 2>$null
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Host ' WARN db role 점검 실패 - psql 접속/권한 확인 필요.'
|
||||
return
|
||||
}
|
||||
foreach ($row in $rows) {
|
||||
$parts = "$row".Split(':')
|
||||
if ($parts.Count -lt 3) { continue }
|
||||
if ($parts[0] -eq 'vignette_app' -and ($parts[1] -eq 't' -or $parts[2] -eq 't')) {
|
||||
Write-Host ' WARN vignette_app role 이 SUPERUSER/BYPASSRLS 상태 - RLS 검증이 무의미함. 컨테이너를 owner/app 분리로 재생성 필요.'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Inspect-DevDbContainer {
|
||||
$healthMode = & docker inspect -f '{{if .Config.Healthcheck}}health{{else}}none{{end}}' vignette-dev-db 2>$null
|
||||
if ($LASTEXITCODE -eq 0 -and "$healthMode" -eq 'none') {
|
||||
Write-Host ' WARN vignette-dev-db healthcheck 없음 - 기존 컨테이너라면 재생성 시 healthcheck가 붙음.'
|
||||
}
|
||||
$ownerUser = & docker exec vignette-dev-db printenv POSTGRES_USER 2>$null
|
||||
if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrWhiteSpace($ownerUser)) { $ownerUser = 'vignette_owner' }
|
||||
$dbName = & docker exec vignette-dev-db printenv POSTGRES_DB 2>$null
|
||||
if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrWhiteSpace($dbName)) { $dbName = 'vignette' }
|
||||
& docker exec vignette-dev-db pg_isready -U $ownerUser 1>$null 2>$null
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Host ' OK db (vignette-dev-db 준비됨)'
|
||||
} else {
|
||||
Write-Host ' WARN db 컨테이너는 있으나 pg_isready 실패'
|
||||
}
|
||||
Test-DevDbRoleSafety "$ownerUser" "$dbName"
|
||||
}
|
||||
|
||||
function Ensure-DevDb {
|
||||
if (!(Get-Command docker -ErrorAction SilentlyContinue)) {
|
||||
Write-Host ' WARN docker CLI 없음 - DB 없이 degraded(UI 세션 시작 제한).'
|
||||
|
|
@ -97,13 +171,13 @@ function Ensure-DevDb {
|
|||
|
||||
$running = docker ps --filter name=vignette-dev-db --format '{{.Names}}' 2>$null
|
||||
if ($running -match 'vignette-dev-db') {
|
||||
Write-Host ' OK db (vignette-dev-db 실행 중)'
|
||||
Inspect-DevDbContainer
|
||||
return
|
||||
}
|
||||
|
||||
docker rm -f vignette-dev-db 1>$null 2>$null
|
||||
$envLines = Get-Content -LiteralPath (Join-Path $api '.env')
|
||||
$dbUrl = (($envLines | Where-Object { $_ -match '^DATABASE_URL=' }) -replace '^DATABASE_URL=', '').Trim()
|
||||
$apiEnv = Join-Path $api '.env'
|
||||
$dbUrl = Read-EnvFileValue $apiEnv 'DATABASE_URL'
|
||||
if ($dbUrl -notmatch 'postgresql://([^:]+):([^@]+)@[^:]+:([0-9]+)/(\S+)') {
|
||||
Write-Host ' WARN DATABASE_URL 파싱 실패 - DB 스킵'
|
||||
return
|
||||
|
|
@ -113,16 +187,27 @@ function Ensure-DevDb {
|
|||
$p = $Matches[2]
|
||||
$port = $Matches[3]
|
||||
$db = $Matches[4]
|
||||
$ownerUser = 'vignette_owner'
|
||||
$ownerPassword = $p
|
||||
$appUser = $u
|
||||
$appPassword = $p
|
||||
if ($appUser -eq $ownerUser) {
|
||||
Write-Host ' WARN DATABASE_URL 이 owner role 을 사용 중 - RLS 검증을 위해 앱 전용 role URL 권장.'
|
||||
}
|
||||
$initPath = Join-Path $repo 'infra\db\init'
|
||||
$dockerArgs = @(
|
||||
'run', '-d',
|
||||
'--name', 'vignette-dev-db',
|
||||
'-p', ('{0}:5432' -f $port),
|
||||
'-e', ('POSTGRES_USER={0}' -f $u),
|
||||
'-e', ('POSTGRES_PASSWORD={0}' -f $p),
|
||||
'--health-cmd', ('pg_isready -U {0}' -f $ownerUser),
|
||||
'--health-interval', '10s',
|
||||
'--health-timeout', '5s',
|
||||
'--health-retries', '5',
|
||||
'-e', ('POSTGRES_USER={0}' -f $ownerUser),
|
||||
'-e', ('POSTGRES_PASSWORD={0}' -f $ownerPassword),
|
||||
'-e', ('POSTGRES_DB={0}' -f $db),
|
||||
'-e', 'APP_DB_USER=vignette_app',
|
||||
'-e', 'APP_DB_PASSWORD=vignette_app',
|
||||
'-e', ('APP_DB_USER={0}' -f $appUser),
|
||||
'-e', ('APP_DB_PASSWORD={0}' -f $appPassword),
|
||||
'-v', ('{0}:/docker-entrypoint-initdb.d:ro' -f $initPath),
|
||||
'pgvector/pgvector:pg16'
|
||||
)
|
||||
|
|
@ -130,9 +215,10 @@ function Ensure-DevDb {
|
|||
|
||||
for ($i = 0; $i -lt 24; $i++) {
|
||||
Start-Sleep -Seconds 2
|
||||
docker exec vignette-dev-db pg_isready -U $u 1>$null 2>$null
|
||||
docker exec vignette-dev-db pg_isready -U $ownerUser 1>$null 2>$null
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Host ' OK db (Postgres 준비됨, init 스키마 적용)'
|
||||
Test-DevDbRoleSafety $ownerUser $db
|
||||
Start-Sleep -Seconds 1
|
||||
return
|
||||
}
|
||||
|
|
@ -151,6 +237,7 @@ Start-Sleep -Seconds 2
|
|||
|
||||
if (-not $NoDb) {
|
||||
Write-Host '[DB] Postgres(pgvector) 보장...'
|
||||
Warn-ComposeEnvReadiness
|
||||
Ensure-DevDb
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue