CFG_VER/APP_VER in the env file: invalid configs replaced, updates follow APP_VER (dev/stable/pin)
This commit is contained in:
+41
-16
@@ -26,11 +26,15 @@ import (
|
||||
// maxAssetSize bounds release asset downloads.
|
||||
const maxAssetSize = 512 << 20
|
||||
|
||||
// Updater checks one Gitea repository for newer releases.
|
||||
// Updater checks one Gitea repository for releases.
|
||||
type Updater struct {
|
||||
Repo string // e.g. https://git.rambossek.at/PUBLIC/gpu-turnstile
|
||||
Asset string // e.g. gpu-turnstile.exe
|
||||
Version string // current version, e.g. v0.1.2 ("dev" disables updates)
|
||||
Version string // current binary version, e.g. v0.1.2 ("dev" cannot be compared)
|
||||
// Desired is the APP_VER policy: "dev" disables updates, "stable" (or
|
||||
// empty) tracks the latest release, anything else is an exact vX.Y.Z
|
||||
// release tag to pin — staging it even when that means a downgrade.
|
||||
Desired string
|
||||
Log *slog.Logger
|
||||
Client *http.Client
|
||||
}
|
||||
@@ -167,15 +171,20 @@ func CleanupOld(exePath string) {
|
||||
os.Remove(exePath + ".new")
|
||||
}
|
||||
|
||||
// Check performs a single update check. staged is true when a newer,
|
||||
// Check performs a single update check. staged is true when a
|
||||
// signature-verified binary has been swapped into place at exePath; the
|
||||
// caller should then restart the process. A nil error with staged=false
|
||||
// means "no action" (up to date, disabled, or dev build); a non-nil error
|
||||
// means the check failed and the running binary is untouched.
|
||||
// means "no action" (up to date, APP_VER=dev, or no embedded public key);
|
||||
// a non-nil error means the check failed and the running binary is
|
||||
// untouched.
|
||||
func (u *Updater) Check(ctx context.Context, exePath string) (staged bool, err error) {
|
||||
log := u.logger()
|
||||
if u.Version == "" || u.Version == "dev" {
|
||||
log.Debug("auto-update: dev build, skipping")
|
||||
desired := u.Desired
|
||||
if desired == "" {
|
||||
desired = "stable"
|
||||
}
|
||||
if desired == "dev" {
|
||||
log.Debug("auto-update: APP_VER=dev, skipping")
|
||||
return false, nil
|
||||
}
|
||||
if publicKeyPEM == "" {
|
||||
@@ -187,21 +196,37 @@ func (u *Updater) Check(ctx context.Context, exePath string) (staged bool, err e
|
||||
return false, err
|
||||
}
|
||||
|
||||
body, err := u.get(ctx, api+"/releases/latest")
|
||||
pinned := desired != "stable"
|
||||
endpoint := api + "/releases/latest"
|
||||
if pinned {
|
||||
endpoint = api + "/releases/tags/" + desired
|
||||
}
|
||||
body, err := u.get(ctx, endpoint)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("fetch latest release: %w", err)
|
||||
return false, fmt.Errorf("fetch release: %w", err)
|
||||
}
|
||||
var rel release
|
||||
if err := json.Unmarshal(body, &rel); err != nil {
|
||||
return false, fmt.Errorf("parse release: %w", err)
|
||||
}
|
||||
newer, err := newerVersion(u.Version, rel.TagName)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if !newer {
|
||||
log.Debug("auto-update: up to date", "version", u.Version, "latest", rel.TagName)
|
||||
return false, nil
|
||||
if pinned {
|
||||
// Pin mode: any difference from the target tag means stage it —
|
||||
// including downgrades and replacing a dev binary.
|
||||
if u.Version == rel.TagName {
|
||||
log.Debug("auto-update: already on pinned version", "version", u.Version)
|
||||
return false, nil
|
||||
}
|
||||
} else if u.Version != "" && u.Version != "dev" {
|
||||
// Stable mode: only strictly newer releases count; a dev binary
|
||||
// cannot be compared and is always replaced by the latest release.
|
||||
newer, err := newerVersion(u.Version, rel.TagName)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if !newer {
|
||||
log.Debug("auto-update: up to date", "version", u.Version, "latest", rel.TagName)
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
urls := make(map[string]string, len(rel.Assets))
|
||||
|
||||
Reference in New Issue
Block a user