feat(updater): auto-update binary from Forgejo releases at 2am daily #19

Merged
addison merged 2 commits from exe-dev-bot/kiosk:feat/auto-update into main 2026-02-14 04:11:13 -05:00
Contributor

Summary

The kiosk web server now auto-updates itself at 2am daily by checking Forgejo releases.

How it works

  1. SchedulerStartAutoUpdater() launches a goroutine that sleeps until the next 2:00 AM local time, then runs the update check every 24 hours
  2. Version check — Fetches https://git.kwila.cloud/api/v1/repos/kwila/kiosk/releases?limit=1 and compares the release tag_name against the build-time version variable
  3. Download — If versions differ, finds the asset matching runtime.GOARCH (e.g. kiosk-arm64), downloads to a temp file in the same directory
  4. Replacechmod +x, then atomic os.Rename over the running binary
  5. Restart — Calls os.Exit(0). Since the systemd service has Restart=always, it comes back up running the new version

All errors are logged, never fatal — retries next day.

Build-time version injection

The justfile now injects version via ldflags:

go build -ldflags "-X main.version=v0.2.4" -o kiosk .

Defaults to dev for local builds. CI should pass the release tag.

Changes

  • updater.go — Core auto-update logic (scheduler, API check, download, replace, exit)
  • updater_test.go — 8 tests with httptest mock server covering all paths
  • main.go — Wire in StartAutoUpdater() call
  • justfile — Add version variable, inject via -ldflags in build recipe, expand test recipe to ./...

Tests

Test Covers
SkipsWhenVersionMatches No-op when already on latest
DownloadsAndReplaces Happy path: download, replace, exit
HandlesAPIError 500 from releases API
HandlesEmptyReleases Empty releases array
HandlesMissingArchAsset No matching arch in assets
HandlesConnectionError Unreachable API
HandlesBadJSON Malformed response
HandlesDownloadError 404 on binary download
## Summary The kiosk web server now auto-updates itself at 2am daily by checking Forgejo releases. ## How it works 1. **Scheduler** — `StartAutoUpdater()` launches a goroutine that sleeps until the next 2:00 AM local time, then runs the update check every 24 hours 2. **Version check** — Fetches `https://git.kwila.cloud/api/v1/repos/kwila/kiosk/releases?limit=1` and compares the release `tag_name` against the build-time `version` variable 3. **Download** — If versions differ, finds the asset matching `runtime.GOARCH` (e.g. `kiosk-arm64`), downloads to a temp file in the same directory 4. **Replace** — `chmod +x`, then atomic `os.Rename` over the running binary 5. **Restart** — Calls `os.Exit(0)`. Since the systemd service has `Restart=always`, it comes back up running the new version All errors are logged, never fatal — retries next day. ## Build-time version injection The `justfile` now injects version via ldflags: ``` go build -ldflags "-X main.version=v0.2.4" -o kiosk . ``` Defaults to `dev` for local builds. CI should pass the release tag. ## Changes - **`updater.go`** — Core auto-update logic (scheduler, API check, download, replace, exit) - **`updater_test.go`** — 8 tests with httptest mock server covering all paths - **`main.go`** — Wire in `StartAutoUpdater()` call - **`justfile`** — Add `version` variable, inject via `-ldflags` in build recipe, expand test recipe to `./...` ## Tests | Test | Covers | |---|---| | SkipsWhenVersionMatches | No-op when already on latest | | DownloadsAndReplaces | Happy path: download, replace, exit | | HandlesAPIError | 500 from releases API | | HandlesEmptyReleases | Empty releases array | | HandlesMissingArchAsset | No matching arch in assets | | HandlesConnectionError | Unreachable API | | HandlesBadJSON | Malformed response | | HandlesDownloadError | 404 on binary download |
- Add updater.go with daily 2am scheduler that checks Forgejo releases API
- Compare running version (set via ldflags) against latest release tag
- Download matching arch binary, atomic-rename over current, exit for systemd restart
- Add 8 tests covering: version match skip, download+replace, API errors,
  empty releases, missing arch, connection errors, bad JSON, download failures
- Inject version via ldflags in justfile build recipe
- Expand test recipe to run all packages (./... instead of ./deploy/...)

Co-authored-by: Shelley <shelley@exe.dev>
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
kwila/kiosk!19
No description provided.