update.ps1 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. # ==============================================================================
  2. # lf_mri_platform -- Pull latest code and rebuild services
  3. # Usage:
  4. # .\update.ps1 -- git pull + rebuild all containers
  5. # .\update.ps1 -Services o,s -- rebuild only listed services (comma-separated)
  6. # .\update.ps1 -SkipGit -- skip git pull (only rebuild)
  7. # .\update.ps1 -RestartSpec -- also restart the native spectrometer
  8. # ==============================================================================
  9. param(
  10. [string]$Services = "", # e.g. "orchestrator,seq-interp"
  11. [switch]$SkipGit,
  12. [switch]$RestartSpec
  13. )
  14. $ErrorActionPreference = "Stop"
  15. $Root = $PSScriptRoot
  16. $EnvFile = Join-Path $Root ".env"
  17. function Write-Step($msg) { Write-Host "`n==> $msg" -ForegroundColor Cyan }
  18. function Write-OK($msg) { Write-Host " [OK] $msg" -ForegroundColor Green }
  19. function Write-Warn($msg) { Write-Host " [!!] $msg" -ForegroundColor Yellow }
  20. function Write-Fail($msg) { Write-Host "`n[FAIL] $msg" -ForegroundColor Red; exit 1 }
  21. # -- 1. Git pull ---------------------------------------------------------------
  22. if (-not $SkipGit) {
  23. Write-Step "Pulling latest code"
  24. Push-Location $Root
  25. try {
  26. $before = & git rev-parse HEAD 2>$null
  27. & git pull
  28. if ($LASTEXITCODE -ne 0) { Write-Fail "git pull failed" }
  29. $after = & git rev-parse HEAD 2>$null
  30. if ($before -eq $after) {
  31. Write-OK "Already up to date ($($after.Substring(0,8)))"
  32. } else {
  33. Write-OK "Updated $($before.Substring(0,8)) -> $($after.Substring(0,8))"
  34. Write-Host ""
  35. & git log --oneline "$before..$after"
  36. }
  37. } finally {
  38. Pop-Location
  39. }
  40. }
  41. # -- 2. Check Docker -----------------------------------------------------------
  42. Write-Step "Checking Docker"
  43. try { & docker info *>$null } catch {
  44. Write-Fail "Docker is not running. Start Docker Desktop and try again."
  45. }
  46. Write-OK "Docker is running"
  47. # -- 3. Rebuild containers -----------------------------------------------------
  48. Write-Step "Rebuilding containers"
  49. $envArgs = if (Test-Path $EnvFile) { @("--env-file", $EnvFile) } else { @() }
  50. if ($Services) {
  51. $svcList = $Services -split "," | ForEach-Object { $_.Trim() } | Where-Object { $_ }
  52. Write-Host " Services: $($svcList -join ', ')" -ForegroundColor DarkGray
  53. & docker compose @envArgs up --build -d @svcList
  54. } else {
  55. Write-Host " Services: all" -ForegroundColor DarkGray
  56. & docker compose @envArgs up --build -d
  57. }
  58. if ($LASTEXITCODE -ne 0) { Write-Fail "docker compose up --build failed" }
  59. Write-OK "Containers rebuilt and started"
  60. # -- 4. Optionally restart the native spectrometer ----------------------------
  61. if ($RestartSpec) {
  62. Write-Step "Restarting native spectrometer"
  63. $specProc = Get-Process -Name python* -ErrorAction SilentlyContinue |
  64. Where-Object { $_.CommandLine -like "*manage.py*runserver*" }
  65. if ($specProc) {
  66. Write-Host " Stopping old spectrometer process (PID $($specProc.Id))..." -ForegroundColor DarkGray
  67. Stop-Process -Id $specProc.Id -Force
  68. Start-Sleep 1
  69. Write-OK "Old process stopped"
  70. } else {
  71. Write-Warn "No running spectrometer process found -- will start fresh"
  72. }
  73. $specDir = Join-Path $Root "services\spectrometer"
  74. $python = "python"
  75. # Try project venv first
  76. $venvPy = Join-Path $Root "apps\gui\.venv\Scripts\python.exe"
  77. if (Test-Path $venvPy) { $python = $venvPy }
  78. Write-Host " Starting spectrometer at $specDir ..." -ForegroundColor DarkGray
  79. Start-Process $python `
  80. -ArgumentList "manage.py runserver 0.0.0.0:8000" `
  81. -WorkingDirectory $specDir `
  82. -WindowStyle Normal
  83. Write-OK "Spectrometer started in new window"
  84. }
  85. # -- 5. Health check -----------------------------------------------------------
  86. Write-Step "Checking service health"
  87. function Get-EnvPort($key, $default) {
  88. if (Test-Path $EnvFile) {
  89. $line = Get-Content $EnvFile | Select-String "^$key=(\d+)"
  90. if ($line) { return $line.Matches[0].Groups[1].Value }
  91. }
  92. return $default
  93. }
  94. $checks = @(
  95. @{ Name = "Orchestrator"; Url = "http://localhost:$(Get-EnvPort 'ORCHESTRATOR_PORT' '1717')/health"; Native = $false },
  96. @{ Name = "Seq-Interp"; Url = "http://localhost:$(Get-EnvPort 'SEQ_INTERP_PORT' '7475')/health"; Native = $false },
  97. @{ Name = "Spectroscopy"; Url = "http://localhost:$(Get-EnvPort 'SPECTROSCOPY_PORT' '8002')/health"; Native = $false },
  98. @{ Name = "Spectrometer*"; Url = "http://localhost:$(Get-EnvPort 'SPECTROMETER_PORT' '8000')/api/"; Native = $true }
  99. )
  100. $maxWait = 60; $interval = 3; $elapsed = 0
  101. while ($elapsed -lt $maxWait) {
  102. $pending = @()
  103. foreach ($c in $checks) {
  104. try {
  105. $r = Invoke-WebRequest $c.Url -UseBasicParsing -TimeoutSec 2 -ErrorAction Stop
  106. if ($r.StatusCode -ge 400) { $pending += $c.Name }
  107. } catch { $pending += $c.Name }
  108. }
  109. if ($pending.Count -eq 0) { break }
  110. Write-Host (" ... {0}/{1} s waiting: {2}" -f $elapsed, $maxWait, ($pending -join ", ")) -ForegroundColor DarkGray
  111. Start-Sleep $interval; $elapsed += $interval
  112. }
  113. Write-Host ""
  114. foreach ($c in $checks) {
  115. try {
  116. $r = Invoke-WebRequest $c.Url -UseBasicParsing -TimeoutSec 2 -ErrorAction Stop
  117. $ok = $r.StatusCode -lt 400
  118. } catch { $ok = $false }
  119. $icon = if ($ok) { "[OK]" } else { "[--]" }
  120. $color = if ($ok) { "Green" } elseif ($c.Native) { "DarkGray" } else { "Yellow" }
  121. $suffix = if ($c.Native) { " (native – start manually if needed)" } else { "" }
  122. Write-Host (" {0,-6} {1,-16} {2}{3}" -f $icon, $c.Name, $c.Url, $suffix) -ForegroundColor $color
  123. }
  124. # -- 6. Summary ----------------------------------------------------------------
  125. Write-Host ""
  126. Write-Host "============================================================" -ForegroundColor Green
  127. Write-Host " Update complete" -ForegroundColor Green
  128. Write-Host "============================================================" -ForegroundColor Green
  129. Write-Host ""
  130. Write-Host " To rebuild only specific services next time:"
  131. Write-Host " .\update.ps1 -Services orchestrator,seq-interp"
  132. Write-Host ""
  133. Write-Host " To also restart the native spectrometer:"
  134. Write-Host " .\update.ps1 -RestartSpec"
  135. Write-Host ""
  136. Write-Host " Press Enter to close this window..." -ForegroundColor DarkGray
  137. $null = Read-Host