feat(update): release-aware update detection + apply (phase D)

Make the WebUI updater work off release versions, not git commits, in release mode
(git/local paths untouched):

- webui_system_update.sh: a release branch resolves latest_version from the channel
  manifest (lpReleaseLatestVersion), computes update_available via lpVersionGt vs
  the local VERSION, reuses the same throttle + the same update_status.json schema
  (source="release"); reuses last-known latest when throttled so the badge
  doesn't flicker.
- check_update.sh webuiRunUpdate: a release branch version-compares and, if newer,
  lpFetchRelease (download + checksum-verify) the new tarball + dockerInstallApp
  redeploy + regen. No config-backup dance — lpFetchRelease replaces only the
  install tree; configs/logs are in the separate system tree.

Verified against a local server: latest-version read + the no-update / update-
available decision (0.2.0==0.2.0 no; 0.3.0>0.2.0 yes). Remaining: route the
reset/reinstall recovery paths through the release fetch.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
This commit is contained in:
librelad 2026-05-25 18:13:09 +01:00
parent 584d330636
commit acfe7d6bfa
2 changed files with 64 additions and 1 deletions

View File

@ -25,10 +25,37 @@ webuiRunUpdate()
return 1
fi
if [[ "$git_updates" != "true" ]]; then
isError "Git updates are disabled (CFG_GIT_UPDATES). Enable them to update from the WebUI."
isError "Updates are disabled (CFG_GIT_UPDATES). Enable them to update from the WebUI."
return 1
fi
# Release mode: version-compare the channel's latest against the local VERSION
# and, if newer, fetch + verify the new tarball and redeploy. No config backup
# dance — lpFetchRelease replaces only the install tree; configs/logs live in
# the separate system tree.
if [[ "$install_mode" == "release" ]]; then
webuiSystemUpdateCheck "force"
local cur lat
cur=$(tr -d ' \t\n\r' < "$script_dir/VERSION" 2>/dev/null)
lat=$(lpReleaseLatestVersion 2>/dev/null)
if [[ -z "$lat" ]]; then
isError "Could not reach the release server ($(lpReleaseBaseUrl))."
return 1
fi
if ! lpVersionGt "$lat" "$cur"; then
isSuccessful "LibrePortal is already up to date (v${cur})."
return 0
fi
isNotice "Update found — v${cur} → v${lat}. Fetching the verified release..."
lpFetchRelease "$lat" || { isError "Release fetch failed — install unchanged."; return 1; }
isNotice "Redeploying LibrePortal with the new version..."
dockerInstallApp "libreportal"
WEBUI_UPDATER_FORCE=1 webuiLibrePortalUpdate
webuiSystemUpdateCheck "force"
isSuccessful "LibrePortal has been updated to v${lat}."
return 0
fi
# Credential guard — gitReset()/gitCheckGitDetails() would otherwise prompt
# for missing git details and hang the task forever. Fail fast with a clear
# message instead.

View File

@ -98,6 +98,42 @@ EOF
fi
}
# Release mode: compare the local VERSION against the channel's published
# latest.json (no git). Same throttle + same JSON schema, source="release".
if [[ "$install_mode" == "release" ]]; then
local latest_version="$current_version" rel_error=""
local do_fetch="false"
if [[ "$force_flag" == "force" || ! -f "$stamp_file" ]]; then
do_fetch="true"
else
local _now _last; _now=$(date +%s); _last=$(stat -c '%Y' "$stamp_file" 2>/dev/null || echo 0)
(( _now - _last >= fetch_interval )) && do_fetch="true"
fi
if [[ "$do_fetch" == "true" ]] && declare -f lpReleaseLatestVersion >/dev/null 2>&1; then
local _lv; _lv=$(lpReleaseLatestVersion 2>/dev/null)
if [[ -n "$_lv" ]]; then
latest_version="$_lv"
runAsManager touch "$stamp_file" 2>/dev/null || touch "$stamp_file" 2>/dev/null
else
rel_error="Could not reach the update server."
fi
elif [[ -f "$final_file" ]]; then
# Throttled: reuse the last-known latest so the badge doesn't flicker.
local _prev; _prev=$(grep -oE '"latest_version"[^,]*' "$final_file" 2>/dev/null | head -1 | sed -E 's/.*"([^"]*)"$/\1/')
[[ -n "$_prev" ]] && latest_version="$_prev"
fi
local update_available="false"
if declare -f lpVersionGt >/dev/null 2>&1 && lpVersionGt "$latest_version" "$current_version"; then
update_available="true"
fi
local can_update="false"
[[ "$git_updates" == "true" ]] && can_update="true"
_webuiWriteUpdateStatus "$update_available" "$can_update" \
"$current_version" "$latest_version" \
"" "" "0" "0" "${CFG_RELEASE_CHANNEL:-stable}" "release" "$rel_error"
return 0
fi
# Not a git working copy, or a deliberately local install: we can't compare
# against an upstream, so report "managed manually" rather than an error.
if [[ ! -d "$repo_dir/.git" || "$install_mode" == "local" ]]; then