fix: load Sense package environment file (#46)
This commit is contained in:
@@ -5,6 +5,7 @@ for %%I in ("%~dp0..") do set "SENSE_ROOT=%%~fI"
|
||||
for %%I in ("%SENSE_ROOT%\dist") do set "OUTPUT_ROOT=%%~fI"
|
||||
for %%I in ("%OUTPUT_ROOT%\sense-windows-amd64") do set "PACKAGE_DIR=%%~fI"
|
||||
for %%I in ("%OUTPUT_ROOT%\sense-windows-amd64.zip") do set "ZIP_PATH=%%~fI"
|
||||
for %%I in ("%OUTPUT_ROOT%\.sense.env.preserve") do set "PRESERVED_ENV=%%~fI"
|
||||
for %%I in ("%SENSE_ROOT%\ui\dist") do set "UI_DIST=%%~fI"
|
||||
|
||||
if /I not "%PACKAGE_DIR%"=="%SENSE_ROOT%\dist\sense-windows-amd64" (
|
||||
@@ -15,6 +16,10 @@ if /I not "%ZIP_PATH%"=="%SENSE_ROOT%\dist\sense-windows-amd64.zip" (
|
||||
echo [ERROR] Unsafe ZIP path: %ZIP_PATH%
|
||||
exit /b 1
|
||||
)
|
||||
if /I not "%PRESERVED_ENV%"=="%SENSE_ROOT%\dist\.sense.env.preserve" (
|
||||
echo [ERROR] Unsafe preserved configuration path: %PRESERVED_ENV%
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
where go >nul 2>nul || goto :missing_go
|
||||
for /f "tokens=3" %%V in ('go version') do set "GO_VERSION=%%V"
|
||||
@@ -45,6 +50,14 @@ echo [2/5] Building frontend...
|
||||
call corepack pnpm@9.15.1 build || goto :failed_popd
|
||||
popd
|
||||
|
||||
if exist "%PRESERVED_ENV%" (
|
||||
echo [ERROR] Preserved configuration already exists: %PRESERVED_ENV%
|
||||
echo Move it back to config\sense.env or remove it after confirming it is obsolete.
|
||||
exit /b 1
|
||||
)
|
||||
if exist "%PACKAGE_DIR%\config\sense.env" (
|
||||
copy /y "%PACKAGE_DIR%\config\sense.env" "%PRESERVED_ENV%" >nul || goto :failed
|
||||
)
|
||||
if exist "%PACKAGE_DIR%" rmdir /s /q "%PACKAGE_DIR%"
|
||||
if exist "%ZIP_PATH%" del /q "%ZIP_PATH%"
|
||||
mkdir "%PACKAGE_DIR%\config" || goto :failed
|
||||
@@ -64,10 +77,14 @@ robocopy "%SENSE_ROOT%\LICENSES" "%PACKAGE_DIR%\LICENSES" /E /NFL /NDL /NJH /NJS
|
||||
if errorlevel 8 goto :failed
|
||||
copy /y "%SENSE_ROOT%\config\sense.env.example" "%PACKAGE_DIR%\config\sense.env.example" >nul || goto :failed
|
||||
copy /y "%SENSE_ROOT%\scripts\runtime\start-sense.bat" "%PACKAGE_DIR%\start-sense.bat" >nul || goto :failed
|
||||
copy /y "%SENSE_ROOT%\scripts\runtime\start-sense.ps1" "%PACKAGE_DIR%\start-sense.ps1" >nul || goto :failed
|
||||
copy /y "%SENSE_ROOT%\scripts\runtime\README-WINDOWS.md" "%PACKAGE_DIR%\README-WINDOWS.md" >nul || goto :failed
|
||||
|
||||
echo [5/5] Creating ZIP...
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -Command "Compress-Archive -Path '%PACKAGE_DIR%' -DestinationPath '%ZIP_PATH%' -Force" || goto :failed
|
||||
if exist "%PRESERVED_ENV%" (
|
||||
move /y "%PRESERVED_ENV%" "%PACKAGE_DIR%\config\sense.env" >nul || goto :failed
|
||||
)
|
||||
|
||||
echo.
|
||||
echo Package directory: %PACKAGE_DIR%
|
||||
|
||||
@@ -14,7 +14,7 @@ start-sense.bat demo
|
||||
|
||||
## 生产启动
|
||||
|
||||
生产环境必须先安装并准备独立 PostgreSQL,然后在仓库和运行包之外安全设置以下环境变量:
|
||||
生产环境必须先安装并准备独立 PostgreSQL。把配置写入运行目录的 `config\sense.env`,或在 Windows 进程环境中提供;已存在的非空进程环境变量优先于文件:
|
||||
|
||||
- `SENSE_DATABASE_URL`:PostgreSQL 连接地址。
|
||||
- `SENSE_IDENTITY_SIGNING_KEY`:至少 32 个字符的会话签名密钥。
|
||||
@@ -27,6 +27,12 @@ start-sense.bat demo
|
||||
start-sense.bat
|
||||
```
|
||||
|
||||
完整变量名可参考 `config\sense.env.example`。示例文件只有空值和非秘密默认值,启动脚本不会自动读取它;请使用 Windows 环境变量或外部秘密管理工具注入真实值。
|
||||
启动前可只检查配置,不连接数据库也不启动服务:
|
||||
|
||||
```bat
|
||||
start-sense.bat check
|
||||
```
|
||||
|
||||
完整变量名可参考 `config\sense.env.example`。复制为 `config\sense.env` 后填写真实值;该文件不会进入 ZIP 或 Git。本机在同一运行目录重新打包时会保留该文件,但交付 ZIP 始终不包含它。启动器只读取 `SENSE_*` 键,忽略空行与 `#` 注释,且不会打印配置值。生产环境仍建议使用 Windows 环境变量或外部秘密管理工具注入真实值。
|
||||
|
||||
健康检查为 `GET /healthz` 和 `GET /readyz`。MediaMTX 仍是独立程序,本运行包不会安装 PostgreSQL、MediaMTX 或 Windows 服务。
|
||||
|
||||
@@ -1,45 +1,5 @@
|
||||
@echo off
|
||||
setlocal
|
||||
cd /d "%~dp0"
|
||||
|
||||
set "SENSE_UI_STATIC_DIR=%~dp0ui"
|
||||
|
||||
if /I "%~1"=="demo" goto :demo
|
||||
|
||||
set "SENSE_DATABASE_MODE=postgres"
|
||||
if "%SENSE_DATABASE_URL%"=="" goto :missing_database_url
|
||||
if "%SENSE_IDENTITY_SIGNING_KEY%"=="" goto :missing_identity_key
|
||||
if "%SENSE_BOOTSTRAP_TOKEN%"=="" goto :missing_bootstrap_token
|
||||
if "%SENSE_CREDENTIAL_KEY%"=="" goto :missing_credential_key
|
||||
|
||||
echo Starting Sense in production mode at %SENSE_HTTP_ADDRESS%...
|
||||
"%~dp0sense-server.exe"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0start-sense.ps1" %*
|
||||
exit /b %ERRORLEVEL%
|
||||
|
||||
:demo
|
||||
set "SENSE_DATABASE_MODE=memory"
|
||||
if "%SENSE_HTTP_ADDRESS%"=="" set "SENSE_HTTP_ADDRESS=127.0.0.1:18080"
|
||||
echo Starting Sense in temporary demo mode at http://%SENSE_HTTP_ADDRESS% ...
|
||||
echo Demo data is discarded when the process stops. Do not use this mode in production.
|
||||
"%~dp0sense-server.exe"
|
||||
exit /b %ERRORLEVEL%
|
||||
|
||||
:missing_database_url
|
||||
echo [ERROR] SENSE_DATABASE_URL is required in production mode.
|
||||
goto :configuration_help
|
||||
|
||||
:missing_identity_key
|
||||
echo [ERROR] SENSE_IDENTITY_SIGNING_KEY is required in production mode.
|
||||
goto :configuration_help
|
||||
|
||||
:missing_bootstrap_token
|
||||
echo [ERROR] SENSE_BOOTSTRAP_TOKEN is required in production mode.
|
||||
goto :configuration_help
|
||||
|
||||
:missing_credential_key
|
||||
echo [ERROR] SENSE_CREDENTIAL_KEY is required in production mode.
|
||||
|
||||
:configuration_help
|
||||
echo Set the required environment variables outside this directory.
|
||||
echo See README-WINDOWS.md and config\sense.env.example.
|
||||
exit /b 1
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
param(
|
||||
[ValidateSet('production', 'demo', 'check')]
|
||||
[string]$Mode = 'production'
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
function Import-SenseEnvironment {
|
||||
param([string]$Path)
|
||||
|
||||
if (-not (Test-Path -LiteralPath $Path -PathType Leaf)) {
|
||||
return
|
||||
}
|
||||
|
||||
$lineNumber = 0
|
||||
foreach ($line in Get-Content -LiteralPath $Path -Encoding UTF8) {
|
||||
$lineNumber++
|
||||
$trimmed = $line.Trim()
|
||||
if ($trimmed.Length -eq 0 -or $trimmed.StartsWith('#')) {
|
||||
continue
|
||||
}
|
||||
if ($line -notmatch '^\s*(SENSE_[A-Z0-9_]+)\s*=(.*)$') {
|
||||
throw "config\sense.env line $lineNumber must use SENSE_NAME=value format"
|
||||
}
|
||||
|
||||
$name = $Matches[1]
|
||||
$value = $Matches[2].Trim()
|
||||
if ($value.Length -ge 2) {
|
||||
$first = $value[0]
|
||||
$last = $value[$value.Length - 1]
|
||||
if (($first -eq '"' -and $last -eq '"') -or ($first -eq "'" -and $last -eq "'")) {
|
||||
$value = $value.Substring(1, $value.Length - 2)
|
||||
}
|
||||
}
|
||||
|
||||
$current = [Environment]::GetEnvironmentVariable($name, 'Process')
|
||||
if ([string]::IsNullOrEmpty($current)) {
|
||||
[Environment]::SetEnvironmentVariable($name, $value, 'Process')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Assert-RequiredEnvironment {
|
||||
param([string[]]$Names)
|
||||
|
||||
foreach ($name in $Names) {
|
||||
if ([string]::IsNullOrWhiteSpace([Environment]::GetEnvironmentVariable($name, 'Process'))) {
|
||||
throw "$name is required in production mode"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$runtimeRoot = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
Import-SenseEnvironment -Path (Join-Path $runtimeRoot 'config\sense.env')
|
||||
|
||||
[Environment]::SetEnvironmentVariable('SENSE_UI_STATIC_DIR', (Join-Path $runtimeRoot 'ui'), 'Process')
|
||||
if ([string]::IsNullOrWhiteSpace($env:SENSE_HTTP_ADDRESS)) {
|
||||
$env:SENSE_HTTP_ADDRESS = '127.0.0.1:18080'
|
||||
}
|
||||
|
||||
if ($Mode -eq 'demo') {
|
||||
$env:SENSE_DATABASE_MODE = 'memory'
|
||||
Write-Host "Starting Sense in temporary demo mode at http://$($env:SENSE_HTTP_ADDRESS) ..."
|
||||
Write-Host 'Demo data is discarded when the process stops. Do not use this mode in production.'
|
||||
} else {
|
||||
$env:SENSE_DATABASE_MODE = 'postgres'
|
||||
Assert-RequiredEnvironment -Names @(
|
||||
'SENSE_DATABASE_URL',
|
||||
'SENSE_IDENTITY_SIGNING_KEY',
|
||||
'SENSE_BOOTSTRAP_TOKEN',
|
||||
'SENSE_CREDENTIAL_KEY'
|
||||
)
|
||||
if ($Mode -eq 'check') {
|
||||
Write-Host 'Sense production configuration check passed.'
|
||||
exit 0
|
||||
}
|
||||
Write-Host "Starting Sense in production mode at $($env:SENSE_HTTP_ADDRESS) ..."
|
||||
}
|
||||
|
||||
$server = Join-Path $runtimeRoot 'sense-server.exe'
|
||||
if (-not (Test-Path -LiteralPath $server -PathType Leaf)) {
|
||||
throw 'sense-server.exe was not found beside the start script'
|
||||
}
|
||||
& $server
|
||||
exit $LASTEXITCODE
|
||||
} catch {
|
||||
Write-Host "[ERROR] $($_.Exception.Message)"
|
||||
Write-Host 'See README-WINDOWS.md and config\sense.env.example.'
|
||||
exit 1
|
||||
}
|
||||
Reference in New Issue
Block a user