feat: add desktop updater and release automation

This commit is contained in:
lbl
2026-08-22 10:00:24 +08:00
parent da72670154
commit 60a4403f0e
42 changed files with 1374 additions and 257 deletions
+15
View File
@@ -16,6 +16,7 @@
- 桌面工作台通过 Tauri IPC 直接调用进程内 `vnt-core`,不监听本地 API 端口
- 可选 Web 访问:启停、端口、本机/局域网监听范围、访问令牌、打开浏览器
- Web API 强制使用 Bearer 令牌鉴权,令牌可在桌面端重新生成
- 关于页提供 GitHub 开源地址与更新检查;桌面端可通过 Tauri Updater 下载并安装更新
桌面数据存放在系统应用数据目录的 `com.vnt.desktop` 下,包括 `vnt_config`、自启动记录、`web_access.toml`、日志及 Windows 下的 `wintun.dll`
@@ -45,11 +46,25 @@ cargo check -p vnt-desktop
## 打包
```powershell
$env:TAURI_SIGNING_PRIVATE_KEY=Get-Content -Raw -LiteralPath "$HOME\.tauri\vnt-desktop.key"
$env:TAURI_SIGNING_PRIVATE_KEY_PASSWORD=""
pnpm build:desktop
```
Windows 使用虚拟网卡模式时,可能需要以管理员身份运行。
### 发布桌面更新
Tauri Updater 会从以下 GitHub Release 资源检查更新:
```text
https://github.com/vnt-dev/vnt/releases/latest/download/latest.json
```
更新包必须使用与 `tauri.conf.json` 内公钥匹配的私钥签名。当前密钥默认保存在 `~/.tauri/vnt-desktop.key`,请妥善备份并在 CI 中将私钥内容配置为 `TAURI_SIGNING_PRIVATE_KEY`;私钥不得提交到仓库。发布时需将 Tauri 生成的安装包、`.sig` 文件以及对应的 `latest.json` 一并上传到 GitHub Release。
仓库的 Release 流水线会在推送版本标签后自动构建 Windows 桌面安装包及 updater 元数据。请在 GitHub Actions Secrets 中配置 `TAURI_SIGNING_PRIVATE_KEY`;如果私钥设置了密码,同时配置 `TAURI_SIGNING_PRIVATE_KEY_PASSWORD`。流水线还会将桌面安装包和各平台 VNT 工具包的直接下载链接写入 Release Notes。
## 应用图标
图标母版保存在 `vnt-desktop/assets/vnt-icon-master.png`。需要重新生成各平台图标时,在仓库根目录执行:
+2
View File
@@ -10,6 +10,8 @@
},
"dependencies": {
"@tauri-apps/api": "^2.8.0",
"@tauri-apps/plugin-process": "^2.3.1",
"@tauri-apps/plugin-updater": "^2.10.1",
"pinia": "catalog:",
"vue": "catalog:",
"vue-router": "catalog:"
+2
View File
@@ -24,3 +24,5 @@ serde.workspace = true
serde_json.workspace = true
toml.workspace = true
anyhow.workspace = true
tauri-plugin-updater = "2"
tauri-plugin-process = "2"
@@ -11,6 +11,8 @@
"core:window:allow-unmaximize",
"core:window:allow-is-maximized",
"core:window:allow-start-dragging",
"opener:allow-open-url"
"opener:allow-open-url",
"process:allow-restart",
"updater:default"
]
}
+3 -1
View File
@@ -245,6 +245,8 @@ pub fn run() {
open_web_url
])
.plugin(tauri_plugin_opener::init())
.plugin(tauri_plugin_process::init())
.plugin(tauri_plugin_updater::Builder::new().build())
.plugin(tauri_plugin_single_instance::init(|app, _args, _cwd| {
show_main_window(app);
}))
@@ -260,7 +262,7 @@ pub fn run() {
let config_path = data_dir.join(WEB_ACCESS_CONFIG);
let config = load_web_config(&config_path);
save_web_config(&config_path, &config)?;
let service = tauri::async_runtime::block_on(VntService::new(None))?;
let service = tauri::async_runtime::block_on(VntService::new_desktop(None))?;
let mut web = WebRuntime {
config,
cancellation: None,
+13 -1
View File
@@ -25,11 +25,12 @@
}
],
"security": {
"csp": "default-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' asset: data:; connect-src 'self' ipc: http://ipc.localhost http://127.0.0.1:*"
"csp": "default-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' asset: data:; connect-src 'self' ipc: http://ipc.localhost http://127.0.0.1:* https://api.github.com"
}
},
"bundle": {
"active": true,
"createUpdaterArtifacts": true,
"targets": "all",
"icon": [
"icons/32x32.png",
@@ -45,5 +46,16 @@
"wix": { "language": "zh-CN" },
"nsis": { "displayLanguageSelector": false }
}
},
"plugins": {
"updater": {
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEE3MTQzQjc3NTJGQjBGRTEKUldUaEQvdFNkenNVcHdwd0pRNEhDV1lTdkMzTDZLa1V3WGllMDRoMmxBNDdobi8wclN1dmo3cFoK",
"endpoints": [
"https://github.com/vnt-dev/vnt/releases/latest/download/latest.json"
],
"windows": {
"installMode": "passive"
}
}
}
}
+30
View File
@@ -1,4 +1,8 @@
import { invoke } from "@tauri-apps/api/core";
import { relaunch } from "@tauri-apps/plugin-process";
import { check } from "@tauri-apps/plugin-updater";
let pendingUpdate = null;
globalThis.__VNT_DESKTOP__ = true;
globalThis.__VNT_IPC_REQUEST__ = ({ method, path, body }) =>
@@ -9,6 +13,32 @@ globalThis.__VNT_WEB_ACCESS__ = {
generateToken: () => invoke("generate_web_token"),
openUrl: (url) => invoke("open_web_url", { url }),
};
globalThis.__VNT_UPDATER__ = {
check: async () => {
pendingUpdate = await check();
if (!pendingUpdate) return null;
return {
currentVersion: pendingUpdate.currentVersion,
version: pendingUpdate.version,
date: pendingUpdate.date || "",
body: pendingUpdate.body || "",
};
},
downloadAndInstall: async (onProgress) => {
if (!pendingUpdate) throw new Error("请先检查更新");
let downloaded = 0;
let contentLength = 0;
await pendingUpdate.downloadAndInstall((event) => {
if (event.event === "Started") {
contentLength = event.data.contentLength || 0;
} else if (event.event === "Progress") {
downloaded += event.data.chunkLength;
}
onProgress?.({ event: event.event, downloaded, contentLength });
});
await relaunch();
},
};
// Tauri 与 Web 端共用同一个 Vue 应用,这里只负责平台初始化。
await import("@shared/main.js");