fix: add updater/process capabilities and improve update error display

This commit is contained in:
lanrtop 2026-04-02 14:50:19 +09:00
parent fcdab7f575
commit 4d3dd66afc
3 changed files with 59 additions and 9 deletions

View File

@ -96,6 +96,27 @@ $bytes = [System.Text.Encoding]::UTF8.GetBytes($content)
} }
``` ```
### 2.2 配置 Capabilities 权限
`src-tauri/capabilities/default.json` 中必须添加以下权限,否则前端调用 updater / process API 会被拦截:
```jsonc
{
"permissions": [
"core:default",
// ... 其他权限 ...
{
"identifier": "http:default",
"allow": [
{ "url": "https://*.aliyuncs.com/**" } // ⚠️ 允许访问 OSS 域名
]
},
"updater:default", // ⚠️ 必须!否则报 updater.check not allowed
"process:default" // ⚠️ 必须!否则 relaunch() 无法调用
]
}
```
### 踩坑记录 ### 踩坑记录
| 问题 | 现象 | 原因 | | 问题 | 现象 | 原因 |
@ -103,6 +124,10 @@ $bytes = [System.Text.Encoding]::UTF8.GetBytes($content)
| **缺少 `createUpdaterArtifacts: true`** | 构建成功但只有 `.exe`,没有 `.exe.sig` | Tauri v2 默认不生成更新包,必须显式开启 | | **缺少 `createUpdaterArtifacts: true`** | 构建成功但只有 `.exe`,没有 `.exe.sig` | Tauri v2 默认不生成更新包,必须显式开启 |
| **pubkey 填成了私钥** | 构建报错 `failed to decode pubkey: Base64 conversion failed` | pubkey 是公钥的 base64不是私钥 | | **pubkey 填成了私钥** | 构建报错 `failed to decode pubkey: Base64 conversion failed` | pubkey 是公钥的 base64不是私钥 |
| **pubkey 与私钥不匹配** | 构建成功但客户端更新时签名验证失败 | 重新生成密钥后要同步更新两处 | | **pubkey 与私钥不匹配** | 构建成功但客户端更新时签名验证失败 | 重新生成密钥后要同步更新两处 |
| **缺少 `updater:default` 权限** | 点击检查更新报 `updater.check not allowed` | Tauri v2 capabilities 需显式声明 updater 权限 |
| **缺少 `process:default` 权限** | 更新后 `relaunch()` 无响应 | 同上,需声明 process 权限 |
| **http 权限未放行 OSS 域名** | 报 `Could not fetch a valid release JSON` | capabilities 的 http allow 列表需包含 OSS 域名 |
| **OSS Bucket 为私有** | 同上错误curl 返回 `AccessDenied` | Bucket ACL 必须设为**公共读** |
--- ---
@ -305,15 +330,16 @@ jobs:
## 七、发版流程(日常操作) ## 七、发版流程(日常操作)
```bash ```bash
# 1. 更新版本号 # 1. 更新版本号(三处必须保持一致!)
# 编辑 src-tauri/tauri.conf.json 中的 "version" 字段 # - src-tauri/tauri.conf.json → "version": "0.2.0"
# 编辑 src-tauri/Cargo.toml 中的 version保持一致 # - src-tauri/Cargo.toml → version = "0.2.0"
# - package.json → "version": "0.2.0"
# 2. 提交代码 # 2. 提交代码
git add -A git add -A
git commit -m "release: v0.2.0" git commit -m "release: v0.2.0"
# 3. 打 tag 并推送 # 3. 打 tag 并推送PowerShell 不支持 &&,分开执行)
git tag v0.2.0 git tag v0.2.0
git push git push
git push --tags git push --tags
@ -323,6 +349,8 @@ git push --tags
# 约 10 分钟完成 # 约 10 分钟完成
``` ```
> **注意**:版本号必须三处同步,否则 `latest.json` 中的 version 与客户端内部版本不一致,可能导致重复提示更新。
--- ---
## 八、客户端更新检测(前端代码) ## 八、客户端更新检测(前端代码)
@ -373,6 +401,10 @@ tauri-plugin-process = "2"
| 10 | Tauri v2 找 `.nsis.zip` 找不到 | v2 格式是 `.exe` + `.exe.sig`,不是 `.nsis.zip` | | 10 | Tauri v2 找 `.nsis.zip` 找不到 | v2 格式是 `.exe` + `.exe.sig`,不是 `.nsis.zip` |
| 11 | Windows 上 `~` 路径问题 | 用 `$HOME` 代替 `~` | | 11 | Windows 上 `~` 路径问题 | 用 `$HOME` 代替 `~` |
| 12 | PowerShell `&&` 语法错误 | PowerShell 5 不支持 `&&`,用 `;` 或分开执行 | | 12 | PowerShell `&&` 语法错误 | PowerShell 5 不支持 `&&`,用 `;` 或分开执行 |
| 13 | `updater.check not allowed` | `capabilities/default.json` 添加 `updater:default` 权限 |
| 14 | `relaunch()` 无效 | `capabilities/default.json` 添加 `process:default` 权限 |
| 15 | `Could not fetch a valid release JSON` | 检查1) OSS Bucket 是否公共读 2) capabilities http allow 是否包含 OSS 域名 |
| 16 | 版本号不一致导致重复更新提示 | 三处版本号必须同步:`tauri.conf.json`、`Cargo.toml`、`package.json` |
--- ---

View File

@ -12,8 +12,11 @@
"identifier": "http:default", "identifier": "http:default",
"allow": [ "allow": [
{ "url": "https://github.com/**" }, { "url": "https://github.com/**" },
{ "url": "https://api.github.com/**" } { "url": "https://api.github.com/**" },
{ "url": "https://*.aliyuncs.com/**" }
] ]
} },
"updater:default",
"process:default"
] ]
} }

View File

@ -538,9 +538,6 @@ function UpdateSection() {
{state.status === "latest" && ( {state.status === "latest" && (
<span className="text-xs text-green-600"></span> <span className="text-xs text-green-600"></span>
)} )}
{state.status === "error" && (
<span className="text-xs text-red-500" title={state.message}></span>
)}
{state.status === "downloading" && ( {state.status === "downloading" && (
<span className="text-xs text-blue-600"> {state.progress}%</span> <span className="text-xs text-blue-600"> {state.progress}%</span>
)} )}
@ -562,6 +559,24 @@ function UpdateSection() {
)} )}
</div> </div>
</div> </div>
{state.status === "error" && (
<div className="mt-3 px-3 py-2.5 bg-red-50 border border-red-200 rounded-lg">
<div className="flex items-start justify-between gap-2">
<p className="text-xs text-red-600 break-all font-mono flex-1 select-text">
{state.message}
</p>
<button
onClick={() => {
navigator.clipboard.writeText(state.message);
}}
className="text-xs text-red-400 hover:text-red-600 shrink-0 transition-colors"
>
</button>
</div>
</div>
)}
</section> </section>
); );
} }