feat(settings): apply releases and manage versions from the console - #564
Open
dviejokfs wants to merge 2 commits into
Open
feat(settings): apply releases and manage versions from the console#564dviejokfs wants to merge 2 commits into
dviejokfs wants to merge 2 commits into
Conversation
The console already told operators a newer release existed and then left them to SSH in. This adds the missing action to that banner: an "Update now" button that downloads the release, verifies its published SHA-256, swaps the binary and exits so the supervisor restarts temps on it. The download/verify/swap machinery is reused from `temps upgrade`. What is new is deciding honestly whether the process will actually come back, and reporting the result of an operation that kills the process that started it: - Supervision is detected up front (systemd `INVOCATION_ID`, launchd `XPC_SERVICE_NAME`, container markers). Containers and unsupervised processes are refused with the reason and the command to run instead, rather than exiting into permanent downtime. - The attempt is journalled to `<data_dir>/self-update.json` before the exit and resolved on the next boot by comparing the running version to the target, so the console can report "updated to X" or "came back on the old version" instead of a spinner. - The new binary must answer `--version` before it is moved into place, and the replaced one is kept as a `.bak` sibling for rollback. - A missing checksum fails closed here, unlike the interactive CLI where a human can judge. Two independent off switches, since an operator may want to forbid this entirely: - `temps serve --disable-self-update` — bootstrap flag, cannot be cleared over the API. - `self_update.enabled` in settings — runtime toggle in Settings → Platform. The flag wins. Gated on a new `platform:update` permission rather than `settings:write`: replacing the running binary and dropping in-flight requests is a different class of action from editing a config value, so custom roles scoped to settings must not inherit it. Every attempt is audited as `PLATFORM_UPDATE_STARTED` before the process exits. Adds `GET/POST /settings/update` with CLI parity as `temps platform update status|apply`.
… restart Three changes on top of the console update action. **Installing no longer requires a supervisor.** A missing systemd/launchd was treated as a blocker, so the one case where an operator most wants help — a temps they start themselves — got a refusal. Installing the binary was always possible there; only the restart wasn't. The two are now separate: every permitted install proceeds, and `restart_mode` says up front whether temps restarts itself (`automatic`) or keeps serving the old binary until the operator restarts it (`manual`). Containers move the same way, from refusal to an install plus a caveat that recreating the container reverts to the image. The journal gained `installed_pending_restart` for that state. It resolves to `succeeded` when the new version finally boots, and — importantly — stays put rather than failing when the old one boots again, because a restart the operator hasn't done yet is not a failed update. **A Version page** under Settings → Version: the running version, the channel and where it came from, the supervisor and what a restart will do, the binary path, an explicit "Check for updates" that queries the release API instead of waiting for the periodic pass, and the outcome of the last attempt. The platform-updates toggle moves here from the Platform page rather than being duplicated. **Release channels are selectable.** `self_update.channel` pins stable, beta or nightly; unset keeps the previous behaviour of inferring from the running version tag. The background notifier re-reads it every pass, so switching takes effect without a restart. A check that finds nothing newer now clears the shared notice — otherwise moving a nightly box onto stable would leave the old nightly banner up forever, since stable is older and could never overwrite it. Adds `POST /settings/update/check`, with CLI parity as `temps platform update check` and `temps platform update channel [name|auto]`.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
The console already told operators a newer release existed, then left them to SSH in. This adds the missing action to that banner — an Update now button — plus a Settings → Version page for what's running, which channel it tracks, and an explicit update check.
How it works
The download / checksum-verify / atomic-swap machinery is reused from the existing
temps upgrade. The genuinely new problems were deciding whether the process will come back, and reporting the result of an operation that kills the process that started it.Install and restart are separate
restart_modeautomaticmanualA missing supervisor is deliberately not a blocker. Installing was always possible there — only the restart wasn't — so refusing helped nobody. Containers behave the same way, with a caveat that recreating the container reverts to the image's binary.
Reporting an outcome across a restart
The attempt is journalled to
<data_dir>/self-update.jsonbefore the exit and resolved on the next boot by comparing the running version against the target. So the console says "updated to X" or "came back on the old version", never an indefinite spinner.installed_pending_restartstays put rather than degrading tofailedwhen the old binary boots again — a restart you haven't done yet is not a failed update.Safety
--versionbefore it's moved into place (catches wrong libc, corrupt extraction)..baksibling for rollback, path surfaced in the UI.Turning it off
Two independent switches:
temps serve --disable-self-update— bootstrap flag, cannot be cleared over the API.self_update.enabled— runtime toggle in Settings → Version.The flag wins, and the UI says so rather than showing a toggle that does nothing.
Permission
Gated on a new
platform:updatepermission, notsettings:write. Replacing the running binary and dropping in-flight requests is a different class of action from editing a config value, so custom roles scoped to settings must not inherit it. Granted toAdminandPlatformAdminby default. Every attempt is audited asPLATFORM_UPDATE_STARTEDbefore the process exits.Release channels
self_update.channelpinsstable/beta/nightly; unset keeps the existing behaviour of inferring from the running version tag. The notifier re-reads it each pass, so switching takes effect without a restart. A check that finds nothing newer now clears the shared notice — otherwise moving a nightly box onto stable would leave the stale nightly banner up forever, since stable is older and could never overwrite it.API
GET /settings/updatePOST /settings/updateversionpin)POST /settings/update/checkCLI parity:
temps platform update status | apply | check | channel [name\|auto].Evidence
Run against a live server on a dev slot. All four capability states:
Permission gating — a custom key holding only
settings:read:Real end-to-end install, automatic mode (simulated systemd) — downloaded a real 93.5 MB release:
Then restarting deliberately on the old binary produced an honest failure rather than a false success:
{ "status": "failed", "error": "Restarted on v0.1.0-beta.1 instead of v0.1.0-beta.55. The binary swap did not take effect ... The replaced binary was kept at .../temps.bak." }Real end-to-end install, manual mode (no supervisor) — the case this PR unblocks:
Channel switching via CLI:
UI verified in-browser: banner + button, confirm dialog (enabled and blocked variants), the Version page, and the pending-restart result card.
Checks
temps-core303 passing,temps-auth330 passingcargo clippy --all-targets -- -D warningsclean ontemps-core,temps-auth,temps-config,temps-clitsc --noEmitclean forweb/and no new errors inapps/temps-cli(5 pre-existing errors onmaininproviders/notifications/openapi-ts.config.tsare untouched)Notes for review
temps agentare unaffected and still upgrade separately.temps proxyon its old binary; the capability surfaces that as a caveat before the click.