参与贡献

编辑此文档

翻译文档,或在您的计算机上打开完整项目。

在您选择提交工作成果之前,不会发布任何内容。

可自更新的 Wails 应用

构建一个可通过 GitHub Releases 自行更新的 Wails v3应用——涵盖从`wails3 init`到签名版本验证和辅助模式替换的全过程。

本教程将为一个全新的 Wails v3应用添加应用内更新程序。完成后,该应用将能够:

  • 按需检查 GitHub Releases(也可选择定时检查)。
  • 下载适用于当前操作系统和架构的资源。
  • 根据下载的字节验证 SHA-256摘要(也可选择验证 Ed25519 签名)。
  • 在框架的默认更新窗口中显示发行说明。
  • 替换正在运行的二进制文件并重新启动,而且无需分发单独的辅助可执行文件。

我们将使用GitHub Releases作为更新源,因为它免费且不需要任何基础设施。同样的模式也适用于keygen.sh和Sparkle AppCast——完成本教程后,请参阅更新程序指南。


1

从全新的 Wails 应用开始

使用 vanilla 模板搭建新项目:

bash
wails3 init -n updater-tutorial -t vanilla
cd updater-tutorial

现在应当已有一个包含main.go、frontend/和Taskfile.yml的目录。确认项目能够构建并启动:

bash
wails3 task dev

此时应打开一个空白的 Wails 窗口。退出应用,然后继续。

2

添加更新程序导入项

打开main.go,将两个更新程序包添加到导入项中:

main.go
go
package main

import (
    _ "embed"

    "github.com/wailsapp/wails/v3/pkg/application"
    "github.com/wailsapp/wails/v3/pkg/updater"
    "github.com/wailsapp/wails/v3/pkg/updater/providers/github"
)

这两个包分别引入 Updater 本身和 GitHub Releases 提供程序。

3

配置 Updater

app.Updater已接入每个*application.App,你只需调用Init:

main.go
go
const currentVersion = "1.0.0"

gh, err := github.New(github.Config{
    Repository:    "yourorg/your-repo",   // ← change this
    ChecksumAsset: "SHA256SUMS",          // sibling file with sha256 digests
})
if err != nil {
    log.Fatalf("github.New: %v", err)
}

if err := app.Updater.Init(updater.Config{
    CurrentVersion: currentVersion,
    Providers:      []updater.Provider{gh},
}); err != nil {
    log.Fatalf("Updater.Init: %v", err)
}

将此代码放在application.New之后、app.Run()之前。

4

添加触发更新的菜单项

在同一个main.go中添加“检查更新…”菜单项:

main.go
go
menu := app.Menu.New()
app.Menu.SetApplicationMenu(menu)
appMenu := menu.AddSubmenu("App")
appMenu.Add("Check for Updates…").OnClick(func(*application.Context) {
    go func() {
        if err := app.Updater.CheckAndInstall(context.Background()); err != nil {
            app.Logger.Error("update", "error", err)
        }
    }()
})

CheckAndInstall会打开框架的更新窗口,运行Check;如果发现发行版本,则自动运行DownloadAndInstall。没有新版本时,窗口会保持打开并显示“已是最新版本”状态,用户可通过关闭按钮将其关闭。

5

在没有发行版本时运行一次

bash
wails3 task dev

点击应用 → 检查更新…。此时应看到更新窗口短暂打开、访问 GitHub API、未找到比1.0.0更新的发行版本,最后停留在带有绿色 ✓ 的已是最新版本状态。

如果此处出现错误,通常是以下原因之一:

症状 修复方法
404 Not Found Repository字段不正确——必须为owner/repo
403 rate-limited 将Token: "ghp_…"添加到 github.Config(使用具有public_repo作用域的 PAT)
网络错误 确认正在运行的应用可以访问api.github.com
6

发布测试版本

将main.go中的currentVersion提升至1.0.0(也可保持不变)。针对一个平台进行构建,以获得可附加到发行版本的二进制文件:

bash
wails3 task build:darwin
# produces bin/updater-tutorial.app
# zip it for the release asset:
cd bin && zip -r updater-tutorial-darwin-arm64.zip updater-tutorial.app && cd ..

在二进制文件旁生成一个SHA256SUMS文件:

bash
cd bin
shasum -a 256 updater-tutorial-* > SHA256SUMS
cat SHA256SUMS

你应当会看到一行或多行类似以下内容:

text
abc123…  updater-tutorial-darwin-arm64.zip

现在将其作为v2.0.0发布到你的 GitHub 仓库:

bash
gh release create v2.0.0 \
    --title "v2.0.0" \
    --notes "First update for the self-update tutorial.

