diff --git a/CHANGELOG.md b/CHANGELOG.md index b5baa46..ba07b46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,11 +13,14 @@ `gtstef/filebrowser:1.3.3-stable → 1.5.6-stable` (release notes read: nothing we use is removed — filebrowser drops `source.config.disableIndexing` and adds auth rate limiting; traefik 3.7 tightens StripPrefix, BasicAuth and `Host(*)`, none of which we configure; cloudflared deprecates `--transport-loglevel`, which we do not pass). -- **A release now moves a running file browser.** traefik and cloudflared were already recreated when their rendered - file changed (the image line is in it). The file browser was not: its bring-up skipped a running container and its - compose is rewritten only when storage changes, so a raised pin never reached an installed box. A running file - browser whose compose names another image now gets ONLY the `image:` line replaced (the mounts stay) and is - recreated once. `TestReconcileFileBrowserImage_MovesOnlyTheImage`, red-proved. +- **How a release moves the three containers** (measured on 9202, 2026-10-04): traefik and cloudflared are recreated by + the base-infra bring-up when their rendered file changes (the image line is in it); the file browser is recreated by + the web server's START-UP mount sync (`internal/web/server.go:302-304`), which renders the new image. On 9202 the + 0.291.0 start moved traefik (silent ≤ 1.9 s) and the file browser (≤ 1.5 s). **Correction, same day:** an earlier + line here said a raised file-browser pin "never reached an installed box" — wrong; the search for the sync's callers + missed the constructor. The added `reconcileFileBrowserImage` (a running file browser whose compose names another + image gets ONLY its `image:` line replaced and is recreated) is therefore a second net, not the only route. + `TestReconcileFileBrowserImage_MovesOnlyTheImage`, red-proved. - **`scripts/check-infra-pins.py`** — the monthly re-test's infrastructure half: newest upstream release per pin, in the same channel; BEHIND exits 1 (report only). diff --git a/controller/internal/stacks/infra.go b/controller/internal/stacks/infra.go index 74ddcb0..596cde9 100644 --- a/controller/internal/stacks/infra.go +++ b/controller/internal/stacks/infra.go @@ -416,9 +416,10 @@ func containerRunning(name string) bool { var composeImageLine = regexp.MustCompile(`(?m)^(\s*image:\s*)(\S+)\s*$`) // reconcileFileBrowserImage moves a RUNNING file browser to the pinned image (R-838, controller v0.291.0). Its compose -// file is owned by web.SyncFileBrowserMounts (the storage mounts), which runs only when storage changes — so before -// this, a release that raised FileBrowserImage never reached an installed box. Only the `image:` line is replaced; -// the mounts stay byte-for-byte. Same image (or no compose file) → nothing. Pinned by TestReconcileFileBrowserImage_*. +// file is owned by web.SyncFileBrowserMounts, which ALSO runs at every controller start (web/server.go) and renders the +// pinned image — that is the main route; this is a second net for a start-up sync that failed. Only the `image:` line +// is replaced; the mounts stay byte-for-byte. Same image (or no compose file) → nothing. Pinned by +// TestReconcileFileBrowserImage_*. func (m *Manager) reconcileFileBrowserImage(dir string) error { composePath := filepath.Join(dir, "docker-compose.yml") cur, err := os.ReadFile(composePath)