docs: project docs, scripts, deployment configs, and evidence
This commit is contained in:
35
scripts/dev/init-admin-local.ps1
Normal file
35
scripts/dev/init-admin-local.ps1
Normal file
@@ -0,0 +1,35 @@
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$Username,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$Password,
|
||||
|
||||
[string]$Email = '',
|
||||
|
||||
[switch]$ResetPassword
|
||||
)
|
||||
|
||||
$repoRoot = (Resolve-Path (Join-Path $PSScriptRoot '..\..')).Path
|
||||
$cacheRoot = Join-Path $repoRoot '.cache\go'
|
||||
$buildCache = Join-Path $repoRoot '.cache\go-build'
|
||||
$modCache = Join-Path $cacheRoot 'pkg\mod'
|
||||
|
||||
New-Item -ItemType Directory -Force $cacheRoot, $buildCache, $modCache | Out-Null
|
||||
|
||||
$env:GOPATH = $cacheRoot
|
||||
$env:GOCACHE = $buildCache
|
||||
$env:GOMODCACHE = $modCache
|
||||
$env:UMS_ADMIN_USERNAME = $Username
|
||||
$env:UMS_ADMIN_PASSWORD = $Password
|
||||
$env:UMS_ADMIN_EMAIL = $Email
|
||||
$env:UMS_ADMIN_RESET_PASSWORD = if ($ResetPassword.IsPresent) { 'true' } else { 'false' }
|
||||
|
||||
Push-Location $repoRoot
|
||||
try {
|
||||
& go run .\tools\init_admin.go
|
||||
} finally {
|
||||
Pop-Location
|
||||
}
|
||||
135
scripts/dev/start-preview-local.ps1
Normal file
135
scripts/dev/start-preview-local.ps1
Normal file
@@ -0,0 +1,135 @@
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
function Stop-TrackedProcess {
|
||||
param(
|
||||
[string]$PidFile
|
||||
)
|
||||
|
||||
if (-not (Test-Path $PidFile)) {
|
||||
return
|
||||
}
|
||||
|
||||
$pidText = (Get-Content $PidFile -Raw).Trim()
|
||||
if (-not $pidText) {
|
||||
Remove-Item $PidFile -Force -ErrorAction SilentlyContinue
|
||||
return
|
||||
}
|
||||
|
||||
$existing = Get-Process -Id ([int]$pidText) -ErrorAction SilentlyContinue
|
||||
if ($null -ne $existing) {
|
||||
Stop-Process -Id $existing.Id -Force
|
||||
}
|
||||
|
||||
Remove-Item $PidFile -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
function Wait-HttpReady {
|
||||
param(
|
||||
[string]$Url,
|
||||
[int]$MaxAttempts = 60,
|
||||
[int]$SleepSeconds = 1
|
||||
)
|
||||
|
||||
for ($i = 0; $i -lt $MaxAttempts; $i++) {
|
||||
try {
|
||||
$response = Invoke-WebRequest -UseBasicParsing -Uri $Url -TimeoutSec 3
|
||||
return $response
|
||||
} catch {
|
||||
Start-Sleep -Seconds $SleepSeconds
|
||||
}
|
||||
}
|
||||
|
||||
return $null
|
||||
}
|
||||
|
||||
function Show-LogTail {
|
||||
param(
|
||||
[string]$Path
|
||||
)
|
||||
|
||||
if (Test-Path $Path) {
|
||||
Write-Host ""
|
||||
Write-Host "Last log lines: $Path"
|
||||
Get-Content $Path -Tail 40
|
||||
}
|
||||
}
|
||||
|
||||
$repoRoot = (Resolve-Path (Join-Path $PSScriptRoot '..\..')).Path
|
||||
$frontendRoot = Join-Path $repoRoot 'frontend\admin'
|
||||
$runtimeRoot = Join-Path $repoRoot 'runtime'
|
||||
$logsRoot = Join-Path $repoRoot 'logs'
|
||||
$binRoot = Join-Path $repoRoot 'bin'
|
||||
$cacheRoot = Join-Path $repoRoot '.cache\go'
|
||||
$buildCache = Join-Path $repoRoot '.cache\go-build'
|
||||
$modCache = Join-Path $cacheRoot 'pkg\mod'
|
||||
|
||||
New-Item -ItemType Directory -Force $runtimeRoot, $logsRoot, $binRoot, $cacheRoot, $buildCache, $modCache | Out-Null
|
||||
|
||||
$backendPidFile = Join-Path $runtimeRoot 'backend.pid'
|
||||
$frontendPidFile = Join-Path $runtimeRoot 'frontend.pid'
|
||||
$backendOut = Join-Path $logsRoot 'backend-dev.out.log'
|
||||
$backendErr = Join-Path $logsRoot 'backend-dev.err.log'
|
||||
$frontendOut = Join-Path $logsRoot 'frontend-dev.out.log'
|
||||
$frontendErr = Join-Path $logsRoot 'frontend-dev.err.log'
|
||||
$backendExe = Join-Path $binRoot 'server.exe'
|
||||
|
||||
Stop-TrackedProcess -PidFile $backendPidFile
|
||||
Stop-TrackedProcess -PidFile $frontendPidFile
|
||||
|
||||
Remove-Item $backendOut, $backendErr, $frontendOut, $frontendErr -Force -ErrorAction SilentlyContinue
|
||||
|
||||
$env:GOPATH = $cacheRoot
|
||||
$env:GOCACHE = $buildCache
|
||||
$env:GOMODCACHE = $modCache
|
||||
|
||||
Push-Location $repoRoot
|
||||
try {
|
||||
& go build -o $backendExe .\cmd\server
|
||||
} finally {
|
||||
Pop-Location
|
||||
}
|
||||
|
||||
$node = (Get-Command node).Source
|
||||
|
||||
$backendProcess = Start-Process -FilePath $backendExe `
|
||||
-WorkingDirectory $repoRoot `
|
||||
-RedirectStandardOutput $backendOut `
|
||||
-RedirectStandardError $backendErr `
|
||||
-PassThru
|
||||
Set-Content -Path $backendPidFile -Value $backendProcess.Id
|
||||
|
||||
$frontendProcess = Start-Process -FilePath $node `
|
||||
-ArgumentList '.\node_modules\vite\bin\vite.js', '--configLoader', 'native', '--host', '0.0.0.0', '--port', '3000' `
|
||||
-WorkingDirectory $frontendRoot `
|
||||
-RedirectStandardOutput $frontendOut `
|
||||
-RedirectStandardError $frontendErr `
|
||||
-PassThru
|
||||
Set-Content -Path $frontendPidFile -Value $frontendProcess.Id
|
||||
|
||||
$backendReady = Wait-HttpReady -Url 'http://127.0.0.1:8080/health'
|
||||
$frontendReady = Wait-HttpReady -Url 'http://127.0.0.1:3000'
|
||||
|
||||
if ($null -eq $backendReady) {
|
||||
Write-Host 'Backend failed to become ready on http://127.0.0.1:8080/health'
|
||||
Show-LogTail -Path $backendErr
|
||||
Show-LogTail -Path $backendOut
|
||||
exit 1
|
||||
}
|
||||
|
||||
if ($null -eq $frontendReady) {
|
||||
Write-Host 'Frontend failed to become ready on http://127.0.0.1:3000'
|
||||
Show-LogTail -Path $frontendErr
|
||||
Show-LogTail -Path $frontendOut
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Host ''
|
||||
Write-Host "Backend ready: http://127.0.0.1:8080"
|
||||
Write-Host "Frontend ready: http://127.0.0.1:3000"
|
||||
Write-Host "Backend PID: $($backendProcess.Id)"
|
||||
Write-Host "Frontend PID: $($frontendProcess.Id)"
|
||||
Write-Host "Stop command: powershell -ExecutionPolicy Bypass -File scripts/dev/stop-preview-local.ps1"
|
||||
Write-Host ""
|
||||
Write-Host "Note: this repository does not ship a default admin account."
|
||||
Write-Host "If login fails on first run, initialize one explicitly:"
|
||||
Write-Host " powershell -ExecutionPolicy Bypass -File scripts/dev/init-admin-local.ps1 -Username admin -Password '<strong-password>' -Email 'admin@example.com'"
|
||||
31
scripts/dev/stop-preview-local.ps1
Normal file
31
scripts/dev/stop-preview-local.ps1
Normal file
@@ -0,0 +1,31 @@
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
function Stop-TrackedProcess {
|
||||
param(
|
||||
[string]$PidFile
|
||||
)
|
||||
|
||||
if (-not (Test-Path $PidFile)) {
|
||||
return
|
||||
}
|
||||
|
||||
$pidText = (Get-Content $PidFile -Raw).Trim()
|
||||
if (-not $pidText) {
|
||||
Remove-Item $PidFile -Force -ErrorAction SilentlyContinue
|
||||
return
|
||||
}
|
||||
|
||||
$existing = Get-Process -Id ([int]$pidText) -ErrorAction SilentlyContinue
|
||||
if ($null -ne $existing) {
|
||||
Stop-Process -Id $existing.Id -Force
|
||||
Write-Host "Stopped PID $($existing.Id)"
|
||||
}
|
||||
|
||||
Remove-Item $PidFile -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
$repoRoot = (Resolve-Path (Join-Path $PSScriptRoot '..\..')).Path
|
||||
$runtimeRoot = Join-Path $repoRoot 'runtime'
|
||||
|
||||
Stop-TrackedProcess -PidFile (Join-Path $runtimeRoot 'backend.pid')
|
||||
Stop-TrackedProcess -PidFile (Join-Path $runtimeRoot 'frontend.pid')
|
||||
Reference in New Issue
Block a user