- **Bold** Markdown renders in the update window
- \`Code spans\` too
- Lists work
- GFM tables work" \
    bin/SHA256SUMS bin/updater-tutorial-*
7

运行应用并验证更新

保持currentVersion仍为1.0.0,再次运行应用:

bash
wails3 task dev

点击应用 → 检查更新…。这一次,你应当会看到类似以下内容:

处于“更新就绪”状态的默认更新程序窗口,其中显示版本徽标、经 Markdown 渲染的发行说明,以及“重新启动并应用”主按钮。

  • 主图标会从蓝色 ↓(“有可用更新”)变为绿色 ✓(“更新就绪”)。
  • 副标题显示v1.0.0 → v2.0.0 · <size>。
  • 发行说明面板会渲染你的 Markdown,包括粗体、行内代码和表格。
  • 下载期间进度条会逐渐填满(速度会很快,因为二进制文件很小)。

Updater 会将新二进制文件暂存到临时目录中。要完成更新:

  • 点击重新启动并应用。
  • 应用退出,辅助程序替换二进制文件,然后重新启动新的二进制文件。
  • 重新启动的应用会报告currentVersion = "1.0.0"(因为我们对其进行了硬编码),但磁盘上的字节与v2.0.0构建版本一致。

在实际应用中,currentVersion应在构建时通过-ldflags设置,使新二进制文件知道自己现在是v2.0.0,这样后续检查就不会发现更新。

8

将`currentVersion`接入构建流程

将常量替换为构建时变量:

main.go
go
var (
    currentVersion = "dev" // overridden by -ldflags at release time
)

然后在构建命令中:

bash
wails3 task build:darwin -- -ldflags "-X main.currentVersion=2.0.0"

或者,将-ldflags添加到Taskfile.yml,使其从git describe --tags获取值。

9

添加加密签名(建议用于生产环境)

SHA256SUMS 路径验证的是完整性(这些字节与 GitHub 存储的内容一致),而非真实性(即这些字节由你的发布流水线生成,而不是来自已遭入侵的维护者账户)。为防止篡改,请使用 Ed25519 密钥为每个发行版本签名:

bash
# One-time: generate the keypair
ssh-keygen -t ed25519 -f updater-key -N "" -C "wails-updater"
#   updater-key      — keep secret (build server, HSM, password manager)
#   updater-key.pub  — bundle in your app

每次发布时,都使用私钥对每个资源的 SHA-256 摘要进行签名。下面是一个简单的 Go 辅助程序:

cmd/sign-release/main.go
go
package main

import (
    "crypto/ed25519"
    "crypto/sha256"
    "encoding/base64"
    "fmt"
    "io"
    "os"
)

func main() {
    priv, _ := os.ReadFile("updater-key")
    key := ed25519.PrivateKey(priv) // raw 64-byte private key

    f, _ := os.Open(os.Args[1])
    defer f.Close()
    h := sha256.New()
    _, _ = io.Copy(h, f)
    sig := ed25519.Sign(key, h.Sum(nil))
    fmt.Println(base64.StdEncoding.EncodeToString(sig))
}

默认的 GitHub 提供程序目前不会获取单独的签名文件——你可以编写自定义提供程序来获取该文件,也可以改用keygen.sh;它会在服务器端签署每个制品,并通过其 API 同时提供摘要和签名。

将公钥嵌入应用:

main.go
go
//go:embed updater-key.pub
var updaterPublicKey []byte

app.Updater.Init(updater.Config{
    CurrentVersion: currentVersion,
    PublicKey:      updaterPublicKey,
    Providers:      []updater.Provider{gh},
})

设置PublicKey后,任何附带Signature的发行版都必须通过此密钥的验证。发行源无法替换为自己的密钥——这正是在构建时通过带外方式固定密钥的意义所在。

10

自定义窗口

默认窗口适用于常见情况。如果需要更多控制,可以使用以下三种扩展方式——根据所需的自定义程度选择一种:

go
app.Updater.Init(updater.Config{
    // …
    Window: &updater.BuiltinWindow{
        CSS: `:root { --accent: #ff6f00; --radius: 16px; }`,
    },
})

有关完整的变量列表,请参阅通过 CSS 变量设置主题一节。

11

在后台运行自动检查

要按定时器检查,而不是通过菜单点击检查(或在菜单点击检查之外同时进行定时检查),请使用:

go
app.Updater.Init(updater.Config{
    CurrentVersion: currentVersion,
    Providers:      []updater.Provider{gh},
    PublicKey:      updaterPublicKey,
    CheckInterval:  6 * time.Hour,
})

每次定时触发都会运行与手动点击相同的CheckAndInstall流程。如果希望定期检查在实际发现内容之前保持静默,请设置Window: updater.WindowNone,然后自行订阅EventUpdateAvailable,以决定显示何种用户体验。

大功告成

现在,你已经拥有一个具备以下功能的 Wails 应用:

  • 按需和按定时器检查 GitHub Releases 中的更新。
  • 在精美的默认窗口中将发行说明渲染为 Markdown。
  • 使用你发布的 SHA-256 摘要验证下载内容。
  • 可选择使用构建时嵌入的公钥验证 Ed25519 签名。
  • 原地替换正在运行的二进制文件,并自动重新启动。

后续步骤

生产环境中的注意事项

  • macOS 上的代码签名——Gatekeeper 要求替换后的二进制文件经过签名和公证。请在将.app包压缩为发行文件之前对其签名。更新程序会原样保留所有字节,不会重新签署任何内容。
  • Windows 上的防病毒软件——从互联网下载的未签名.exe文件可能会触发 SmartScreen 警告。请使用 Authenticode 证书对二进制文件进行签名;否则,使用受严格管控计算机的用户可能需要将你的应用加入白名单。
  • 原子化发布——请一起发布SHA256SUMS和二进制文件,不要分成不同的提交。更新程序会分别获取伴随文件和二进制文件;如果两者不同步,摘要检查将以安全方式失败并拒绝继续。
  • 跳过版本——默认窗口中的“跳过此版本”按钮会在本地记录跳过操作。如果要发布关键安全更新,请使用新的版本号,以免曾忽略较早发行版的用户自动跳过该更新。
编辑页面

最后更新: