@@ -12,6 +12,7 @@ permissions:
1212env :
1313 # Derived from tag at runtime (e.g. v1.0.3 -> 1.0.3)
1414 RELEASE_VERSION : " "
15+ # Starting port written into engine-config.json in CI (engine may increment).
1516 ENGINE_PORT : " 8740"
1617
1718jobs :
@@ -93,19 +94,41 @@ jobs:
9394 - name : Validate engine runs (health check)
9495 shell : pwsh
9596 run : |
96- $p = Start-Process -FilePath ".\\dist\\SentraCoreEngine.exe" -PassThru -WindowStyle Hidden
97+ $cfgPath = Resolve-Path ".\\dist\\engine-config.json"
98+ # Kill anything listening on the start port (best-effort).
99+ $startPort = [int]${env:ENGINE_PORT}
100+ $pids = (Get-NetTCPConnection -State Listen -LocalPort $startPort -ErrorAction SilentlyContinue | Select-Object -ExpandProperty OwningProcess -Unique)
101+ foreach ($pid in $pids) { try { Stop-Process -Id $pid -Force } catch {} }
102+ # Write engine-config.json next to engine (single source of truth).
103+ $cfg = @{
104+ host = "127.0.0.1"
105+ port = $startPort
106+ bind_host = "127.0.0.1"
107+ status = "stopped"
108+ last_error = ""
109+ pid = 0
110+ } | ConvertTo-Json
111+ $tmp = "$cfgPath.tmp"
112+ $cfg | Out-File -FilePath $tmp -Encoding utf8
113+ Move-Item -Force $tmp $cfgPath
114+ $p = Start-Process -FilePath ".\\dist\\SentraCoreEngine.exe" -PassThru -WindowStyle Hidden -Environment @{ "SENTRACORE_ENGINE_CONFIG" = "$cfgPath" }
97115 try {
98116 $ok = $false
99117 for ($i=0; $i -lt 40; $i++) {
100118 try {
101- $r = Invoke-WebRequest -UseBasicParsing -TimeoutSec 2 "http://127.0.0.1:${env:ENGINE_PORT}/api/v1/health"
119+ $cfgDisk = $null
120+ try { $cfgDisk = Get-Content "$cfgPath" -Raw | ConvertFrom-Json } catch {}
121+ $host = if ($cfgDisk -and $cfgDisk.host) { $cfgDisk.host } else { "127.0.0.1" }
122+ $port = if ($cfgDisk -and $cfgDisk.port) { [int]$cfgDisk.port } else { $startPort }
123+ $r = Invoke-WebRequest -UseBasicParsing -TimeoutSec 2 "http://$host`:$port/api/v1/health"
102124 if ($r.StatusCode -eq 200) { $ok = $true; break }
103125 } catch {}
104126 Start-Sleep -Milliseconds 500
105127 }
106128 if (-not $ok) { throw "Engine health check failed" }
107129 } finally {
108130 try { Stop-Process -Id $p.Id -Force } catch {}
131+ try { Stop-Process -Name "SentraCoreEngine" -Force } catch {}
109132 }
110133
111134 - name : Setup Flutter
@@ -210,17 +233,43 @@ jobs:
210233 - name : Validate engine runs (health check)
211234 run : |
212235 chmod +x dist/SentraCoreEngine
213- ./dist/SentraCoreEngine &
236+ START_PORT="${ENGINE_PORT:-8740}"
237+ # Kill anything on start port (best-effort).
238+ lsof -ti "tcp:${START_PORT}" | xargs kill -9 2>/dev/null || true
239+ # Write engine-config.json next to engine.
240+ cat > dist/engine-config.json <<EOF
241+ {
242+ "host": "127.0.0.1",
243+ "port": ${START_PORT},
244+ "bind_host": "127.0.0.1",
245+ "status": "stopped",
246+ "last_error": "",
247+ "pid": 0
248+ }
249+ EOF
250+ SENTRACORE_ENGINE_CONFIG="$(pwd)/dist/engine-config.json" ./dist/SentraCoreEngine &
214251 PID=$!
215252 OK=0
216253 for i in {1..40}; do
217- if curl -fsS --max-time 2 "http://127.0.0.1:${ENGINE_PORT}/api/v1/health" >/dev/null; then
254+ PORT="$(python - <<'PY'
255+ import json, pathlib
256+ p = pathlib.Path("dist/engine-config.json")
257+ try:
258+ j = json.loads(p.read_text())
259+ print(int(j.get("port", 0)) or 0)
260+ except Exception:
261+ print(0)
262+ PY
263+ )"
264+ if [ -z "$PORT" ] || [ "$PORT" = "0" ]; then PORT="$START_PORT"; fi
265+ if curl -fsS --max-time 2 "http://127.0.0.1:${PORT}/api/v1/health" >/dev/null; then
218266 OK=1
219267 break
220268 fi
221269 sleep 0.5
222270 done
223271 kill $PID || true
272+ pkill -f SentraCoreEngine || true
224273 if [ "$OK" -ne 1 ]; then
225274 echo "Engine health check failed"
226275 exit 1
@@ -330,17 +379,41 @@ jobs:
330379 - name : Validate engine runs (health check)
331380 run : |
332381 chmod +x dist/SentraCoreEngine
333- ./dist/SentraCoreEngine &
382+ START_PORT="${ENGINE_PORT:-8740}"
383+ fuser -k "${START_PORT}/tcp" 2>/dev/null || true
384+ cat > dist/engine-config.json <<EOF
385+ {
386+ "host": "127.0.0.1",
387+ "port": ${START_PORT},
388+ "bind_host": "0.0.0.0",
389+ "status": "stopped",
390+ "last_error": "",
391+ "pid": 0
392+ }
393+ EOF
394+ SENTRACORE_ENGINE_CONFIG="$(pwd)/dist/engine-config.json" ./dist/SentraCoreEngine &
334395 PID=$!
335396 OK=0
336397 for i in {1..40}; do
337- if curl -fsS --max-time 2 "http://127.0.0.1:${ENGINE_PORT}/api/v1/health" >/dev/null; then
398+ PORT="$(python - <<'PY'
399+ import json, pathlib
400+ p = pathlib.Path("dist/engine-config.json")
401+ try:
402+ j = json.loads(p.read_text())
403+ print(int(j.get("port", 0)) or 0)
404+ except Exception:
405+ print(0)
406+ PY
407+ )"
408+ if [ -z "$PORT" ] || [ "$PORT" = "0" ]; then PORT="$START_PORT"; fi
409+ if curl -fsS --max-time 2 "http://127.0.0.1:${PORT}/api/v1/health" >/dev/null; then
338410 OK=1
339411 break
340412 fi
341413 sleep 0.5
342414 done
343415 kill $PID || true
416+ pkill -f SentraCoreEngine || true
344417 if [ "$OK" -ne 1 ]; then
345418 echo "Engine health check failed"
346419 exit 1
@@ -373,19 +446,38 @@ jobs:
373446 set -e
374447 HERE="$(dirname "$(readlink -f "$0")")"
375448 cd "$HERE/usr/bin"
449+ # Create engine-config.json (single source of truth) next to binaries.
450+ if [ ! -f "./engine-config.json" ]; then
451+ cat > "./engine-config.json" <<'JSON'
452+ {
453+ "host": "127.0.0.1",
454+ "port": 8740,
455+ "bind_host": "0.0.0.0",
456+ "status": "stopped",
457+ "last_error": "",
458+ "pid": 0
459+ }
460+ JSON
461+ fi
376462 # Start engine in background (best-effort) and stop it when UI exits.
377- ./SentraCoreEngine >/dev/null 2>&1 &
463+ SENTRACORE_ENGINE_CONFIG="$HERE/usr/bin/engine-config.json" ./SentraCoreEngine >/dev/null 2>&1 &
378464 ENGINE_PID=$!
379- trap "kill $ENGINE_PID >/dev/null 2>&1 || true" EXIT
465+ trap "kill $ENGINE_PID >/dev/null 2>&1 || true; pkill -f SentraCoreEngine >/dev/null 2>&1 || true " EXIT
380466 # Wait until engine responds (avoid UI starting before backend).
381467 OK=0
382468 for i in $(seq 1 40); do
383- if curl -fsS --max-time 2 "http://127.0.0.1:${ENGINE_PORT}/api/v1/health" >/dev/null; then
469+ PORT="$(sed -n 's/.*\"port\"[[:space:]]*:[[:space:]]*\\([0-9][0-9]*\\).*/\\1/p' ./engine-config.json | head -n 1)"
470+ if [ -z "$PORT" ]; then PORT="8740"; fi
471+ if curl -fsS --max-time 2 "http://127.0.0.1:${PORT}/api/v1/health" >/dev/null; then
384472 OK=1
385473 break
386474 fi
387475 sleep 0.5
388476 done
477+ if [ "$OK" -ne 1 ]; then
478+ echo "Engine health check failed"
479+ exit 1
480+ fi
389481 exec ./sentracore_dashboard "$@"
390482 EOF
391483 chmod +x SentraCore.AppDir/AppRun
0 commit comments