Skip to content

Commit e62bcbb

Browse files
committed
chore: improve updater build flow and docs
1 parent 02e07c9 commit e62bcbb

7 files changed

Lines changed: 222 additions & 54 deletions

File tree

.github/workflows/build-desktop-tauri.yml

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ env:
4747
# build outputs will include signed updater bundles and *.sig files.
4848
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY || '' }}
4949
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD || '' }}
50+
# Default updater source points to upstream release latest.json; can be overridden per repo/fork.
51+
ASTRBOT_UPDATER_ENDPOINT: ${{ vars.ASTRBOT_UPDATER_ENDPOINT || 'https://github.com/AstrBotDevs/AstrBot-desktop/releases/latest/download/latest.json' }}
52+
ASTRBOT_UPDATER_PUBKEY: ${{ vars.ASTRBOT_UPDATER_PUBKEY || '' }}
5053

5154
jobs:
5255
resolve_build_context:
@@ -200,6 +203,20 @@ jobs:
200203
with:
201204
astrbot_version: ${{ steps.desktop_version.outputs.normalized }}
202205

206+
- name: Prepare Tauri build config (Linux)
207+
env:
208+
ASTRBOT_UPDATER_ENDPOINT: ${{ env.ASTRBOT_UPDATER_ENDPOINT }}
209+
ASTRBOT_UPDATER_PUBKEY: ${{ env.ASTRBOT_UPDATER_PUBKEY }}
210+
shell: bash
211+
run: |
212+
set -euo pipefail
213+
config_path="src-tauri/tauri.build.config.json"
214+
python3 scripts/ci/render-tauri-build-config.py \
215+
--output "${config_path}" \
216+
--updater-endpoint "${ASTRBOT_UPDATER_ENDPOINT}" \
217+
--updater-pubkey "${ASTRBOT_UPDATER_PUBKEY}"
218+
echo "ASTRBOT_TAURI_CONFIG_PATH=${config_path}" >> "${GITHUB_ENV}"
219+
203220
- name: Build desktop installers (Linux)
204221
env:
205222
ASTRBOT_SOURCE_GIT_URL: ${{ needs.resolve_build_context.outputs.source_git_url }}
@@ -208,7 +225,7 @@ jobs:
208225
ASTRBOT_LINUX_BUNDLES: ${{ env.ASTRBOT_LINUX_BUNDLES }}
209226
GITHUB_TOKEN: ${{ github.token }}
210227
GH_TOKEN: ${{ github.token }}
211-
run: cargo tauri build --bundles "${ASTRBOT_LINUX_BUNDLES}"
228+
run: cargo tauri build --config "${ASTRBOT_TAURI_CONFIG_PATH}" --bundles "${ASTRBOT_LINUX_BUNDLES}"
212229

213230
- name: Collect Linux updater artifacts (if any)
214231
env:
@@ -298,6 +315,20 @@ jobs:
298315
--override-source "env:ASTRBOT_MACOS_APP_BUNDLE_NAME" \
299316
--github-output "${GITHUB_OUTPUT}"
300317
318+
- name: Prepare Tauri build config (macOS)
319+
env:
320+
ASTRBOT_UPDATER_ENDPOINT: ${{ env.ASTRBOT_UPDATER_ENDPOINT }}
321+
ASTRBOT_UPDATER_PUBKEY: ${{ env.ASTRBOT_UPDATER_PUBKEY }}
322+
shell: bash
323+
run: |
324+
set -euo pipefail
325+
config_path="src-tauri/tauri.build.config.json"
326+
python3 scripts/ci/render-tauri-build-config.py \
327+
--output "${config_path}" \
328+
--updater-endpoint "${ASTRBOT_UPDATER_ENDPOINT}" \
329+
--updater-pubkey "${ASTRBOT_UPDATER_PUBKEY}"
330+
echo "ASTRBOT_TAURI_CONFIG_PATH=${config_path}" >> "${GITHUB_ENV}"
331+
301332
- name: Build desktop app bundle (macOS)
302333
env:
303334
ASTRBOT_SOURCE_GIT_URL: ${{ needs.resolve_build_context.outputs.source_git_url }}
@@ -341,7 +372,7 @@ jobs:
341372
342373
for attempt in $(seq 1 "${max_attempts}"); do
343374
build_log="$(mktemp -t tauri-macos-build.XXXXXX.log)"
344-
if cargo tauri build --verbose --target ${{ matrix.target }} --bundles app 2>&1 | tee "${build_log}"; then
375+
if cargo tauri build --verbose --config "${ASTRBOT_TAURI_CONFIG_PATH}" --target ${{ matrix.target }} --bundles app 2>&1 | tee "${build_log}"; then
345376
rm -f "${build_log}" || true
346377
break
347378
fi
@@ -460,6 +491,20 @@ jobs:
460491
with:
461492
astrbot_version: ${{ steps.desktop_version.outputs.normalized }}
462493

494+
- name: Prepare Tauri build config (Windows)
495+
env:
496+
ASTRBOT_UPDATER_ENDPOINT: ${{ env.ASTRBOT_UPDATER_ENDPOINT }}
497+
ASTRBOT_UPDATER_PUBKEY: ${{ env.ASTRBOT_UPDATER_PUBKEY }}
498+
shell: bash
499+
run: |
500+
set -euo pipefail
501+
config_path="src-tauri/tauri.build.config.json"
502+
python3 scripts/ci/render-tauri-build-config.py \
503+
--output "${config_path}" \
504+
--updater-endpoint "${ASTRBOT_UPDATER_ENDPOINT}" \
505+
--updater-pubkey "${ASTRBOT_UPDATER_PUBKEY}"
506+
echo "ASTRBOT_TAURI_CONFIG_PATH=${config_path}" >> "${GITHUB_ENV}"
507+
463508
- name: Build desktop installers (Windows)
464509
env:
465510
ASTRBOT_SOURCE_GIT_URL: ${{ needs.resolve_build_context.outputs.source_git_url }}

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ resources/webui/
1414
# rust/tauri build outputs
1515
src-tauri/target/
1616
src-tauri/gen/
17+
src-tauri/tauri.build.config.json
1718

1819
# logs
1920
*.log

Makefile

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,21 @@ RUST_MANIFEST ?= src-tauri/Cargo.toml
1515
NODE_MODULES_DIR ?= node_modules
1616
PNPM_STORE_DIR ?= .pnpm-store
1717
TAURI_TARGET_DIR ?= src-tauri/target
18+
TAURI_BUILD_CONFIG ?= src-tauri/tauri.build.config.json
19+
TAURI_SIGNING_PRIVATE_KEY_OUT ?= $(HOME)/.tauri/astrbot.key
20+
ASTRBOT_UPDATER_ENDPOINT ?= https://github.com/AstrBotDevs/AstrBot-desktop/releases/latest/download/latest.json
21+
ASTRBOT_UPDATER_PUBKEY ?=
22+
ASTRBOT_UPDATER_PUBKEY_FILE ?=
23+
ASTRBOT_ENABLE_UPDATER_ARTIFACTS ?= 1
24+
ASTRBOT_TAURI_BUNDLES ?=
1825
# Single source of env keys managed by `make clean-env`.
1926
# If build/resource scripts start consuming a new persistent env var, add it here.
20-
ASTRBOT_ENV_KEYS := ASTRBOT_SOURCE_DIR ASTRBOT_SOURCE_GIT_URL ASTRBOT_SOURCE_GIT_REF ASTRBOT_DESKTOP_VERSION ASTRBOT_BUILD_SOURCE_DIR
27+
ASTRBOT_ENV_KEYS := ASTRBOT_SOURCE_DIR ASTRBOT_SOURCE_GIT_URL ASTRBOT_SOURCE_GIT_REF ASTRBOT_DESKTOP_VERSION ASTRBOT_BUILD_SOURCE_DIR ASTRBOT_UPDATER_ENDPOINT ASTRBOT_UPDATER_PUBKEY ASTRBOT_UPDATER_PUBKEY_FILE ASTRBOT_ENABLE_UPDATER_ARTIFACTS ASTRBOT_TAURI_BUNDLES TAURI_SIGNING_PRIVATE_KEY TAURI_SIGNING_PRIVATE_KEY_PATH TAURI_SIGNING_PRIVATE_KEY_PASSWORD
2128
# Hash of ASTRBOT_ENV_KEYS for stale reset-script detection in `make clean-env`.
2229
ASTRBOT_ENV_KEYS_HASH := $(shell (printf '%s\n' "$(ASTRBOT_ENV_KEYS)" | shasum -a 256 2>/dev/null || printf '%s\n' "$(ASTRBOT_ENV_KEYS)" | sha256sum 2>/dev/null || printf '%s\n' "$(ASTRBOT_ENV_KEYS)" | cksum 2>/dev/null) | awk '{print $$1}' | head -n 1)
2330

2431
.PHONY: help deps sync-version update prepare-webui prepare-backend prepare-resources dev build \
32+
signing-key render-tauri-config build-signed \
2533
prepare rebuild lint test doctor prune size clean clean-rust clean-resources \
2634
clean-vendor-local clean-vendor clean-node clean-env clean-all
2735

@@ -38,6 +46,12 @@ help:
3846
@echo " make dev Run Tauri dev"
3947
@echo " make build Run Tauri build"
4048
@echo " (set ASTRBOT_SOURCE_DIR=... or ASTRBOT_BUILD_SOURCE_DIR=...)"
49+
@echo " make signing-key Generate updater signing key pair"
50+
@echo " (TAURI_SIGNING_PRIVATE_KEY_OUT=$(TAURI_SIGNING_PRIVATE_KEY_OUT))"
51+
@echo " make render-tauri-config Generate temporary tauri build override config"
52+
@echo " (ASTRBOT_UPDATER_ENDPOINT / ASTRBOT_UPDATER_PUBKEY / ASTRBOT_UPDATER_PUBKEY_FILE)"
53+
@echo " make build-signed Build with --config $(TAURI_BUILD_CONFIG)"
54+
@echo " (optional ASTRBOT_TAURI_BUNDLES=deb,rpm,appimage)"
4155
@echo " make rebuild Clean and build"
4256
@echo " make lint Run formatting and clippy checks"
4357
@echo " make test Run Rust + script behavior tests"
@@ -104,6 +118,51 @@ build:
104118
fi; \
105119
pnpm run build
106120

121+
signing-key:
122+
cargo tauri signer generate -w "$(TAURI_SIGNING_PRIVATE_KEY_OUT)"
123+
124+
render-tauri-config:
125+
@set -e; \
126+
updater_pubkey="$(ASTRBOT_UPDATER_PUBKEY)"; \
127+
if [ -z "$$updater_pubkey" ] && [ -n "$(ASTRBOT_UPDATER_PUBKEY_FILE)" ]; then \
128+
updater_pubkey="$$(cat "$(ASTRBOT_UPDATER_PUBKEY_FILE)")"; \
129+
fi; \
130+
disable_flag=""; \
131+
case "$(ASTRBOT_ENABLE_UPDATER_ARTIFACTS)" in \
132+
0|false|False|FALSE|no|No|NO|off|Off|OFF) disable_flag="--disable-updater-artifacts" ;; \
133+
esac; \
134+
python3 scripts/ci/render-tauri-build-config.py \
135+
--output "$(TAURI_BUILD_CONFIG)" \
136+
--updater-endpoint "$(ASTRBOT_UPDATER_ENDPOINT)" \
137+
--updater-pubkey "$$updater_pubkey" \
138+
$$disable_flag
139+
140+
build-signed: render-tauri-config
141+
@set -e; \
142+
build_version="$(ASTRBOT_DESKTOP_VERSION)"; \
143+
build_source_dir="$(ASTRBOT_BUILD_SOURCE_DIR)"; \
144+
if [ -z "$$build_source_dir" ]; then \
145+
build_source_dir="$(ASTRBOT_SOURCE_DIR)"; \
146+
fi; \
147+
if [ -z "$$build_version" ]; then \
148+
build_version="$$(node -e "console.log(require('./package.json').version)")"; \
149+
fi; \
150+
if [ -n "$$build_source_dir" ]; then \
151+
echo "Using build source dir: $$build_source_dir"; \
152+
fi; \
153+
echo "Build resource source dir: $${build_source_dir:-<auto vendor from git ref>}"; \
154+
export ASTRBOT_SOURCE_GIT_URL="$(ASTRBOT_SOURCE_GIT_URL)"; \
155+
export ASTRBOT_SOURCE_GIT_REF="$(ASTRBOT_SOURCE_GIT_REF)"; \
156+
export ASTRBOT_DESKTOP_VERSION="$$build_version"; \
157+
if [ -n "$$build_source_dir" ]; then \
158+
export ASTRBOT_SOURCE_DIR="$$build_source_dir"; \
159+
fi; \
160+
build_cmd="cargo tauri build --config $(TAURI_BUILD_CONFIG)"; \
161+
if [ -n "$(ASTRBOT_TAURI_BUNDLES)" ]; then \
162+
build_cmd="$$build_cmd --bundles \"$(ASTRBOT_TAURI_BUNDLES)\""; \
163+
fi; \
164+
eval "$$build_cmd"
165+
107166
rebuild: clean build
108167

109168
lint:

README.md

Lines changed: 31 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -110,72 +110,54 @@ source .astrbot-reset-env.sh
110110

111111
## 应用内升级(Updater)与签名构建
112112

