192 lines
8.1 KiB
PowerShell
192 lines
8.1 KiB
PowerShell
#Requires -Version 5.1
|
|
<#
|
|
.SYNOPSIS
|
|
Installs everything owpengram-server.bat checks for, via winget: Go, Python 3
|
|
(+ the panel's packages in a venv) and OpenSSL.
|
|
|
|
.DESCRIPTION
|
|
Docker is the deliberate exception. It is only reported, with a link: on Windows
|
|
the containers this server needs (PostgreSQL, Redis, MinIO) are Linux images, so
|
|
the daemon has to sit on a Linux kernel -- which means Docker Desktop with WSL2,
|
|
an install that wants a reboot and carries its own licence terms. That is not a
|
|
thing to start behind someone's back.
|
|
|
|
.PARAMETER DryRun
|
|
Only report what would be installed.
|
|
|
|
.PARAMETER Yes
|
|
Skip the confirmation prompt.
|
|
#>
|
|
param(
|
|
[switch]$DryRun,
|
|
[switch]$Yes
|
|
)
|
|
|
|
Set-StrictMode -Version Latest
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
$RepoRoot = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path
|
|
$DockerDocs = 'https://docs.docker.com/desktop/setup/install/windows-install/'
|
|
$GoMinMinor = 25
|
|
|
|
function Write-Ok { param([string]$Text) Write-Host "[ok] $Text" -ForegroundColor Green }
|
|
function Write-Info { param([string]$Text) Write-Host "[..] $Text" -ForegroundColor Cyan }
|
|
function Write-Warn { param([string]$Text) Write-Host "[WARN] $Text" -ForegroundColor Yellow }
|
|
function Write-Err { param([string]$Text) Write-Host "[ERROR] $Text" -ForegroundColor Red }
|
|
|
|
function Test-Command { param([string]$Name) [bool](Get-Command $Name -ErrorAction SilentlyContinue) }
|
|
|
|
# winget puts new tools on the machine/user PATH, but this process was started
|
|
# with the old one -- without this the venv step cannot find the Python it just
|
|
# installed, and the closing "go version" would report the absence of Go.
|
|
function Update-PathFromRegistry {
|
|
$machine = [Environment]::GetEnvironmentVariable('Path', 'Machine')
|
|
$user = [Environment]::GetEnvironmentVariable('Path', 'User')
|
|
$env:Path = (@($machine, $user) | Where-Object { $_ }) -join ';'
|
|
}
|
|
|
|
# python.exe on a stock Windows is often the Microsoft Store's app-execution
|
|
# alias: present on PATH, and it opens the Store instead of running anything.
|
|
# Only a real version string counts, which is the same trap owpengram-server.bat
|
|
# documents.
|
|
function Get-WorkingPython {
|
|
foreach ($candidate in @('py -3', 'python3', 'python')) {
|
|
$parts = $candidate.Split(' ')
|
|
if (-not (Test-Command $parts[0])) { continue }
|
|
try {
|
|
$out = & $parts[0] @($parts[1..($parts.Length - 1)] + '--version') 2>&1 | Out-String
|
|
} catch { continue }
|
|
if ($out -match 'Python 3\.') { return $candidate }
|
|
}
|
|
return $null
|
|
}
|
|
|
|
function Test-GoRecentEnough {
|
|
if (-not (Test-Command 'go')) { return $false }
|
|
try { $version = (& go env GOVERSION 2>$null | Out-String).Trim() } catch { return $false }
|
|
if ($version -match '^go1\.(\d+)') { return [int]$Matches[1] -ge $GoMinMinor }
|
|
return $false
|
|
}
|
|
|
|
# Same precedence owpengram-server.bat uses when it picks an interpreter: the
|
|
# venv when one exists, otherwise whatever Python is on PATH. Checking only the
|
|
# venv would report the packages missing on a machine that already has them
|
|
# installed system-wide, and build a venv nobody asked for.
|
|
function Test-PanelDepsInstalled {
|
|
$checker = Join-Path $RepoRoot 'tui-panel\check_deps.py'
|
|
$venvPython = Join-Path $RepoRoot '.venv\Scripts\python.exe'
|
|
if (Test-Path $venvPython) {
|
|
$missing = & $venvPython $checker 2>$null | Out-String
|
|
return [string]::IsNullOrWhiteSpace($missing)
|
|
}
|
|
$fallback = Get-WorkingPython
|
|
if (-not $fallback) { return $false }
|
|
$parts = $fallback.Split(' ')
|
|
$missing = & $parts[0] @($parts[1..($parts.Length - 1)] + $checker) 2>$null | Out-String
|
|
return [string]::IsNullOrWhiteSpace($missing)
|
|
}
|
|
|
|
function Install-WingetPackage {
|
|
param([string]$Id, [string]$Label)
|
|
Write-Info "Installing $Label ($Id)"
|
|
& winget install --exact --id $Id --source winget `
|
|
--accept-package-agreements --accept-source-agreements --disable-interactivity
|
|
# 0 is installed; -1978335189 is "no applicable upgrade", i.e. already current.
|
|
if ($LASTEXITCODE -ne 0 -and $LASTEXITCODE -ne -1978335189) {
|
|
throw "winget failed to install $Id (exit $LASTEXITCODE)"
|
|
}
|
|
Update-PathFromRegistry
|
|
}
|
|
|
|
if (-not (Test-Command 'winget')) {
|
|
Write-Err 'winget is not available. Install "App Installer" from the Microsoft Store, then run this again.'
|
|
exit 1
|
|
}
|
|
|
|
# --- what is missing ---------------------------------------------------------
|
|
$python = Get-WorkingPython
|
|
$needed = [System.Collections.Generic.List[string]]::new()
|
|
if (-not (Test-GoRecentEnough)) { $needed.Add('go') }
|
|
if (-not $python) { $needed.Add('python') }
|
|
if (-not (Test-Command 'openssl')) { $needed.Add('openssl') }
|
|
if (-not (Test-PanelDepsInstalled)) { $needed.Add('pydeps') }
|
|
$dockerMissing = -not (Test-Command 'docker')
|
|
|
|
if ($needed.Count -eq 0 -and -not $dockerMissing) {
|
|
Write-Ok 'All prerequisites are already installed.'
|
|
exit 0
|
|
}
|
|
|
|
Write-Host ''
|
|
Write-Host '== Missing prerequisites ==' -ForegroundColor Yellow
|
|
foreach ($item in $needed) {
|
|
switch ($item) {
|
|
'go' { Write-Host " - Go 1.$GoMinMinor+ (builds owpengram-server and the admin panel)" }
|
|
'python' { Write-Host ' - Python 3 (runs the server-panel TUI)' }
|
|
'pydeps' { Write-Host ' - Python packages: textual, psutil, cryptography (into .\.venv)' }
|
|
'openssl' { Write-Host " - OpenSSL (exports the server's RSA public key for clients)" }
|
|
}
|
|
}
|
|
if ($dockerMissing) { Write-Host ' - Docker (runs PostgreSQL, Redis and MinIO) -- install this one yourself, see below' }
|
|
Write-Host ''
|
|
|
|
if ($DryRun) {
|
|
Write-Ok 'Dry run -- nothing was installed.'
|
|
exit 0
|
|
}
|
|
|
|
if ($needed.Count -gt 0 -and -not $Yes) {
|
|
# Without a console there is nobody to answer, and Read-Host would block for
|
|
# as long as the caller is willing to wait -- forever, for a CI job or a
|
|
# wrapping script. Say so instead of hanging.
|
|
if ([Console]::IsInputRedirected) {
|
|
Write-Err 'no console to confirm on -- re-run with -Yes to install without asking, or -DryRun to only look'
|
|
exit 1
|
|
}
|
|
$answer = Read-Host 'Install these now? [Y/n]'
|
|
if ($answer -and $answer -notmatch '^(y|yes)$') {
|
|
Write-Err 'cancelled'
|
|
exit 1
|
|
}
|
|
}
|
|
|
|
if ($needed -contains 'go') { Install-WingetPackage -Id 'GoLang.Go' -Label 'Go' }
|
|
if ($needed -contains 'python') { Install-WingetPackage -Id 'Python.Python.3.13' -Label 'Python 3.13' }
|
|
if ($needed -contains 'openssl') { Install-WingetPackage -Id 'ShiningLight.OpenSSL.Light' -Label 'OpenSSL' }
|
|
|
|
# --- the panel's Python packages ---------------------------------------------
|
|
# A venv rather than the machine-wide interpreter, to match what the Linux side
|
|
# does and what owpengram-server.bat already prefers once one exists.
|
|
if ($needed -contains 'pydeps' -or $needed -contains 'python') {
|
|
$python = Get-WorkingPython
|
|
if (-not $python) {
|
|
Write-Err 'Python still is not callable. Open a new terminal and run this script again.'
|
|
exit 1
|
|
}
|
|
Write-Info 'Installing the panel''s Python packages into .\.venv'
|
|
$venvPython = Join-Path $RepoRoot '.venv\Scripts\python.exe'
|
|
if (-not (Test-Path $venvPython)) {
|
|
$parts = $python.Split(' ')
|
|
& $parts[0] @($parts[1..($parts.Length - 1)] + @('-m', 'venv', (Join-Path $RepoRoot '.venv')))
|
|
if ($LASTEXITCODE -ne 0) { throw 'could not create .venv' }
|
|
}
|
|
& $venvPython -m pip install --quiet --upgrade pip
|
|
& $venvPython -m pip install --quiet -r (Join-Path $RepoRoot 'tui-panel\requirements-panel.txt')
|
|
if ($LASTEXITCODE -ne 0) { throw 'could not install the panel''s Python packages' }
|
|
Write-Ok 'Python packages installed'
|
|
}
|
|
|
|
Write-Host ''
|
|
if ($dockerMissing) {
|
|
Write-Warn 'Docker still has to be installed by hand.'
|
|
Write-Host " The server's PostgreSQL, Redis and MinIO are Linux containers, so Windows"
|
|
Write-Host ' needs Docker Desktop (it brings the WSL2 backend that runs them).'
|
|
Write-Host " $DockerDocs"
|
|
Write-Host ' Install it, reboot if it asks, then run this script again.'
|
|
Write-Host ''
|
|
}
|
|
if ($needed.Count -gt 0) {
|
|
Write-Ok 'Prerequisites are ready.'
|
|
Write-Host ' Open a new terminal so the updated PATH is picked up, then start the server with:'
|
|
Write-Host ' owpengram-server.bat'
|
|
}
|