Aplikasi Wails dengan Self-Update

Dalam tutorial ini Anda akan menambahkan updater dalam aplikasi ke aplikasi Wails v3 baru. Di akhir, aplikasi akan:

  • Mengecek GitHub Releases sesuai permintaan (dan opsional dengan timer).
  • Mengunduh asset yang tepat untuk OS + arsitektur yang sedang berjalan.
  • Memverifikasi digest SHA-256 (dan opsional tanda tangan Ed25519) terhadap byte yang diunduh.
  • Menampilkan release notes di jendela update default framework.
  • Menukar biner yang sedang berjalan dan meluncurkan ulang — semua tanpa mengirim executable helper terpisah.

Kita akan menggunakan GitHub Releases sebagai sumber update karena gratis dan tidak memerlukan infrastruktur. Pola yang sama bekerja dengan keygen.sh dan Sparkle AppCast — lihat panduan Updater setelah selesai.


1

Mulai dengan aplikasi Wails baru

Buat proyek baru dengan template vanilla:

bash
wails3 init --template vanilla --name updater-tutorial
cd updater-tutorial

Anda sekarang seharusnya memiliki direktori dengan main.go, frontend/, dan Taskfile.yml. Konfirmasi dapat di-build dan diluncurkan:

bash
wails3 task dev

Jendela Wails kosong seharusnya terbuka. Keluar dan lanjutkan.

2

Tambahkan import updater

Buka main.go dan tambahkan dua paket updater ke import Anda:

main.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"
)

Ini menarik Updater itu sendiri dan provider GitHub Releases.

3

Konfigurasi Updater

app.Updater sudah terhubung ke setiap *application.App — Anda hanya perlu memanggil Init:

main.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)
}

Tempatkan ini setelah application.New dan sebelum app.Run().

4

Tambahkan item menu yang memicu update

Di main.go yang sama, tambahkan entri menu “Check for Updates…”:

main.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 membuka jendela update framework, menjalankan Check, dan jika rilis ditemukan, menjalankan DownloadAndInstall otomatis. Jendela tetap terbuka dalam state “Up to Date” saat tidak ada yang baru — pengguna menutupnya dengan tombol Close.

5

Jalankan sekali tanpa rilis

bash
wails3 task dev

Klik App → Check for Updates…. Anda seharusnya melihat jendela update terbuka sebentar, mengakses API GitHub, tidak menemukan rilis lebih baru dari 1.0.0, dan menetap pada state Up to Date dengan ✓ hijau.

Jika Anda mendapat error di sini, biasanya salah satu dari:

Gejala Perbaikan
404 Not Found Field Repository salah — harus owner/repo
403 rate-limited Tambahkan Token: "ghp_…" ke github.Config (gunakan PAT dengan scope public_repo)
Network errors Konfirmasi aplikasi yang berjalan dapat mengakses api.github.com
6

Terbitkan rilis uji

Naikkan currentVersion di main.go ke 1.0.0 (atau biarkan). Build untuk satu platform untuk mendapatkan biner yang dapat dilampirkan ke rilis:

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 ..

Buat file SHA256SUMS di samping biner:

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

Anda seharusnya melihat satu atau lebih baris seperti:

abc123…  updater-tutorial-darwin-arm64.zip

Sekarang terbitkan ini sebagai v2.0.0 di repositori GitHub Anda:

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

Jalankan aplikasi dan verifikasi update

Dengan currentVersion masih 1.0.0, jalankan aplikasi lagi:

bash
wails3 task dev

Klik App → Check for Updates…. Kali ini Anda seharusnya melihat sesuatu seperti:

Jendela updater default dalam state Update Ready, menampilkan pill versi, release notes yang dirender Markdown, dan tombol utama Restart & Apply.

  • Ikon hero berubah dari biru ↓ (“Update Available”) ke hijau ✓ (“Update Ready”).
  • Subtitle menampilkan v1.0.0 → v2.0.0 · <size>.
  • Panel release notes merender Markdown Anda dengan bold, code span, dan tabel.
  • Progress bar terisi selama unduhan (cepat — biner kecil).

Updater men-stage biner baru di direktori temp. Untuk menyelesaikan update:

  • Klik Restart & Apply.
  • Aplikasi Anda keluar, helper menukar biner, biner baru diluncurkan ulang.
  • Aplikasi yang diluncurkan ulang melaporkan currentVersion = "1.0.0" (karena kita hardcode), tetapi byte di disk sesuai build v2.0.0.

