mirror of
https://github.com/hansjone/netx.git
synced 2026-10-10 11:20:48 +08:00
Add update checker, tray controller, and slimmer release venv.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
54c6bc9298
commit
fe9df32024
7 changed files with 367 additions and 13 deletions
148
packaging/check_update.ps1
Normal file
148
packaging/check_update.ps1
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
param(
|
||||
[string]$ProgramRoot = "",
|
||||
[string]$DataRoot = "",
|
||||
[string]$UpdateUrl = "",
|
||||
[string]$Channel = "",
|
||||
[switch]$Apply = $false,
|
||||
[switch]$Quiet = $false
|
||||
)
|
||||
|
||||
# Check for a newer NetX Windows package.
|
||||
# Sources (first that works):
|
||||
# 1) -UpdateUrl / NETX_UPDATE_URL → JSON manifest (see manifest.example.json)
|
||||
# 2) GitHub Releases API for hansjone/netx (default)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
. "$PSScriptRoot\_common.ps1"
|
||||
|
||||
$prog = Get-NetxProgramRoot -Override $ProgramRoot
|
||||
$data = Get-NetxDataRoot -ProgramRoot $prog -Override $DataRoot
|
||||
$envPath = Join-Path $data ".env"
|
||||
$map = @{}
|
||||
if (Test-Path $envPath) { $map = Read-DotEnv -Path $envPath }
|
||||
|
||||
if (-not $UpdateUrl) {
|
||||
if ($map["NETX_UPDATE_URL"]) { $UpdateUrl = $map["NETX_UPDATE_URL"] }
|
||||
elseif ($env:NETX_UPDATE_URL) { $UpdateUrl = $env:NETX_UPDATE_URL }
|
||||
}
|
||||
if (-not $Channel) {
|
||||
if ($map["NETX_UPDATE_CHANNEL"]) { $Channel = $map["NETX_UPDATE_CHANNEL"] }
|
||||
elseif ($env:NETX_UPDATE_CHANNEL) { $Channel = $env:NETX_UPDATE_CHANNEL }
|
||||
else { $Channel = "stable" }
|
||||
}
|
||||
|
||||
$current = Get-NetxVersion -ProgramRoot $prog
|
||||
|
||||
function Compare-SemVer {
|
||||
param([string]$A, [string]$B)
|
||||
$pa = @($A.TrimStart('v','V').Split('.') | ForEach-Object { try { [int]$_ } catch { 0 } })
|
||||
$pb = @($B.TrimStart('v','V').Split('.') | ForEach-Object { try { [int]$_ } catch { 0 } })
|
||||
while ($pa.Count -lt 3) { $pa += 0 }
|
||||
while ($pb.Count -lt 3) { $pb += 0 }
|
||||
for ($i = 0; $i -lt 3; $i++) {
|
||||
if ($pa[$i] -lt $pb[$i]) { return -1 }
|
||||
if ($pa[$i] -gt $pb[$i]) { return 1 }
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
function Get-ManifestFromUrl {
|
||||
param([string]$Url)
|
||||
$resp = Invoke-WebRequest -Uri $Url -UseBasicParsing -TimeoutSec 30
|
||||
return ($resp.Content | ConvertFrom-Json)
|
||||
}
|
||||
|
||||
function Get-FromGitHubReleases {
|
||||
$api = "https://api.github.com/repos/hansjone/netx/releases/latest"
|
||||
$headers = @{ "User-Agent" = "NetX-UpdateCheck"; "Accept" = "application/vnd.github+json" }
|
||||
$rel = Invoke-RestMethod -Uri $api -Headers $headers -TimeoutSec 30
|
||||
$tag = [string]$rel.tag_name
|
||||
$ver = $tag.TrimStart('v', 'V')
|
||||
$zipAsset = $rel.assets | Where-Object { $_.name -match 'win64\.zip$' } | Select-Object -First 1
|
||||
$setupAsset = $rel.assets | Where-Object { $_.name -match 'Setup-.*\.exe$' } | Select-Object -First 1
|
||||
if (-not $zipAsset) { throw "github_release_missing_zip" }
|
||||
return [pscustomobject]@{
|
||||
channel = "stable"
|
||||
latest = $ver
|
||||
min_compatible = $ver
|
||||
notes_url = [string]$rel.html_url
|
||||
windows = [pscustomobject]@{
|
||||
url = [string]$zipAsset.browser_download_url
|
||||
sha256 = ""
|
||||
size = [int64]$zipAsset.size
|
||||
setup_url = $(if ($setupAsset) { [string]$setupAsset.browser_download_url } else { "" })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "==> Current version: $current"
|
||||
$manifest = $null
|
||||
try {
|
||||
if ($UpdateUrl) {
|
||||
Write-Host "==> Fetching manifest: $UpdateUrl"
|
||||
$manifest = Get-ManifestFromUrl -Url $UpdateUrl
|
||||
if ($manifest.channel -and $Channel -and ($manifest.channel -ne $Channel)) {
|
||||
Write-Host "[WARN] manifest channel=$($manifest.channel) requested=$Channel"
|
||||
}
|
||||
} else {
|
||||
Write-Host "==> Fetching latest from GitHub Releases"
|
||||
$manifest = Get-FromGitHubReleases
|
||||
}
|
||||
} catch {
|
||||
if ($Quiet) { exit 2 }
|
||||
throw "update_check_failed: $($_.Exception.Message)"
|
||||
}
|
||||
|
||||
$latest = [string]$manifest.latest
|
||||
$cmp = Compare-SemVer -A $current -B $latest
|
||||
$result = [pscustomobject]@{
|
||||
current = $current
|
||||
latest = $latest
|
||||
update_available = ($cmp -lt 0)
|
||||
download_url = [string]$manifest.windows.url
|
||||
setup_url = $(if ($manifest.windows.setup_url) { [string]$manifest.windows.setup_url } else { "" })
|
||||
notes_url = $(if ($manifest.notes_url) { [string]$manifest.notes_url } else { "" })
|
||||
sha256 = $(if ($manifest.windows.sha256) { [string]$manifest.windows.sha256 } else { "" })
|
||||
}
|
||||
|
||||
if (-not $result.update_available) {
|
||||
Write-Host "==> Up to date (latest=$latest)" -ForegroundColor Green
|
||||
if (-not $Quiet) {
|
||||
$result | ConvertTo-Json -Compress | Write-Output
|
||||
}
|
||||
exit 0
|
||||
}
|
||||
|
||||
Write-Host "==> Update available: $current -> $latest" -ForegroundColor Cyan
|
||||
if ($result.notes_url) { Write-Host " Notes: $($result.notes_url)" }
|
||||
|
||||
if (-not $Apply) {
|
||||
Write-Host " Download (zip): $($result.download_url)"
|
||||
if ($result.setup_url) { Write-Host " Or install: $($result.setup_url)" }
|
||||
Write-Host " To apply: .\packaging\check_update.ps1 -Apply"
|
||||
$result | ConvertTo-Json -Compress | Write-Output
|
||||
exit 10
|
||||
}
|
||||
|
||||
$dlDir = Join-Path $data "backups\downloads"
|
||||
if (-not (Test-Path $dlDir)) {
|
||||
New-Item -ItemType Directory -Path $dlDir -Force | Out-Null
|
||||
}
|
||||
$zipName = "NetX-$latest-win64.zip"
|
||||
$zipPath = Join-Path $dlDir $zipName
|
||||
Write-Host "==> Downloading $zipName ..."
|
||||
Invoke-WebRequest -Uri $result.download_url -OutFile $zipPath -UseBasicParsing
|
||||
if ($result.sha256 -and $result.sha256 -notmatch 'REPLACE') {
|
||||
$hash = (Get-FileHash -Path $zipPath -Algorithm SHA256).Hash.ToLowerInvariant()
|
||||
$expect = $result.sha256.ToLowerInvariant()
|
||||
if ($hash -ne $expect) {
|
||||
throw "sha256_mismatch: got $hash expected $expect"
|
||||
}
|
||||
Write-Host "==> SHA256 OK"
|
||||
}
|
||||
|
||||
Write-Host "==> Applying update via update_netx.ps1"
|
||||
& powershell -ExecutionPolicy Bypass -File (Join-Path $PSScriptRoot "update_netx.ps1") `
|
||||
-PackagePath $zipPath -ProgramRoot $prog -DataRoot $data
|
||||
Write-Host "==> Update applied to $latest" -ForegroundColor Green
|
||||
exit 0
|
||||
Loading…
Add table
Add a link
Reference in a new issue