159 lines
5.6 KiB
PowerShell
159 lines
5.6 KiB
PowerShell
param(
|
|
[int]$MockPort = 18080,
|
|
[int]$AppPort = 18081,
|
|
[switch]$SkipGoFmt
|
|
)
|
|
|
|
Set-StrictMode -Version Latest
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
. (Join-Path $PSScriptRoot "dev-tools.ps1")
|
|
|
|
Use-LocalTooling
|
|
$repoRoot = Get-RepoRoot
|
|
$tmpRoot = Join-Path (Get-LocalRoot) ("selftest-" + [guid]::NewGuid().ToString("N"))
|
|
Ensure-Directory -Path $tmpRoot
|
|
$mockProcess = $null
|
|
$appProcess = $null
|
|
$appStdoutTask = $null
|
|
$appStderrTask = $null
|
|
|
|
function Stop-TrackedProcess {
|
|
param($Process)
|
|
if ($null -ne $Process -and -not $Process.HasExited) {
|
|
Stop-Process -Id $Process.Id -Force
|
|
$Process.WaitForExit()
|
|
}
|
|
}
|
|
|
|
try {
|
|
if (-not $SkipGoFmt) {
|
|
Write-Step "gofmt"
|
|
Invoke-CheckedCommand -FilePath "gofmt" -Arguments @(
|
|
"-w",
|
|
(Join-Path $repoRoot "backend\main.go"),
|
|
(Join-Path $repoRoot "backend\handlers\api.go"),
|
|
(Join-Path $repoRoot "backend\models\db.go"),
|
|
(Join-Path $repoRoot "backend\services\cse.go"),
|
|
(Join-Path $repoRoot "backend\services\cse_test.go"),
|
|
(Join-Path $repoRoot "backend\services\search_collectors.go"),
|
|
(Join-Path $repoRoot "backend\services\ranker.go"),
|
|
(Join-Path $repoRoot "backend\services\gemini.go"),
|
|
(Join-Path $repoRoot "backend\services\gemini_test.go")
|
|
)
|
|
}
|
|
|
|
Write-Step "python syntax"
|
|
Invoke-CheckedCommand -FilePath (Resolve-VenvPythonExe) -Arguments @(
|
|
"-m",
|
|
"py_compile",
|
|
(Join-Path $repoRoot "worker\downloader.py"),
|
|
(Join-Path $repoRoot "scripts\mock_searxng.py")
|
|
)
|
|
|
|
Write-Step "go test"
|
|
Invoke-CheckedCommand -FilePath "go" -Arguments @("test", "./...")
|
|
|
|
Write-Step "frontend syntax"
|
|
Invoke-CheckedCommand -FilePath "node" -Arguments @("--check", (Join-Path $repoRoot "frontend\app.js"))
|
|
|
|
Write-Step "go build"
|
|
$binaryPath = Join-Path $tmpRoot "ai-media-hub.exe"
|
|
Invoke-CheckedCommand -FilePath "go" -Arguments @("build", "-o", $binaryPath, "./backend")
|
|
|
|
Write-Step "start mock searxng"
|
|
$mockLog = Join-Path $tmpRoot "mock-searxng.stdout.log"
|
|
$mockErrLog = Join-Path $tmpRoot "mock-searxng.stderr.log"
|
|
$mockProcess = Start-Process -FilePath (Resolve-VenvPythonExe) `
|
|
-ArgumentList @((Join-Path $repoRoot "scripts\mock_searxng.py"), "--port", $MockPort) `
|
|
-RedirectStandardOutput $mockLog `
|
|
-RedirectStandardError $mockErrLog `
|
|
-PassThru `
|
|
-WindowStyle Hidden
|
|
|
|
Write-Step "start app"
|
|
$downloadsDir = Join-Path $tmpRoot "downloads"
|
|
Ensure-Directory -Path $downloadsDir
|
|
$appLog = Join-Path $tmpRoot "app.log"
|
|
$envMap = Get-AppEnvironment `
|
|
-WorkspaceRoot $repoRoot `
|
|
-DownloadsDir $downloadsDir `
|
|
-SqlitePath (Join-Path $tmpRoot "media.db") `
|
|
-AppAddr ("127.0.0.1:{0}" -f $AppPort) `
|
|
-SearxUrl ("http://127.0.0.1:{0}" -f $MockPort)
|
|
|
|
$appStartInfo = New-Object System.Diagnostics.ProcessStartInfo
|
|
$appStartInfo.FileName = $binaryPath
|
|
$appStartInfo.WorkingDirectory = $repoRoot
|
|
$appStartInfo.UseShellExecute = $false
|
|
$appStartInfo.RedirectStandardOutput = $true
|
|
$appStartInfo.RedirectStandardError = $true
|
|
foreach ($entry in $envMap.GetEnumerator()) {
|
|
$appStartInfo.Environment[$entry.Key] = [string]$entry.Value
|
|
}
|
|
$appProcess = New-Object System.Diagnostics.Process
|
|
$appProcess.StartInfo = $appStartInfo
|
|
$null = $appProcess.Start()
|
|
$appStdoutTask = $appProcess.StandardOutput.ReadToEndAsync()
|
|
$appStderrTask = $appProcess.StandardError.ReadToEndAsync()
|
|
|
|
$healthUrl = "http://127.0.0.1:$AppPort/healthz"
|
|
$healthy = $false
|
|
for ($i = 0; $i -lt 30; $i++) {
|
|
try {
|
|
$health = Invoke-RestMethod -Uri $healthUrl -TimeoutSec 2
|
|
if ($health.status -eq "ok") {
|
|
$healthy = $true
|
|
break
|
|
}
|
|
} catch {
|
|
Start-Sleep -Seconds 1
|
|
}
|
|
}
|
|
if (-not $healthy) {
|
|
throw "/healthz 확인 실패"
|
|
}
|
|
|
|
Write-Step "verify search"
|
|
$searchPayload = @{
|
|
query = "city rain"
|
|
platforms = @("envato", "artgrid", "google video")
|
|
} | ConvertTo-Json
|
|
$search = Invoke-RestMethod -Method Post -Uri "http://127.0.0.1:$AppPort/api/search" -ContentType "application/json" -Body $searchPayload
|
|
$searchResults = @($search.results)
|
|
if ($null -eq $search.results -or $searchResults.Count -lt 2) {
|
|
throw "검색 결과가 너무 적습니다."
|
|
}
|
|
if (@($searchResults | Where-Object { -not $_.link }).Count -gt 0) {
|
|
throw "검색 결과에 link가 비어 있습니다."
|
|
}
|
|
|
|
Write-Step "verify upload"
|
|
$sampleFile = Join-Path $tmpRoot "sample.txt"
|
|
Set-Content -LiteralPath $sampleFile -Value "selftest upload" -Encoding UTF8
|
|
$form = @{
|
|
file = Get-Item -LiteralPath $sampleFile
|
|
}
|
|
$upload = Invoke-RestMethod -Method Post -Uri "http://127.0.0.1:$AppPort/api/upload" -Form $form
|
|
if (-not $upload.filename) {
|
|
throw "업로드 응답에 filename이 없습니다."
|
|
}
|
|
$uploadedPath = Join-Path $downloadsDir $upload.filename
|
|
if (-not (Test-Path -LiteralPath $uploadedPath)) {
|
|
throw "업로드된 파일이 downloads에 존재하지 않습니다."
|
|
}
|
|
|
|
Write-Step "selftest ok"
|
|
} finally {
|
|
Stop-TrackedProcess -Process $appProcess
|
|
Stop-TrackedProcess -Process $mockProcess
|
|
if ($appStdoutTask) {
|
|
$appStdoutTask.Wait()
|
|
$appStdoutTask.Result | Set-Content -LiteralPath (Join-Path $tmpRoot "app.log") -Encoding UTF8
|
|
}
|
|
if ($appStderrTask) {
|
|
$appStderrTask.Wait()
|
|
$appStderrTask.Result | Add-Content -LiteralPath (Join-Path $tmpRoot "app.log") -Encoding UTF8
|
|
}
|
|
}
|