force-update: single-shot with a 30s fail-fast timeout

This commit is contained in:
mram
2026-09-21 09:09:27 +02:00
parent cedf28a809
commit 272a3a467d
2 changed files with 10 additions and 6 deletions
+7 -5
View File
@@ -263,11 +263,13 @@ executable location as-is and leaves the config untouched.
idle the process exits with code 3 so the service recovery restarts it idle the process exits with code 3 so the service recovery restarts it
on the new version. Interactive runs only log "restart to apply". on the new version. Interactive runs only log "restart to apply".
`dev` builds and builds without an embedded public key never update. `dev` builds and builds without an embedded public key never update.
- **`--force-update`** runs the same check immediately: it downloads, - **`--force-update`** runs the same check immediately, single-shot: one
verifies and stages a newer release, and if the service is running it attempt with a 30 s timeout, then exit — "up to date" (exit 0) or the
restarts it right away (otherwise the new version applies on next error (exit 1), no retries. When a newer release is found it downloads,
start). On Windows it elevates via UAC only when the stage or restart verifies and stages it, and if the service is running it restarts it
needs permissions the caller does not have. right away (otherwise the new version applies on next start). On Windows
it elevates via UAC only when the stage or restart needs permissions the
caller does not have.
- **Signing setup (one time)**: `openssl genpkey -algorithm ed25519 -out - **Signing setup (one time)**: `openssl genpkey -algorithm ed25519 -out
private.pem`; `openssl pkey -in private.pem -pubout -out public.pem`. private.pem`; `openssl pkey -in private.pem -pubout -out public.pem`.
Private key → repo secret `RELEASE_SIGNING_KEY`; public key → committed into Private key → repo secret `RELEASE_SIGNING_KEY`; public key → committed into
+3 -1
View File
@@ -315,7 +315,9 @@ func forceUpdateCommand(configPath string, elevatedChild bool) int {
defer logCloser.Close() defer logCloser.Close()
u := &update.Updater{Repo: cfg.UpdateRepo, Asset: cfg.UpdateAsset, Version: version, Log: log} u := &update.Updater{Repo: cfg.UpdateRepo, Asset: cfg.UpdateAsset, Version: version, Log: log}
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) // Single-shot: one attempt, fail fast when the server is unreachable
// instead of hanging in a TCP connect for minutes.
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel() defer cancel()
staged, err := u.Check(ctx, exePath) staged, err := u.Check(ctx, exePath)
if err != nil && isPermission(err) && !service.Elevated() { if err != nil && isPermission(err) && !service.Elevated() {