diff --git a/packaging/check_update.ps1 b/packaging/check_update.ps1 index 7f90413..87536b2 100644 --- a/packaging/check_update.ps1 +++ b/packaging/check_update.ps1 @@ -315,16 +315,24 @@ try { } $zipName = "NetX-$latest-win64.zip" $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; - # 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" + + $needDownload = $true + if ((Test-Path -LiteralPath $zipPath) -and ((Get-Item -LiteralPath $zipPath).Length -gt 1MB)) { + Write-Host "==> Using existing download: $zipPath ($([math]::Round((Get-Item $zipPath).Length/1MB,1)) MB)" + $needDownload = $false + } + if ($needDownload) { + 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()) { $hash = (Get-FileHash -Path $zipPath -Algorithm SHA256).Hash.ToLowerInvariant() $expect = $result.sha256.ToLowerInvariant() @@ -334,7 +342,27 @@ try { 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" + $env:NETX_UPDATE_ELEVATED = "1" & powershell -ExecutionPolicy Bypass -File (Join-Path $PSScriptRoot "update_netx.ps1") ` -PackagePath $zipPath -ProgramRoot $prog -DataRoot $data Write-Host "==> Update applied to $latest" -ForegroundColor Green diff --git a/packaging/installer/netx.iss b/packaging/installer/netx.iss index c9acd89..115c09e 100644 --- a/packaging/installer/netx.iss +++ b/packaging/installer/netx.iss @@ -5,7 +5,7 @@ #define MyAppName "NetX" #ifndef MyAppVersion - #define MyAppVersion "0.4.7" + #define MyAppVersion "0.4.8" #endif #define MyAppPublisher "NetX" #define MyAppURL "https://github.com/hansjone/netx" diff --git a/packaging/manifest.example.json b/packaging/manifest.example.json index 2dccc21..3c8d6aa 100644 --- a/packaging/manifest.example.json +++ b/packaging/manifest.example.json @@ -1,11 +1,11 @@ { "channel": "stable", - "latest": "0.4.7", + "latest": "0.4.8", "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": { - "url": "https://github.com/hansjone/netx/releases/download/v0.4.7/NetX-0.4.7-win64.zip", - "setup_url": "https://github.com/hansjone/netx/releases/download/v0.4.7/NetX-Setup-0.4.7.exe", + "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.8/NetX-Setup-0.4.8.exe", "sha256": "", "size": 0 } diff --git a/packaging/netx_tray.ps1 b/packaging/netx_tray.ps1 index e1d31c6..6b2aa97 100644 --- a/packaging/netx_tray.ps1 +++ b/packaging/netx_tray.ps1 @@ -467,8 +467,36 @@ $miUpdate.add_Click({ [System.Windows.Forms.MessageBoxIcon]::Question ) if ($ans -eq [System.Windows.Forms.DialogResult]::Yes) { - Start-NetxPowerShell -File $checkPs1 -Arguments @("-ProgramRoot", $prog, "-DataRoot", $data, "-Apply") ` - -WorkingDirectory $prog -WindowStyle Normal | Out-Null + # Apply replaces Program Files → needs admin; wait so the console is not abandoned mid-copy. + $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) { [System.Windows.Forms.MessageBox]::Show( diff --git a/packaging/update_netx.ps1 b/packaging/update_netx.ps1 index 0f12cc5..943bcbf 100644 --- a/packaging/update_netx.ps1 +++ b/packaging/update_netx.ps1 @@ -90,7 +90,8 @@ try { -ProgramRoot $prog -DataRoot $data # 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) { $from = Join-Path $src $name $to = Join-Path $prog $name @@ -107,7 +108,7 @@ try { 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")) { $rt = Join-Path $prog "runtime" 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 } + # 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 if (-not $NoStart) { & powershell -ExecutionPolicy Bypass -File (Join-Path $PSScriptRoot "start_netx_app.ps1") ` diff --git a/pyproject.toml b/pyproject.toml index d16a36f..2ea3429 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "netx-ops" -version = "0.4.7" +version = "0.4.8" description = "netx operations tool: alarm-centric workflows with REST API and stdio MCP" readme = "README.md" requires-python = ">=3.11"