Add read-only OS package update status (apt) on the About page
New system package checks `apt list --upgradable` against the current package index (no apt update triggered) and the reboot-required marker file. Read-only - never installs or upgrades anything. Shown as a card on the About page with a manual "Check now" refresh. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
1d080904b0
commit
bdcf1ec60c
@@ -0,0 +1,63 @@
|
||||
// Package system checks the host OS for pending package updates. It never
|
||||
// installs or upgrades anything - read-only status only, using the
|
||||
// existing apt package index (no "apt update" is run automatically, since
|
||||
// that touches network/package state on every page load).
|
||||
package system
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// UpdateStatus summarizes pending OS package updates on a Debian/Ubuntu host.
|
||||
type UpdateStatus struct {
|
||||
Supported bool `json:"supported"` // false if apt isn't available (e.g. non-Debian host)
|
||||
UpgradableCount int `json:"upgradable_count"`
|
||||
Packages []string `json:"packages"`
|
||||
RebootRequired bool `json:"reboot_required"`
|
||||
CheckedAt time.Time `json:"checked_at"`
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// CheckAptUpdates lists upgradable packages from the current apt index
|
||||
// (`apt list --upgradable`) without refreshing it, and checks for the
|
||||
// standard Debian/Ubuntu reboot-required marker file.
|
||||
func CheckAptUpdates() UpdateStatus {
|
||||
status := UpdateStatus{CheckedAt: time.Now().UTC()}
|
||||
|
||||
if _, err := exec.LookPath("apt"); err != nil {
|
||||
status.Supported = false
|
||||
return status
|
||||
}
|
||||
status.Supported = true
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
||||
defer cancel()
|
||||
|
||||
cmd := exec.CommandContext(ctx, "apt", "list", "--upgradable")
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
status.Error = "cannot list upgradable packages: " + err.Error()
|
||||
return status
|
||||
}
|
||||
|
||||
scanner := bufio.NewScanner(strings.NewReader(string(out)))
|
||||
for scanner.Scan() {
|
||||
line := strings.TrimSpace(scanner.Text())
|
||||
if line == "" || strings.HasPrefix(line, "Listing...") {
|
||||
continue
|
||||
}
|
||||
status.Packages = append(status.Packages, line)
|
||||
}
|
||||
status.UpgradableCount = len(status.Packages)
|
||||
|
||||
if _, err := os.Stat("/var/run/reboot-required"); err == nil {
|
||||
status.RebootRequired = true
|
||||
}
|
||||
|
||||
return status
|
||||
}
|
||||
Reference in New Issue
Block a user