返回 DeepSeek-Reasonix
manifest.go
根目录 / desktop / internal / update / manifest.go
1 // Package update defines the desktop auto-updater's shared types and signature
2 // verification — the single source of truth for the latest.json manifest format,
3 // the platform-asset lookup, and minisign verification. Both the CI signing tool
4 // (desktop/cmd/sign) and the running updater (desktop/updater.go) import this
5 // package, so the sign path and the verify path can never drift apart.
6 package update
7
8 import "runtime"
9
10 // ElectronInstallLayout is an explicit migration boundary. Wails-era clients
11 // reject unknown layouts before downloading or replacing any installed file.
12 // Their first Electron upgrade must use the complete installer manually.
13 const ElectronInstallLayout = "electron-v1"
14
15 // Manifest is the latest.json published alongside a desktop release. The updater
16 // fetches it from the R2 mirror (primary) or GitHub releases (fallback), compares
17 // Version against the running build, and looks up the running platform's artifact
18 // via Asset / NativePackage.
19 type Manifest struct {
20 Version string `json:"version"` // release version, e.g. "v1.1.0"
21 Notes string `json:"notes"` // markdown release notes
22 PubDate string `json:"pub_date"` // RFC3339, optional
23 DownloadPage string `json:"download_page"` // human-facing download page (macOS manual-update fallback)
24 ReleaseNotesURL string `json:"release_notes_url,omitempty"` // exact version history page; older manifests omit it
25 Platforms map[string]Asset `json:"platforms"` // keyed by PlatformKey, e.g. "darwin-arm64"
26 NativePackages map[string]Asset `json:"native_packages,omitempty"` // optional OS package assets, e.g. linux-amd64 → .deb
27 Downloads map[string]Asset `json:"downloads,omitempty"` // optional signed human-download assets keyed by exact filename
28 }
29
30 // Asset is one platform's downloadable artifact plus the metadata the updater
31 // needs to verify and report on it.
32 type Asset struct {
33 URL string `json:"url"` // direct download URL for the artifact
34 Sig string `json:"sig"` // URL of the detached minisign (.minisig) signature
35 Size int64 `json:"size"` // artifact size in bytes (download-progress denominator)
36 SHA256 string `json:"sha256"` // lowercase hex digest, for a second integrity check after verify
37 // InstallLayout identifies the on-disk layout the artifact expects after
38 // install. Empty means the pre-v1.20 flat layout (ignored by old clients).
39 // New clients require "versioned-v1" for self-update and reject unknown
40 // values without changing the active install.
41 InstallLayout string `json:"install_layout,omitempty"`
42 }
43
44 // PlatformKey is the map key used in Manifest.Platforms for the given OS/arch.
45 // The updater calls CurrentPlatform; the manifest generator builds keys the same
46 // way, so lookups always agree.
47 func PlatformKey(goos, goarch string) string { return goos + "-" + goarch }
48
49 // CurrentPlatform is PlatformKey for the running binary.
50 func CurrentPlatform() string { return PlatformKey(runtime.GOOS, runtime.GOARCH) }
51
52 // Asset returns the portable/tarball artifact for the running platform, if listed.
53 func (m Manifest) Asset() (Asset, bool) {
54 a, ok := m.Platforms[CurrentPlatform()]
55 return a, ok
56 }
57
58 // NativePackage returns the OS package artifact for the running platform, if listed.
59 // Older manifests omit native_packages; callers must treat absence as "no package".
60 func (m Manifest) NativePackage() (Asset, bool) {
61 if m.NativePackages == nil {
62 return Asset{}, false
63 }
64 a, ok := m.NativePackages[CurrentPlatform()]
65 return a, ok
66 }
67
67 lines GO