Tauri应用版本更新指南
Tauri 是一个轻便的跨端应用构建工具,类似 Electron。它内置了一套版本更新的方案,下面我分成三个部分给大家做下介绍。
- 版本发布机制
- 版本更新机制
- 注意事项
版本发布机制
跨端应用的版本发布,涉及到多个平台( Win / Mac / Linux )的构建产物,挨个构建比较复杂,可以借助 Github Actions 等自动化 CI 平台进行。
Tauri 官方提供了一个适配 GitHub Actions 的 tauri-action,可以用来加速这个过程。
首先按照其教程配置如下的 Github workflow 配置:
1# .github/workflows/publish.yml 2name: "publish" 3on: 4 push: 5 branches: 6 - release 7 8jobs: 9 publish-tauri: 10 strategy: 11 fail-fast: false 12 matrix: 13 platform: [macos-latest, ubuntu-latest, windows-latest] 14 15 runs-on: ${{ matrix.platform }} 16 steps: 17 - uses: actions/checkout@v2 18 - name: setup node 19 uses: actions/setup-node@v1 20 with: 21 node-version: 16 22 - name: install Rust stable 23 uses: actions-rs/toolchain@v1 24 with: 25 toolchain: stable 26 - name: install dependencies (ubuntu only) 27 if: matrix.platform == 'ubuntu-latest' 28 run: | 29 sudo apt-get update 30 sudo apt-get install -y libgtk-3-dev webkit2gtk-4.0 libappindicator3-dev librsvg2-dev patchelf 31 - name: install app dependencies and build it 32 run: yarn && yarn build 33 - uses: tauri-apps/tauri-action@v0 34 env: 35 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 36 with: 37 tagName: v__VERSION__ # the action automatically replaces \_\_VERSION\_\_ with the app version 38 releaseName: "v__VERSION__" 39 releaseBody: "See the assets to download this version and install." 40 releaseDraft: true # 不需要 draft 的可以改成 false 41 prerelease: false
有了这个配置文件之后,每当 release 分支推送新代码,就会触发 tauri 的版本构建和发布过程。
下面是 Github Action 的示意图:
如果顺利构建完成的话,会 tauri 会自动根据当前的版本号,创建出对应的 tag 和 release。
Release 附件形如:
如上一个简单的版本发布就完成了。
签名
为使版本的发布更安全,可以使用 tauri 提供的签名功能。
首先使用如下的方式生成签名用的公钥、私钥。(注意保存,丢失后无法再发布新版本)
1# 需要先全局安装 @tauri-apps/cli 2# npm i -g @tauri-apps/cli 3 4tauri signer generate -w ~/.tauri/myapp.key
上面 的命令会自动生成一个公钥、私钥对。公钥可以公开分享,私钥必须严密保存。
先在 Github workflow 配置中加入以下内容:
1 - uses: tauri-apps/tauri-action@v0 2 env: 3 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 4 TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} # 密钥,需要提前配置在 Github Secrets中 5 TAURI_KEY_PASSWORD: "" # 密钥的加密文本,与ssh-keygen时输入的密码一致即可。如果未输入密码,则此处留空,如果输入了密码,则也需要添加到 secrets 中,然后使用 ${{ secrets.TAURI_PRIVATE_KEY_PASSWORD }} 这种形式 6 with: 7 tagName: "v__VERSION__" # the action automatically replaces \_\_VERSION\_\_ with the app version 8 releaseName: "v__VERSION__" 9 releaseBody: "See the assets to download this version and install." 10 releaseDraft: false # 按需调整 11 prerelease: false
签名的版本发布才会有上面 release 附件中的 .sig
后缀的文件,它们代表着各个不同版本的签名内容。
版本更新机制
Tauri 中提供了关于版本更新的教程,详见 Updater。
在 tauri.conf.json
文件中加入如下的内容:
1"updater": { 2 "active": true, 3 "endpoints": [ 4 "https://releases.myapp.com/{{target}}/{{current_version}}" 5 ], 6 "dialog": true, 7 "pubkey": "YOUR_UPDATER_SIGNATURE_PUBKEY_HERE" 8}
其中各个字段的含义解释如下:
- active 是否启用
- endpoints 检查版本更新的地址列表
- dialog 是否启用内建的新版本提醒对话框,如果不启用的话,需要在 JS 中自行监听事件并进行提醒
- pubkey 上面提到
tauri signer generate
生成的钥匙对中的公钥的内容。
Endpoints 可以有多个,tauri 会依次尝试。它的内容也可以有两种不同的格式
- 动态接口形式
- 静态文件形式
动态接口形式的 endpoint 地址,形如 https://releases.myapp.com/{{target}}/{{current_version}}
,在 url 中已经有了当前平台和当前版本号的参数,因此只需要返回当前平台的信息即可,形如:
1{ 2 "url": "https://mycompany.example.com/myapp/releases/myrelease.tar.gz", 3 "version": "0.0.1", 4 "notes": "Theses are some release notes", 5 "pub_date": "2020-09-18T12:29:53+01:00", 6 "signature": "" 7}
而静态文件形式的方式,则需要同时指定多个平台的最新版本信息,形如:
1{ 2 "name": "v1.0.0", 3 "notes": "Test version", 4 "pub_date": "2020-06-22T19:25:57Z", 5 "platforms": { 6 "darwin": { 7 "signature": "", 8 "url": "https://github.com/lemarier/tauri-test/releases/download/v1.0.0/app.app.tar.gz" 9 }, 10 "linux": { 11 "signature": "", 12 "url": "https://github.com/lemarier/tauri-test/releases/download/v1.0.0/app.AppImage.tar.gz" 13 }, 14 "win64": { 15 "signature": "", 16 "url": "https://github.com/lemarier/tauri-test/releases/download/v1.0.0/app.x64.msi.zip" 17 } 18 } 19}
需要注意无论是哪种形式,endpoint 的 url 都需要是 https 协议的。
因为上面版本发布时使用了 GitHub Actions 自动发布,有一定的规律,因此这里我们也可以使用动态接口的形式,实时获取 Github 中最新的 release 信息。
伪码如下:
1const platformSuffixMap: Record<string, string> = { 2 darwin: '.app.tar.gz', 3 linux: '.AppImage.tar.gz', 4 win64: '.msi.zip', 5}; 6 7const [platform, version] = params // 获取当前请求对应的平台和版本号 8const suffix = platformSuffixMap[platform ?? '']; 9if (suffix) { 10 // 获取 github 上公开的版本号信息,只取第一页 11 const releases = await axios.get( 12 'https://api.github.com/repos/<user>/<repo>/releases' 13 ); 14 15 // 过滤状态得到最后一个正式的版本号 16 const latestRelease = releases.data.find( 17 (item: any) => !item.draft && !item.prerelease 18 ); 19 if (latestRelease) { 20 // 分别查找安装包和签名文件 21 const binaryAsset = latestRelease.assets.find((e: any) => 22 e.name.endsWith(suffix) 23 ); 24 const sigAsset = latestRelease.assets.find((e: any) => 25 e.name.endsWith(`${suffix}.sig`) 26 ); 27 if (binaryAsset && sigAsset) { 28 const sigContent = await axios.get(sigAsset.browser_download_url); 29 30 // 返回版本更新信息 31 res.status(200).json({ 32 url: binaryAsset.browser_download_url, 33 version: latestRelease.tag_name, 34 notes: latestRelease.body, 35 pub_date: latestRelease.published_at, 36 signature: sigContent.data, 37 }); 38 return; 39 } 40 } 41} 42 43// 没有找到可用的更新,返回 HTTP 204 no content 44res.status(204).end();
按如上方式配置之后,就可以实现版本号的自动更新与 Github Release 的动态结合了。
注意事项
如上的方式也有一些需要注意的事项:
-
Endpoint 必须为 https 的地址,不然会构建失败
-
签名信息请妥善保存,私钥(以 .key 结尾的文件)不能外传
-
Github 的 assets 保存在 s3 之上,因为众所周知的原因,无法正常下载。需要指定 HTTPS_PROXY 和 HTTP_PROXY 为本地代理地址之后,方能正常运行。不然会出现版本正常提醒,但是点击确定后无法正常安装的现象。