diff --git a/backend/app/services/slicer_api.py b/backend/app/services/slicer_api.py index 4317f0d0a..de8fabd52 100644 --- a/backend/app/services/slicer_api.py +++ b/backend/app/services/slicer_api.py @@ -199,10 +199,22 @@ def _upload_size_rejection(response: httpx.Response, model_size_bytes: int | Non f"{common} Raise it by setting MAX_MODEL_UPLOAD_MB on the slicer-api service and " f"restarting it. Sidecar said: {detail}" ) + # Naming the service in the compose commands is not a style choice. The + # Bambu Studio sidecar sits behind `profiles: [bambu]`, and a bare + # `docker compose pull` silently skips every profile-gated service — so the + # update this message asks for was a no-op for exactly the users who need + # it, and `restart: unless-stopped` kept the old container serving (#2802, + # second round). Naming a service enables its profile implicitly, for both + # pull and up. `--profile bambu` would also work, but on an OrcaSlicer-only + # host it downloads the 220 MB Bambu image and then *starts* a sidecar the + # user never asked for. return ( - f"{common} This sidecar image predates the configurable cap and is fixed at 100 MB — " - "update it with 'cd slicer-api/ && docker compose pull && docker compose up -d', which " - "raises the default and adds MAX_MODEL_UPLOAD_MB for going higher still. " + f"{common} This sidecar image predates the configurable cap and is fixed at 100 MB. " + "Update it with 'cd slicer-api/ && docker compose pull orca-slicer-api && " + "docker compose up -d orca-slicer-api', substituting 'bambu-studio-api' if that is the " + "sidecar you slice with. Name the service in both commands — a bare 'docker compose pull' " + "skips the Bambu Studio sidecar, because it sits behind a compose profile. The new image " + "defaults to 512 MB and adds MAX_MODEL_UPLOAD_MB for going higher still. " f"Sidecar said: {detail}" ) diff --git a/backend/tests/unit/test_slicer_upload_size_rejection.py b/backend/tests/unit/test_slicer_upload_size_rejection.py index 005f31806..46ff5c3d7 100644 --- a/backend/tests/unit/test_slicer_upload_size_rejection.py +++ b/backend/tests/unit/test_slicer_upload_size_rejection.py @@ -140,6 +140,33 @@ class TestTheMessageIsActionable: assert "docker compose pull" in message assert "100 MB" in message + @pytest.mark.asyncio + async def test_the_update_command_names_the_service(self): + """A bare ``docker compose pull`` does not update the Bambu sidecar. + + ``bambu-studio-api`` is declared with ``profiles: [bambu]``, and compose + skips profile-gated services unless the profile is enabled or the + service is named. The advice this message used to give was therefore a + no-op for Bambu Studio users -- they pulled, saw "up to date", restarted + into the same 100 MB image and came back to the issue (#2802). + + Both commands are checked: pulling the right image is useless if the + ``up -d`` that follows leaves the old container running. + """ + svc = _service(_responder(500, {"message": "File too large"})) + + with pytest.raises(SlicerInputError) as excinfo: + await svc.slice_with_profiles(**SLICE_ARGS) + + message = str(excinfo.value) + assert "docker compose pull orca-slicer-api" in message + assert "docker compose up -d orca-slicer-api" in message + assert "bambu-studio-api" in message + # The bare forms must not appear at all -- a reader who copies the first + # command they see must not get the one that silently does nothing. + assert "docker compose pull &&" not in message + assert "docker compose up -d'" not in message + @pytest.mark.asyncio async def test_a_current_sidecar_is_told_which_variable_to_set(self): """Once the image is current, the fix is one env var, not another pull.""" diff --git a/slicer-api/README.md b/slicer-api/README.md index 605013067..1f203a74d 100644 --- a/slicer-api/README.md +++ b/slicer-api/README.md @@ -84,13 +84,31 @@ flipped back to `ghcr.io/afkfelix/orca-slicer-api`. ## Updating +OrcaSlicer only (the default): + ```bash docker compose pull +docker compose up -d +``` + +With the Bambu Studio sidecar — the profile flag belongs on **both** +commands: + +```bash +docker compose --profile bambu pull docker compose --profile bambu up -d ``` -That's it — Compose pulls the current `:latest` (or whatever -`SIDECAR_TAG` you've pinned to) and recreates the containers. +`bambu-studio-api` sits behind `profiles: [bambu]`, and a bare +`docker compose pull` skips profile-gated services silently: it reports +success, `restart: unless-stopped` keeps the old container serving, and +you stay on the old image no matter how often you repeat it. To update +one sidecar only, name it — `docker compose pull bambu-studio-api && +docker compose up -d bambu-studio-api` — which enables its profile +implicitly. + +Compose pulls the current `:latest` (or whatever `SIDECAR_TAG` you've +pinned to) and recreates the containers. To roll back to the sidecar that shipped with a previous Bambuddy release, set `SIDECAR_TAG=bambuddy-X.Y.Z` in `.env` and re-run the two diff --git a/slicer-api/docker-compose.yml b/slicer-api/docker-compose.yml index 35bdbd005..a814f540c 100644 --- a/slicer-api/docker-compose.yml +++ b/slicer-api/docker-compose.yml @@ -17,6 +17,11 @@ # docker compose up -d # starts OrcaSlicer only # docker compose --profile bambu up -d # starts both # +# Updating: `docker compose pull` skips profile-gated services, so a bare +# pull silently leaves bambu-studio-api on its old image (and restart: +# unless-stopped keeps it serving). Use `docker compose --profile bambu pull`, +# or name the service: `docker compose pull bambu-studio-api`. +# # First start pulls pre-built images from GHCR (~110 MB OrcaSlicer, # ~220 MB BambuStudio). No local build, no git in the BuildKit worker, # works on QNAP / Synology / Container Station out of the box.