v2.12.0 β auto-update that actually works - #50
Merged
Conversation
`auto_update_enabled` has existed for a while and could never have worked. Three
independent reasons, each sufficient on its own:
1. THE VERSION CHECK USED A STRING COMPARE. "2.11.0" > "2.9.0" is False (at
index 2, "1" < "9"), so every x.9 -> x.10+ upgrade was invisible. The reverse
comparison was True, so the check could have offered a DOWNGRADE as an update.
Present in both routes/admin.py (fixed in 2.11.0) and tasks/auto_update.py
(fixed here β the worker's copy, which is the one that actually schedules).
2. NOTHING APPLIED THE UPDATE. scripts/auto-update.sh had to be installed in the
host crontab by hand and nothing shipped it, so the signal file the worker
wrote was never read.
3. EVEN WHEN TRIGGERED, IT DID NOT UPDATE. That script ran `docker compose up -d
--build` against the source already on disk β a rebuild of the same version.
## waxflow-updater
A container cannot restart itself, so applying an update needs host-side Docker
access. This is the only place WaxFlow asks for it, and it is constrained:
* network_mode: none. It never downloads anything. The worker (network, no
socket) decides the target; the DAEMON fetches image layers when asked over
the socket. Nothing with host-root access talks to the internet.
* Rollback. Health-checks the API afterwards and restores the previous tag if the
new version does not come up. This runs unattended at 3am by default, and an
update that half-applies and is never noticed is worse than one that never ran.
* The target tag comes from the GitHub API and is refused unless it matches
semver, so nothing unexpected reaches `docker pull`.
Verified against a live daemon: a malformed tag ("latest; rm -rf /") is refused
before any docker call, and a valid-but-nonexistent tag fails with the running
stack untouched.
## Published images
Updating is now a pull, not a rebuild. The rebuild path took ~25 minutes for the
worker image on a Synology NAS and wedged the Docker daemon once β unacceptable
for an unattended job. release-images.yml publishes amd64+arm64 images to GHCR on
each release and refuses to publish if the tag disagrees with VERSION. `build:`
blocks remain, so `--build` still works offline and for forks.
auto_update_enabled now defaults to 1 for NEW installs; INSERT OR IGNORE means
existing deployments keep whatever they already had.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HmUiLHPmKoz215WAWV5eHe
Auto-update pulls prebuilt images instead of rebuilding from source. Without this workflow the compose file would reference images that do not exist, so it is a hard dependency of the updater, not an optimisation. Builds linux/amd64 (Synology/Intel NAS) and linux/arm64 (Apple silicon, Pi) on each published release, and refuses to publish when the tag disagrees with the VERSION file β an image whose baked /app/VERSION contradicts its tag would make the update check oscillate forever. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HmUiLHPmKoz215WAWV5eHe
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.
auto_update_enabledhas existed for a while. It could never have worked β three independent reasons, each sufficient on its own.1. The version check was a string compare
"2.11.0" > "2.9.0"isFalseβ at index 2,"1" < "9". So every x.9 β x.10+ upgrade was invisible. Worse, the reverse comparison wasTrue, meaning the check could have offered a downgrade as an update.Present in two places.
routes/admin.pywas fixed in 2.11.0;tasks/auto_update.pyβ the copy that actually schedules β was not. Fixed here, with 7 tests pinning the behaviour.2. Nothing applied the update
scripts/auto-update.shhad to be installed in the host's crontab by hand. Nothing shipped it, so the signal file the worker wrote was never read by anything.3. Even when triggered, it didn't update
That script ran
docker compose up -d --buildagainst the source already on disk β a rebuild of the same version.waxflow-updaterA container cannot restart itself, so applying an update needs host-side Docker access. This is the only place WaxFlow asks for it, and it is deliberately constrained:
network_mode: none. It never downloads anything. The worker (network, no socket) decides the target version; the Docker daemon fetches image layers when asked over the socket. Nothing with host-root access talks to the internet.docker pull.Verified against a live Docker daemon:
latest; rm -rf /Don't want to grant socket access? Delete the service β everything else keeps working, and the UI still tells you when a release is available.
Published images
Updating becomes a pull, not a rebuild. The rebuild path took ~25 minutes for the worker image on a Synology NAS and wedged the Docker daemon once; that is not acceptable for an unattended 3am job.
release-images.ymlpublishesghcr.io/<owner>/waxflow-{api,worker,web}for amd64 + arm64 on each release, and refuses to publish if the tag disagrees withVERSIONβ an image whose baked/app/VERSIONcontradicts its tag would make the update check oscillate forever.build:blocks remain, sodocker compose up -d --buildstill works offline and for forks (WAXFLOW_REGISTRY).Changed
auto_update_enableddefaults to1for new installs only.INSERT OR IGNOREmeans existing deployments keep whatever they already had β nobody gets unattended updates switched on behind their back.Tests
17 pass (10 sync_gate + 7 version compare), including the exact regression and a guard that a downgrade is never offered.
π€ Generated with Claude Code
https://claude.ai/code/session_01HmUiLHPmKoz215WAWV5eHe