Browse Source

Fix SpoolBuddy update check comparing against GitHub releases instead of backend version

  The SpoolBuddy daemon update endpoint fetched GitHub releases and compared
  them against device.firmware_version, which always showed "up to date"
  because the comparison source was wrong. Now compares directly against
  APP_VERSION from the running backend, so a daemon at 0.2.3b1 correctly
  sees 0.2.3 as an available update.
maziggy 2 months ago
parent
commit
511ece791a

+ 1 - 0
CHANGELOG.md

@@ -5,6 +5,7 @@ All notable changes to Bambuddy will be documented in this file.
 ## [0.2.3.b1] - Unreleased
 
 ### Fixed
+- **SpoolBuddy Update Check Always Shows "Up to Date"** — The SpoolBuddy daemon update check compared the device's firmware version against GitHub releases instead of the running Bambuddy backend version. This meant the check could incorrectly report "up to date" even when the daemon was behind. Fixed by comparing directly against `APP_VERSION` from the backend config.
 - **Virtual Printer Proxy A1 Printing Fails** ([#757](https://github.com/maziggy/bambuddy/issues/757)) — BambuStudio could not send prints to A1 (and potentially P1S) virtual printers in proxy mode. The slicer connects to undocumented proprietary ports 2024-2026 on these models, which the proxy was not forwarding, causing BambuStudio to show an access code dialog instead of printing. Added transparent TCP pass-through proxying for ports 2024-2026. These ports are silently ignored on models that don't use them (X1C, H2C, P2S). Reported by @Utility9298.
 - **Spool Assignment on Empty AMS Slots** ([#784](https://github.com/maziggy/bambuddy/issues/784)) — Empty AMS slots (no physical spool detected) showed "Assign Spool" and "Configure" buttons in the hover popup. Assigning a spool to an empty slot created a stuck state because no "Unassign" button is available for empty slots. Removed both buttons from empty AMS and HT AMS slot popups. External spool holders are unaffected. Reported by @RosdasHH.
 

+ 8 - 52
backend/app/api/routes/spoolbuddy.py

@@ -573,15 +573,12 @@ async def update_display_settings(
 @router.get("/devices/{device_id}/update-check")
 async def check_daemon_update(
     device_id: str,
-    include_beta: bool = False,
     db: AsyncSession = Depends(get_db),
     _: User | None = RequirePermissionIfAuthEnabled(Permission.INVENTORY_READ),
 ):
-    """Check if a newer daemon version is available on GitHub."""
-    import httpx
-
-    from backend.app.api.routes.updates import is_newer_version, parse_version
-    from backend.app.core.config import GITHUB_REPO
+    """Check if the SpoolBuddy daemon needs updating to match the Bambuddy backend version."""
+    from backend.app.api.routes.updates import is_newer_version
+    from backend.app.core.config import APP_VERSION
 
     result = await db.execute(select(SpoolBuddyDevice).where(SpoolBuddyDevice.device_id == device_id))
     device = result.scalar_one_or_none()
@@ -590,52 +587,11 @@ async def check_daemon_update(
 
     current = device.firmware_version or "0.0.0"
 
-    try:
-        async with httpx.AsyncClient() as client:
-            response = await client.get(
-                f"https://api.github.com/repos/{GITHUB_REPO}/releases?per_page=20",
-                headers={"Accept": "application/vnd.github.v3+json"},
-                timeout=10.0,
-            )
-            response.raise_for_status()
-            releases = response.json()
-
-            release_data = None
-            for release in releases:
-                tag = release.get("tag_name", "")
-                if include_beta:
-                    release_data = release
-                    break
-                else:
-                    parsed = parse_version(tag)
-                    if parsed[4] == 0:  # is_prerelease == 0
-                        release_data = release
-                        break
-
-            if not release_data:
-                return {
-                    "current_version": current,
-                    "latest_version": None,
-                    "update_available": False,
-                    "release_url": None,
-                }
-
-            latest = release_data.get("tag_name", "").lstrip("v")
-            return {
-                "current_version": current,
-                "latest_version": latest,
-                "update_available": is_newer_version(latest, current),
-                "release_url": release_data.get("html_url"),
-            }
-    except Exception as e:
-        logger.warning("Failed to check for daemon updates: %s", e)
-        return {
-            "current_version": current,
-            "latest_version": None,
-            "update_available": False,
-            "release_url": None,
-            "error": str(e),
-        }
+    return {
+        "current_version": current,
+        "latest_version": APP_VERSION,
+        "update_available": is_newer_version(APP_VERSION, current),
+    }
 
 
 @router.post("/devices/{device_id}/update")

+ 2 - 3
frontend/src/api/client.ts

@@ -4992,7 +4992,6 @@ export interface DaemonUpdateCheck {
   current_version: string;
   latest_version: string | null;
   update_available: boolean;
-  release_url: string | null;
 }
 
 // SpoolBuddy API
@@ -5027,8 +5026,8 @@ export const spoolbuddyApi = {
       body: JSON.stringify({ brightness, blank_timeout: blankTimeout }),
     }),
 
-  checkDaemonUpdate: (deviceId: string, includeBeta?: boolean) =>
-    request<DaemonUpdateCheck>(`/spoolbuddy/devices/${deviceId}/update-check?include_beta=${includeBeta ?? false}`),
+  checkDaemonUpdate: (deviceId: string) =>
+    request<DaemonUpdateCheck>(`/spoolbuddy/devices/${deviceId}/update-check`),
 
   triggerUpdate: (deviceId: string) =>
     request<{ status: string; message: string }>(`/spoolbuddy/devices/${deviceId}/update`, {

+ 1 - 1
frontend/src/components/spoolbuddy/SpoolBuddyLayout.tsx

@@ -61,7 +61,7 @@ export function SpoolBuddyLayout() {
   // Auto-check for SpoolBuddy daemon updates
   const { data: updateCheck } = useQuery({
     queryKey: ['spoolbuddy-update-check', device?.device_id],
-    queryFn: () => device ? spoolbuddyApi.checkDaemonUpdate(device.device_id, true) : Promise.resolve(null),
+    queryFn: () => device ? spoolbuddyApi.checkDaemonUpdate(device.device_id) : Promise.resolve(null),
     enabled: !!device,
     refetchInterval: 5 * 60 * 1000, // re-check every 5 minutes
     staleTime: 4 * 60 * 1000,

+ 1 - 1
frontend/src/pages/spoolbuddy/SpoolBuddySettingsPage.tsx

@@ -509,7 +509,7 @@ function UpdatesTab({ device }: { device: SpoolBuddyDevice }) {
 
   const { data: updateResult, isLoading: checking, refetch } = useQuery({
     queryKey: ['spoolbuddy-update-check', device.device_id],
-    queryFn: () => spoolbuddyApi.checkDaemonUpdate(device.device_id, true),
+    queryFn: () => spoolbuddyApi.checkDaemonUpdate(device.device_id),
     staleTime: 4 * 60 * 1000,
   });
 

File diff suppressed because it is too large
+ 0 - 0
static/assets/index-C2JN3KVZ.js


File diff suppressed because it is too large
+ 0 - 0
static/assets/index-Dn6SXRdj.js


+ 1 - 1
static/index.html

@@ -23,7 +23,7 @@
 
     <!-- Splash screens for iOS -->
     <link rel="apple-touch-startup-image" href="/img/android-chrome-512x512.png" />
-    <script type="module" crossorigin src="/assets/index-BE5xwBJ5.js"></script>
+    <script type="module" crossorigin src="/assets/index-Dn6SXRdj.js"></script>
     <link rel="stylesheet" crossorigin href="/assets/index-CJ-drcFM.css">
   </head>
   <body>

Some files were not shown because too many files changed in this diff