Di aplikasi nyata, currentVersion akan diset saat build via -ldflags agar biner baru tahu sekarang v2.0.0 dan pengecekan berikutnya tidak menemukan update.

8

Hubungkan `currentVersion` ke build

Ganti konstanta dengan variabel build-time:

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

Lalu di perintah build Anda:

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

Atau tambahkan -ldflags ke Taskfile.yml agar mengambil dari git describe --tags.

9

Tambahkan penandatanganan kriptografis (disarankan untuk produksi)

Path SHA256SUMS memverifikasi integritas (byte sesuai yang disimpan GitHub) tetapi bukan autentisitas (byte tersebut diproduksi pipeline rilis Anda, bukan akun maintainer yang dikompromikan). Untuk ketahanan terhadap perubahan, tandatangani setiap rilis dengan kunci 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

Untuk setiap rilis, tandatangani digest SHA-256 setiap asset dengan kunci privat Anda. Helper Go kecil:

cmd/sign-release/main.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))
}

Provider GitHub default saat ini tidak mengambil file tanda tangan terpisah — Anda dapat menulis provider kustom yang melakukannya, atau beralih ke keygen.sh yang menandatangani setiap artifact di sisi server dan mengekspos digest dan tanda tangan via API-nya.

Embed kunci publik di aplikasi Anda:

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

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

Dengan PublicKey diset, rilis apa pun yang mengirim Signature harus diverifikasi terhadap kunci ini. Sumber rilis tidak dapat mengganti kuncinya sendiri — itulah tujuan pinning out-of-band saat build time.

10

Sesuaikan jendela

Jendela default mencakup kasus umum. Tiga jalan keluar jika Anda butuh kontrol lebih — pilih satu berdasarkan seberapa banyak yang ingin disesuaikan:

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

Lihat bagian Tema via variabel CSS untuk daftar variabel lengkap.

11

Jalankan pengecekan otomatis di latar belakang

Untuk mengecek dengan timer alih-alih (atau selain) klik menu:

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

Setiap tick menjalankan alur CheckAndInstall yang sama seperti klik manual. Set Window: updater.WindowNone jika Anda ingin pengecekan berkala diam sampai sesuatu benar-benar ditemukan — lalu subscribe ke EventUpdateAvailable sendiri untuk memutuskan UX apa yang ditampilkan.

Selesai

Anda sekarang memiliki aplikasi Wails yang:

  • Mengecek GitHub Releases untuk update sesuai permintaan dan dengan timer.
  • Merender release notes sebagai Markdown di jendela default yang rapi.
  • Memverifikasi unduhan terhadap digest SHA-256 yang Anda terbitkan.
  • Opsional memverifikasi tanda tangan Ed25519 terhadap kunci publik yang Anda embed saat build time.
  • Menukar biner yang sedang berjalan in-place dan meluncurkan ulang otomatis.

Langkah selanjutnya

  • Panduan Updater memiliki referensi API lengkap, setiap event, setiap opsi konfigurasi, dan mekanisme swap mode helper.
  • Lihat v3/examples/updater untuk contoh lengkap yang dapat Anda clone.
  • Repo target uji wailsapp/updater-demo menunjukkan tata letak release-asset yang disarankan.

Hal yang perlu diperhatikan di produksi

  • Code signing di macOS — Gatekeeper memerlukan biner yang ditukar ditandatangani dan dinotarisasi. Tandatangani bundle .app Anda sebelum zip untuk rilis. Updater mempertahankan byte verbatim; tidak menandatangani ulang apa pun.
  • Antivirus di Windows — file .exe unsigned yang diunduh dari internet dapat memicu peringatan SmartScreen. Tandatangani biner dengan sertifikat Authenticode, atau terima bahwa pengguna di mesin terkunci mungkin perlu whitelist aplikasi Anda.
  • Rilis atomik — terbitkan SHA256SUMS (dan biner Anda) bersama, bukan di commit terpisah. Updater mengambil sidecar terpisah dari biner; jika keduanya drift, pemeriksaan digest gagal closed.
  • Versi yang dilewati — tombol “Skip This Version” jendela default mencatat skip secara lokal. Jika Anda mengirim update keamanan kritis, beri nomor versi baru agar tidak otomatis dilewati pengguna yang menolak rilis sebelumnya.
Edit page

Last updated: