Say which Colonizer this is, and when a newer one is out - #110
Merged
Merged
Conversation
Part of #45. The check and the version it compares; applying an update is not here. #45 opens with "there are no versions to compare", which has since stopped being true: v0.1.0 to v0.1.4 are tagged and Cargo.toml tracks them. What was still missing is that a build records nothing about where it came from, so "is there an update?" had no answer. build.rs stamps `git describe --tags --always --dirty`, the commit, and a build time. Everything degrades rather than fails: a source package with no .git compiles and reports the crate version with no commit. The timestamp honours SOURCE_DATE_EPOCH, because an unconditional clock reading would give every rebuild a different binary, which is what #89/#105's attestation needs not to happen. GET /api/version returns that. GET/PUT /api/update carries the check: on by default, a switch in Settings, and COLONIZER_UPDATE_CHECK=0 to keep it off from the environment. It asks GitHub a minute after start and every six hours, only while it is on — switched off it makes no request and forgets the last answer, so no banner lingers for a check that is not running. Drafts and prereleases are ignored. COLONIZER_RELEASES_URL points it elsewhere for a fork or a test. A build after a tag is measured against the tag it contains, as the issue asks: v0.1.4-12-gabc1234 is told about v0.1.5 and not about v0.1.4. A version that cannot be placed is never told it is behind — better silence than crying wolf. Settings gains an Updates section: the installed version, its commit, whether it was built from a modified tree, and the release notes when there is a newer one. It says plainly that updating means re-running the installer for now. Checked in a browser against the mock: the section reads "v0.1.4 available", the banner shows the notes, and switching the check off replaces it with "the Mothership makes no request to GitHub about releases". The mock now clears its cached release on switch-off too, which it did not before, so it no longer shows a banner the real backend would have dropped. Not done here, deliberately: applying the update. It wants the versioned app directory from #90/#104 first, so an old release stays readable while running colonies still mount plugins out of it.
7 tasks
ParallelEntrepreneur
added a commit
that referenced
this pull request
Sep 18, 2026
) * Update in place, without taking plugins away from running colonies Closes #45. #110 did the check; this applies it. It runs scripts/install-release.sh from inside the app rather than reimplementing the download, the checksum and the swap. That installer already unpacks beside the running app and moves the symlink with one rename, so a failure part-way leaves the running version exactly as it was — which is the "a build that fails leaves the running version untouched" line, for free. The proposal said to fetch the tag into a clone the mothership owns and build it. Prebuilt releases landed since (#74), so there is a verified archive to install and no cargo, npm or node needed on the machine. install.sh now ships the installer into dist/ so an installed mothership has a local copy, instead of downloading a script to execute. The part that would have lost work: colonies mount vendored plugins straight out of the app directory the mothership started from, because resolve_assets canonicalises the symlink away — and the installer deletes the slot it replaces. Applying an update under a running colony would take its plugins with it. So the installer learned COLONIZER_KEEP_PREVIOUS=1, each session records the directory its mounts resolved through, and a kept directory is swept at the next start once no live colony still names it. A person running the installer by hand keeps today's behaviour. Publishing colonies hold the update, and are named in the refusal: the microVM is already gone and the host is committing and pushing, so interrupting it leaves the colony failed with its pull request unopened. A colony that is only working does not hold it — it is detached, and recover reconnects it, which is the whole reason this can be done at all. The restart is an exec of the app symlink's binary, after the live map is told this mothership is going and the mesh children are killed so the new process can take their ports. Checked by driving the real installer on this machine with fake releases: with KEEP_PREVIOUS the previous slot survives an update and its plugin file is still readable, and without it the slot is removed exactly as before. The UI was driven against the mock: Update to v0.1.4 goes to Installing, then Restarting with "colonies keep their microVMs and reconnect" and a line per colony. Not exercised: a real release installed by a running mothership, and the exec itself. Both need two real releases and an installed app. * Say how far behind the running build is, and which commit it is The pane showed a version and a date. It now also says how old the build is relative to the release being offered — "Released 9/18/2026, 12 days after the build you are running" — because a version number alone does not tell you whether you are a day or a season behind. The commit is shown beside the build time, and a development build says which release it came after. The gap is computed from the build time and the release date, so it is honest about the build rather than about the tag: someone running a build from a checkout sees how far that checkout has fallen behind. --------- Co-authored-by: Nick <40026523+Nick-CHI@users.noreply.github.com>
This was referenced Sep 18, 2026
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.
Part of #45 — the check, and the version it compares against. Applying an update is not in this PR; see the end.
The issue's premise has moved
#45 opens with "There are no versions to compare." That stopped being true:
v0.1.0–v0.1.4are tagged andCargo.tomltracks them. What was still missing is the next sentence — a build records nothing about where it came from, so "is there an update?" had no answer.What this adds
build.rsgit describe --tags --always --dirty, the commit, and a build timeGET /api/version{version, commit, dirty, built_at, release}GET/PUT /api/updateCOLONIZER_UPDATE_CHECK=0from the environmentDegrades rather than fails. A source package with no
.gitstill compiles and reports the crate version with no commit.built_athonoursSOURCE_DATE_EPOCH. An unconditional clock reading would give every rebuild a different binary — precisely what the attestation work in #89/#105 needs not to happen.The comparison rule
A build after a tag is measured against the tag it contains, as the issue asks:
v0.1.4-12-gabc1234is told aboutv0.1.5and not aboutv0.1.4. A version that cannot be placed is never told it is behind — silence beats crying wolf. Drafts and prereleases are ignored.Eight tests cover it, including
v0.9.0→v0.10.0, which string ordering gets wrong."Off means no request"
That acceptance criterion is structural, not incidental: the gate is in the loop before anything touches the network. Switching off also forgets the last answer, so no banner lingers for a check that is no longer running.
Verified
Build stamping, on this machine:
— an untagged shallow clone falling back to the crate version,
dirtycaught, andSOURCE_DATE_EPOCHhonoured.In a browser against the mock: the section reads "v0.1.4 available", the banner shows the notes, and switching the check off replaces it with "the Mothership makes no request to GitHub about releases". The mock also cleared its cached release on switch-off only after I fixed it — it previously kept showing a banner the real backend would have dropped.
Not exercised: a real request to the GitHub releases API, and the endpoints served by the real binary.
Acceptance in #45
Why applying is left out
It needs the versioned app directory and
currentsymlink from #90/#104 to land first, so an old release stays readable while running colonies still mount plugins out of it (sessions.rs,-v …:ro). Building that on top of today'srm -rf "$app"install would be the unsafe version of exactly what #45 asks for.