113-
当前 CI 已支持上传 updater 产物并生成 `latest.json`,但要真正启用应用内升级,还需要完成以下配置
113+
推荐使用 `make`,避免手动拼接长命令
114114

115-
### 1. 配置 GitHub Actions(远程构建
115+
### 本地从头构建(推荐
116116

117-
在仓库 `Settings -> Secrets and variables -> Actions` 配置:
117+
```bash
118+
make deps
119+
make prepare
120+
make signing-key
118121

119-
- `TAURI_SIGNING_PRIVATE_KEY`:Tauri updater 私钥内容(多行文本)
120-
- `TAURI_SIGNING_PRIVATE_KEY_PASSWORD`:私钥密码
121-
- `ASTRBOT_LINUX_BUNDLES`(可选):Linux 打包目标,建议 `deb,rpm,appimage`(需要 Linux updater 时)
122-
123-
### 2. 配置 Tauri updater(仓库文件)
124-
125-
`src-tauri/tauri.conf.json` 中启用 updater 配置(示例):
126-
127-
```json
128-
{
129-
"bundle": {
130-
"createUpdaterArtifacts": true
131-
},
132-
"plugins": {
133-
"updater": {
134-
"active": true,
135-
"endpoints": [
136-
"https://github.com/AstrBotDevs/AstrBot-desktop/releases/latest/download/latest.json"
137-
],
138-
"pubkey": "<tauri signer 生成的公钥>"
139-
}
140-
}
141-
}
122+
export TAURI_SIGNING_PRIVATE_KEY_PATH="$HOME/.tauri/astrbot.key"
123+
export TAURI_SIGNING_PRIVATE_KEY_PASSWORD='你的密码'
124+
125+
make build-signed \
126+
ASTRBOT_UPDATER_PUBKEY_FILE="$HOME/.tauri/astrbot.key.pub" \
127+
ASTRBOT_TAURI_BUNDLES="deb,rpm,appimage"
142128
```
143129

144130
说明:
145131

146-
- `pubkey` 必须与签名私钥配对,否则客户端会校验失败。
147-
- `latest.json` 会在 release 阶段由 CI 自动生成并上传。
132+
- `make build-signed` 会自动生成临时覆盖配置 `src-tauri/tauri.build.config.json`,并用 `cargo tauri build --config ...` 构建。
133+
- 默认 updater endpoint 指向上游:
134+
`https://github.com/AstrBotDevs/AstrBot-desktop/releases/latest/download/latest.json`
135+
- 临时覆盖配置已在 `.gitignore` 中,不会误提交。
148136

149-
### 3. 本地生成密钥与签名构建
150-
151-
生成私钥/公钥:
137+
### 本地切换到 fork 更新源(测试用)
152138

153139
```bash
154-
cargo tauri signer generate -w ~/.tauri/astrbot.key
140+
make build-signed \
141+
ASTRBOT_UPDATER_PUBKEY_FILE="$HOME/.tauri/astrbot.key.pub" \
142+
ASTRBOT_UPDATER_ENDPOINT="https://github.com/<your-name>/AstrBot-desktop/releases/latest/download/latest.json" \
143+
ASTRBOT_TAURI_BUNDLES="deb,rpm,appimage"
155144
```
156145

157-
设置签名环境变量(二选一):
146+
注意:`ASTRBOT_UPDATER_ENDPOINT` 对应的发布资产,必须使用与 `ASTRBOT_UPDATER_PUBKEY` 匹配的私钥签名。
158147

159-
```bash
160-
# 方式 A:直接传私钥内容
161-
export TAURI_SIGNING_PRIVATE_KEY="$(cat ~/.tauri/astrbot.key)"
162-
export TAURI_SIGNING_PRIVATE_KEY_PASSWORD='你的密码'
163-
```
148+
### CI(GitHub Actions)需要配置
164149

165-
```bash
166-
# 方式 B:传私钥路径
167-
export TAURI_SIGNING_PRIVATE_KEY_PATH="$HOME/.tauri/astrbot.key"
168-
export TAURI_SIGNING_PRIVATE_KEY_PASSWORD='你的密码'
169-
```
150+
在仓库 `Settings -> Secrets and variables -> Actions` 配置:
170151

171-
执行构建:
152+
- `TAURI_SIGNING_PRIVATE_KEY`:Tauri updater 私钥内容(多行)
153+
- `TAURI_SIGNING_PRIVATE_KEY_PASSWORD`:私钥密码
154+
- `ASTRBOT_UPDATER_PUBKEY`:与私钥配对的公钥
155+
- `ASTRBOT_UPDATER_ENDPOINT`(可选):覆盖更新源(默认上游)
156+
- `ASTRBOT_LINUX_BUNDLES`(可选):建议 `deb,rpm,appimage`
172157

173-
```bash
174-
# Linux(包含 updater 常用目标)
175-
cargo tauri build --bundles "deb,rpm,appimage"
176-
```
158+
CI 在发布阶段会自动生成并上传 `latest.json` 与 updater 产物(含 `.sig`)。
177159

178-
可用以下命令检查是否生成 updater 产物与签名文件:
160+
### 产物检查
179161

180162
```bash
181163
find src-tauri/target/release/bundle -type f | rg 'updater|\.sig$|AppImage\.tar\.gz|\.app\.tar\.gz|nsis\.zip'

scripts/ci/build-windows-installers.sh

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,14 @@ if [ -z "${bundles}" ]; then
2424
exit 1
2525
fi
2626

27+
tauri_config_path="${ASTRBOT_TAURI_CONFIG_PATH:-}"
28+
tauri_build_args=(--bundles "${bundles}")
29+
if [ -n "${tauri_config_path}" ]; then
30+
tauri_build_args=(--config "${tauri_config_path}" "${tauri_build_args[@]}")
31+
fi
32+
2733
echo "Building Windows installers with bundles: ${bundles}"
2834
(
2935
cd "${root_dir}"
30-
cargo tauri build --bundles "${bundles}"
36+
cargo tauri build "${tauri_build_args[@]}"
3137
)
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#!/usr/bin/env python3
2+
3+
from __future__ import annotations
4+
5+
import argparse
6+
import json
7+
import pathlib
8+
9+
DEFAULT_UPDATER_ENDPOINT = (
10+
"https://github.com/AstrBotDevs/AstrBot-desktop/releases/latest/download/latest.json"
11+
)
12+
13+
14+
def parse_args() -> argparse.Namespace:
15+
parser = argparse.ArgumentParser(
16+
description="Render a temporary Tauri config override for CI/local builds."
17+
)
18+
parser.add_argument("--output", required=True, help="Path to output JSON config file.")
19+
parser.add_argument(
20+
"--updater-endpoint",
21+
default=DEFAULT_UPDATER_ENDPOINT,
22+
help="Updater latest.json endpoint URL.",
23+
)
24+
parser.add_argument(
25+
"--updater-pubkey",
26+
default="",
27+
help="Updater public key. If empty, plugins.updater override is skipped.",
28+
)
29+
parser.add_argument(
30+
"--disable-updater-artifacts",
31+
action="store_true",
32+
help="Disable bundle.createUpdaterArtifacts override.",
33+
)
34+
return parser.parse_args()
35+
36+
37+
def main() -> int:
38+
args = parse_args()
39+
output_path = pathlib.Path(args.output)
40+
updater_endpoint = args.updater_endpoint.strip()
41+
updater_pubkey = args.updater_pubkey.strip()
42+
43+
config: dict[str, object] = {}
44+
if not args.disable_updater_artifacts:
45+
config["bundle"] = {"createUpdaterArtifacts": True}
46+
47+
if updater_endpoint and updater_pubkey:
48+
config["plugins"] = {
49+
"updater": {
50+
"active": True,
51+
"endpoints": [updater_endpoint],
52+
"pubkey": updater_pubkey,
53+
}
54+
}
55+
elif updater_endpoint and not updater_pubkey:
56+
print(
57+
"::warning::[tauri-build-config] "
58+
"ASTRBOT_UPDATER_PUBKEY is empty; skip plugins.updater override."
59+
)
60+
61+
output_path.parent.mkdir(parents=True, exist_ok=True)
62+
output_path.write_text(
63+
json.dumps(config, ensure_ascii=False, indent=2) + "\n",
64+
encoding="utf-8",
65+
)
66+
print(f"[tauri-build-config] generated: {output_path}")
67+
return 0
68+
69+
70+
if __name__ == "__main__":
71+
raise SystemExit(main())

src-tauri/src/desktop_bridge_commands.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,11 @@ pub(crate) async fn desktop_bridge_install_desktop_app_update(
247247
append_desktop_log(&format!(
248248
"desktop app update installed to version {target_version}; restarting app"
249249
));
250-
app_handle.restart();
250+
app_handle.request_restart();
251+
BackendBridgeResult {
252+
ok: true,
253+
reason: None,
254+
}
251255
}
252256

253257
#[tauri::command]

0 commit comments

Comments
 (0)