mirror of
https://github.com/hansjone/netx.git
synced 2026-10-09 00:50:46 +08:00
Release 0.4.8: fix in-place update (elevate + ship python/runtime).
Apply updates as Administrator for Program Files, copy portable python with .venv, and wait for tray apply to finish. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
4e582dc4a5
commit
66f9fa9782
6 changed files with 83 additions and 19 deletions
|
|
@ -315,16 +315,24 @@ try {
|
||||||
}
|
}
|
||||||
$zipName = "NetX-$latest-win64.zip"
|
$zipName = "NetX-$latest-win64.zip"
|
||||||
$zipPath = Join-Path $dlDir $zipName
|
$zipPath = Join-Path $dlDir $zipName
|
||||||
Write-Host "==> Downloading $zipName from $($result.source) ..."
|
|
||||||
# Only attach token for non-GitHub hosts (Forgejo/private). Public GitHub assets need no auth;
|
$needDownload = $true
|
||||||
# a Forgejo token would break anonymous GitHub downloads.
|
if ((Test-Path -LiteralPath $zipPath) -and ((Get-Item -LiteralPath $zipPath).Length -gt 1MB)) {
|
||||||
$dlHeaders = @{ "User-Agent" = "NetX-UpdateCheck" }
|
Write-Host "==> Using existing download: $zipPath ($([math]::Round((Get-Item $zipPath).Length/1MB,1)) MB)"
|
||||||
$dlUri = [uri]$result.download_url
|
$needDownload = $false
|
||||||
$isGithub = ($dlUri.Host -match '(^|\.)github\.com$' -or $dlUri.Host -match '(^|\.)githubusercontent\.com$')
|
}
|
||||||
if ($UpdateToken -and -not $isGithub) {
|
if ($needDownload) {
|
||||||
$dlHeaders["Authorization"] = "token $UpdateToken"
|
Write-Host "==> Downloading $zipName from $($result.source) ..."
|
||||||
|
# Only attach token for non-GitHub hosts (Forgejo/private). Public GitHub assets need no auth;
|
||||||
|
# a Forgejo token would break anonymous GitHub downloads.
|
||||||
|
$dlHeaders = @{ "User-Agent" = "NetX-UpdateCheck" }
|
||||||
|
$dlUri = [uri]$result.download_url
|
||||||
|
$isGithub = ($dlUri.Host -match '(^|\.)github\.com$' -or $dlUri.Host -match '(^|\.)githubusercontent\.com$')
|
||||||
|
if ($UpdateToken -and -not $isGithub) {
|
||||||
|
$dlHeaders["Authorization"] = "token $UpdateToken"
|
||||||
|
}
|
||||||
|
Invoke-WebRequest -Uri $result.download_url -OutFile $zipPath -Headers $dlHeaders -UseBasicParsing
|
||||||
}
|
}
|
||||||
Invoke-WebRequest -Uri $result.download_url -OutFile $zipPath -Headers $dlHeaders -UseBasicParsing
|
|
||||||
if ($result.sha256 -and $result.sha256 -notmatch 'REPLACE' -and $result.sha256.Trim()) {
|
if ($result.sha256 -and $result.sha256 -notmatch 'REPLACE' -and $result.sha256.Trim()) {
|
||||||
$hash = (Get-FileHash -Path $zipPath -Algorithm SHA256).Hash.ToLowerInvariant()
|
$hash = (Get-FileHash -Path $zipPath -Algorithm SHA256).Hash.ToLowerInvariant()
|
||||||
$expect = $result.sha256.ToLowerInvariant()
|
$expect = $result.sha256.ToLowerInvariant()
|
||||||
|
|
@ -334,7 +342,27 @@ try {
|
||||||
Write-Host "==> SHA256 OK"
|
Write-Host "==> SHA256 OK"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Program Files installs need admin to replace files; elevate once (avoid loop via NETX_UPDATE_ELEVATED).
|
||||||
|
$progWritable = $false
|
||||||
|
try {
|
||||||
|
$probe = Join-Path $prog (".netx_w_" + [guid]::NewGuid().ToString("n"))
|
||||||
|
[IO.File]::WriteAllText($probe, "x")
|
||||||
|
Remove-Item -LiteralPath $probe -Force -ErrorAction SilentlyContinue
|
||||||
|
$progWritable = $true
|
||||||
|
} catch {
|
||||||
|
$progWritable = $false
|
||||||
|
}
|
||||||
|
if (-not $progWritable -and -not $env:NETX_UPDATE_ELEVATED) {
|
||||||
|
Write-Host "==> Program directory is not writable; relaunching update as Administrator (UAC)..." -ForegroundColor Yellow
|
||||||
|
$arg = "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`" -ProgramRoot `"$prog`" -DataRoot `"$data`" -Apply"
|
||||||
|
$ep = Start-Process -FilePath "powershell.exe" -ArgumentList $arg -WorkingDirectory $prog `
|
||||||
|
-Verb RunAs -Wait -PassThru
|
||||||
|
if ($null -eq $ep.ExitCode) { exit 1 }
|
||||||
|
exit $ep.ExitCode
|
||||||
|
}
|
||||||
|
|
||||||
Write-Host "==> Applying update via update_netx.ps1"
|
Write-Host "==> Applying update via update_netx.ps1"
|
||||||
|
$env:NETX_UPDATE_ELEVATED = "1"
|
||||||
& powershell -ExecutionPolicy Bypass -File (Join-Path $PSScriptRoot "update_netx.ps1") `
|
& powershell -ExecutionPolicy Bypass -File (Join-Path $PSScriptRoot "update_netx.ps1") `
|
||||||
-PackagePath $zipPath -ProgramRoot $prog -DataRoot $data
|
-PackagePath $zipPath -ProgramRoot $prog -DataRoot $data
|
||||||
Write-Host "==> Update applied to $latest" -ForegroundColor Green
|
Write-Host "==> Update applied to $latest" -ForegroundColor Green
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
#define MyAppName "NetX"
|
#define MyAppName "NetX"
|
||||||
#ifndef MyAppVersion
|
#ifndef MyAppVersion
|
||||||
#define MyAppVersion "0.4.7"
|
#define MyAppVersion "0.4.8"
|
||||||
#endif
|
#endif
|
||||||
#define MyAppPublisher "NetX"
|
#define MyAppPublisher "NetX"
|
||||||
#define MyAppURL "https://github.com/hansjone/netx"
|
#define MyAppURL "https://github.com/hansjone/netx"
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
{
|
{
|
||||||
"channel": "stable",
|
"channel": "stable",
|
||||||
"latest": "0.4.7",
|
"latest": "0.4.8",
|
||||||
"min_compatible": "0.3.0",
|
"min_compatible": "0.3.0",
|
||||||
"notes_url": "https://github.com/hansjone/netx/releases/tag/v0.4.7",
|
"notes_url": "https://github.com/hansjone/netx/releases/tag/v0.4.8",
|
||||||
"windows": {
|
"windows": {
|
||||||
"url": "https://github.com/hansjone/netx/releases/download/v0.4.7/NetX-0.4.7-win64.zip",
|
"url": "https://github.com/hansjone/netx/releases/download/v0.4.8/NetX-0.4.8-win64.zip",
|
||||||
"setup_url": "https://github.com/hansjone/netx/releases/download/v0.4.7/NetX-Setup-0.4.7.exe",
|
"setup_url": "https://github.com/hansjone/netx/releases/download/v0.4.8/NetX-Setup-0.4.8.exe",
|
||||||
"sha256": "",
|
"sha256": "",
|
||||||
"size": 0
|
"size": 0
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -467,8 +467,36 @@ $miUpdate.add_Click({
|
||||||
[System.Windows.Forms.MessageBoxIcon]::Question
|
[System.Windows.Forms.MessageBoxIcon]::Question
|
||||||
)
|
)
|
||||||
if ($ans -eq [System.Windows.Forms.DialogResult]::Yes) {
|
if ($ans -eq [System.Windows.Forms.DialogResult]::Yes) {
|
||||||
Start-NetxPowerShell -File $checkPs1 -Arguments @("-ProgramRoot", $prog, "-DataRoot", $data, "-Apply") `
|
# Apply replaces Program Files → needs admin; wait so the console is not abandoned mid-copy.
|
||||||
-WorkingDirectory $prog -WindowStyle Normal | Out-Null
|
$arg = "-NoProfile -ExecutionPolicy Bypass -File `"$checkPs1`" -ProgramRoot `"$prog`" -DataRoot `"$data`" -Apply"
|
||||||
|
$notify.ShowBalloonTip(
|
||||||
|
5000, "NetX",
|
||||||
|
(T "Downloading / applying update… keep the console open." "正在下载/应用更新…请勿关闭控制台窗口。"),
|
||||||
|
[System.Windows.Forms.ToolTipIcon]::Info
|
||||||
|
)
|
||||||
|
$ap = Start-Process -FilePath "powershell.exe" -ArgumentList $arg `
|
||||||
|
-WorkingDirectory $prog -WindowStyle Normal -Verb RunAs -Wait -PassThru
|
||||||
|
$newVer = Get-NetxVersion -ProgramRoot $prog
|
||||||
|
if ($null -ne $ap.ExitCode -and $ap.ExitCode -eq 0) {
|
||||||
|
$ver = $newVer
|
||||||
|
$miHeader.Text = "NetX $ver"
|
||||||
|
[System.Windows.Forms.MessageBox]::Show(
|
||||||
|
(T "Updated to $ver. Restart the tray if the menu still shows the old version." "已更新到 $ver。若菜单仍显示旧版本,请退出托盘后重新打开。"),
|
||||||
|
(T "NetX update" "NetX 更新"),
|
||||||
|
[System.Windows.Forms.MessageBoxButtons]::OK,
|
||||||
|
[System.Windows.Forms.MessageBoxIcon]::Information
|
||||||
|
)
|
||||||
|
} elseif (Test-NetxSetupCancelled -ExitCode $ap.ExitCode) {
|
||||||
|
$notify.ShowBalloonTip(4000, "NetX", (T "Update cancelled." "已取消更新。"), [System.Windows.Forms.ToolTipIcon]::Info)
|
||||||
|
} else {
|
||||||
|
[System.Windows.Forms.MessageBox]::Show(
|
||||||
|
(T "Update failed (exit $($ap.ExitCode)). Re-run Check for updates, or install NetX-Setup manually." "更新失败(退出码 $($ap.ExitCode))。请重试「检查更新」,或手动运行 Setup 安装包。"),
|
||||||
|
(T "NetX update" "NetX 更新"),
|
||||||
|
[System.Windows.Forms.MessageBoxButtons]::OK,
|
||||||
|
[System.Windows.Forms.MessageBoxIcon]::Warning
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Update-NetxTrayTip
|
||||||
}
|
}
|
||||||
} elseif ($p.ExitCode -eq 0) {
|
} elseif ($p.ExitCode -eq 0) {
|
||||||
[System.Windows.Forms.MessageBox]::Show(
|
[System.Windows.Forms.MessageBox]::Show(
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,8 @@ try {
|
||||||
-ProgramRoot $prog -DataRoot $data
|
-ProgramRoot $prog -DataRoot $data
|
||||||
|
|
||||||
# Replace program layers only — never wipe data root.
|
# Replace program layers only — never wipe data root.
|
||||||
$replaceDirs = @("netx_api", "alembic", "web", "packaging", "scripts", "postgres", "packages")
|
# Include python/ (portable runtime) — required with shipped .venv since 0.4.6.
|
||||||
|
$replaceDirs = @("netx_api", "alembic", "web", "packaging", "scripts", "postgres", "packages", "python")
|
||||||
foreach ($name in $replaceDirs) {
|
foreach ($name in $replaceDirs) {
|
||||||
$from = Join-Path $src $name
|
$from = Join-Path $src $name
|
||||||
$to = Join-Path $prog $name
|
$to = Join-Path $prog $name
|
||||||
|
|
@ -107,7 +108,7 @@ try {
|
||||||
Copy-Item -Path $from -Destination (Join-Path $prog $f) -Force
|
Copy-Item -Path $from -Destination (Join-Path $prog $f) -Force
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
# Optional runtime / .venv shipped in package
|
# Legacy top-level runtime/ (older packages) + shipped .venv
|
||||||
if (Test-Path (Join-Path $src "runtime")) {
|
if (Test-Path (Join-Path $src "runtime")) {
|
||||||
$rt = Join-Path $prog "runtime"
|
$rt = Join-Path $prog "runtime"
|
||||||
if (Test-Path $rt) { Remove-Item -Recurse -Force $rt }
|
if (Test-Path $rt) { Remove-Item -Recurse -Force $rt }
|
||||||
|
|
@ -120,6 +121,13 @@ try {
|
||||||
Copy-Item -Path (Join-Path $src ".venv") -Destination $venvTo -Recurse -Force
|
Copy-Item -Path (Join-Path $src ".venv") -Destination $venvTo -Recurse -Force
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Builder-path pyvenv.cfg → local python/runtime (same as first install).
|
||||||
|
if (Get-Command Repair-NetxShippedVenv -ErrorAction SilentlyContinue) {
|
||||||
|
if (Repair-NetxShippedVenv -ProgramRoot $prog) {
|
||||||
|
Write-Host "==> Relinked .venv to bundled python/runtime" -ForegroundColor Green
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Write-Host "==> Update files applied" -ForegroundColor Green
|
Write-Host "==> Update files applied" -ForegroundColor Green
|
||||||
if (-not $NoStart) {
|
if (-not $NoStart) {
|
||||||
& powershell -ExecutionPolicy Bypass -File (Join-Path $PSScriptRoot "start_netx_app.ps1") `
|
& powershell -ExecutionPolicy Bypass -File (Join-Path $PSScriptRoot "start_netx_app.ps1") `
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "netx-ops"
|
name = "netx-ops"
|
||||||
version = "0.4.7"
|
version = "0.4.8"
|
||||||
description = "netx operations tool: alarm-centric workflows with REST API and stdio MCP"
|
description = "netx operations tool: alarm-centric workflows with REST API and stdio MCP"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.11"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue