Documentation
¶
Overview ¶
Package update checks whether a newer KnightLoader release exists, surfaced on both deployments' General tab now (jdp, 2026-08-24: a container user hit the card's old desktop-only gate and asked where the toggle had gone - checking GitHub and saying so is exactly as harmless for a container as for desktop). What differs by deployment is never whether the check runs, only what happens once "update available" is true: desktop can fetch, verify and install the new release itself when the user asks it to (Download/Apply/Relaunch, further down), while a container - which cannot replace itself from the inside - is instead pointed at the release page and told to update the way it was deployed (docker pull, Unraid Community Applications, ...); see routes_features.go's updaterReason for the fuller version of that split.
Check itself only checks and reports, and that half is identical on both deployments. Download/Apply/Relaunch, further down, are desktop-only (App.RequestUpdateInstall is nil on the container build - a container has no running binary of its own to swap) and are never triggered automatically: updaterReason is explicit that installing a fetched release "is still a manual step there, same as any other desktop app before it grows a silent auto-apply" - a background auto-updater that replaces its own binary unattended is a real attack surface regardless of how well it verifies what it downloads, and that line is deliberately not crossed here. What does run, once the user asks: fetch the matching platform zip, verify its SHA-256 against a checksums.txt published in the same release (see INTEGRITY, below), atomically swap it into place, and relaunch. Full code-signature verification is the one piece of that chain still not attempted - see INTEGRITY for exactly what is, and is not, covered.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Apply ¶
Apply extracts the platform build from zipPath and atomically swaps it in at installPath (a single file on Windows/Linux, a .app bundle directory on macOS), then removes the now-consumed zip. installPath's own parent directory is used as the staging area specifically so the final swap is a same-filesystem os.Rename - the one operation that is genuinely atomic (no window where installPath is half-written), rather than a copy that could be interrupted partway.
The previous version is renamed to installPath+".old" rather than deleted outright: on Windows, the currently-running process still holds its own image open under that name, and only a rename (not a delete) of a running executable is reliably permitted while it is still executing - the same reason every self-updating Windows tool uses this exact rename-aside-then-move-in pattern instead of a direct overwrite. Best- effort cleanup is attempted immediately; if it fails (still locked) the leftover .old is harmless and gets replaced by the next Apply.
func CurrentExecutable ¶
CurrentExecutable resolves the running process's own image, and - on macOS specifically - the enclosing .app bundle that is the actual unit Apply swaps (os.Executable there returns the binary buried inside Contents/MacOS/, not the bundle Finder/Wails' own installer deals in). installPath is what Apply's exePath argument expects; runnablePath is what Relaunch actually execs - identical to installPath on Windows and Linux, where the "install" IS the one runnable file.
func Download ¶
Download fetches the release asset matching this platform from the latest GitHub release (only when it is actually newer than `current` - mirrors Check's own "dev never compares" and X.Y.Z-only rules so a caller cannot download a same-or-older build by mistake) into a fresh temp file and returns its path. Before returning, it also fetches that same release's checksums.txt asset and verifies the downloaded zip's own SHA-256 against the entry in it for this platform's filename - see this package's own doc comment for what that does and does not prove, and for why a release missing checksums.txt entirely is a hard failure here rather than a fallback to unverified. Deleting the returned path once Apply has consumed it is the caller's job (os.RemoveAll is safe to call on a path that no longer exists).
func Relaunch ¶
Relaunch starts the freshly-applied build as a new, independent process and returns immediately without waiting for it - the caller (desktop/ main.go, via App.RequestUpdateInstall) is expected to exit the OLD process right after this returns successfully, the same "spawn the replacement before tearing down the original" order every self-updater uses to avoid a window with no running instance at all.
Types ¶
type Info ¶
type Info struct {
Checked bool `json:"checked"`
Available bool `json:"available"`
Current string `json:"current"`
Latest string `json:"latest,omitempty"`
URL string `json:"url,omitempty"`
}
Info is what the settings page shows. Checked is false whenever Check could not complete (network error, private repo, rate limit) - distinct from Available=false, which means the check succeeded and the answer was "no, you already have the latest".
func Check ¶
Check compares `current` (buildinfo.Version) against the latest GitHub release tag. "dev" - every untagged local/main build - can never be meaningfully compared to a released version, so it is reported as checked-but-not-available rather than a version parse this package would have to guess at.