feat(update): stable/beta update channel; stable follows release tags (#684)

Adds auto_update.channel: stable follows the newest vX.Y.Z release tag
(detached HEAD; pre-releases and other tags ignored), beta follows main as
before. Nothing ever moves a device backwards: a checkout newer than the
newest release keeps following main (or stays put when detached) until a
release contains its commit. Legacy configs migrate to stable when they
reach a release. Update Code, the weekly updater's preflight, and the
verifier's rollback (back to old_ref: branch or detached release) all
honour the channel. General tab Update Channel select, GET/POST
/api/v3/system/update-channel, release-aware Overview banner and Tools git
panel. New installs default to stable.

Rig fix (ledpi): /system/check-update reports update_available: false when
the channel's action is none (a detached HEAD newer than the newest
release), matching Update Code; the Tools panel no longer calls every
detached HEAD "a release".

Merged with main through #687 (heartbeat verifier, #683 login, #688
plugin_catalog, #685 Tailwind build).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Chuck
2026-09-30 15:35:26 -04:00
committed by GitHub
co-authored by Claude Opus 5.5
parent 64c7289593
commit 7804ea8f69
21 changed files with 1499 additions and 50 deletions
+8
View File
@@ -476,9 +476,17 @@ def _load_general_partial():
except Exception:
logger.debug("Could not read auto-update status", exc_info=True)
auto_update_status = None
try:
# Local refs only: a page load must not wait on the network.
from web_interface import update_channel
update_channel_status = update_channel.resolve(update_channel.PROJECT_ROOT, main_config)
except Exception:
logger.debug("Could not read the update channel", exc_info=True)
update_channel_status = None
return render_template('v3/partials/general.html',
main_config=main_config,
auto_update_status=auto_update_status,
update_channel_status=update_channel_status,
web_login=_web_login_state())