mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-06 00:47:52 +00:00
fix(fleet): resolve version detection using package.json over stale generated constant (#410)
* fix(fleet): resolve stuck update states and improve update UX The fleet node update flow had several bugs: the in-memory update tracker never cleared terminal states (timeout, failed, completed), leaving nodes permanently stuck with no way to retry or dismiss. The Recheck button only re-fetched stale state without clearing it, and the POST trigger rejected retries with 409 even after timeout. Backend fixes: - Add DELETE endpoints (single node + batch) to clear tracker entries - Fix 409 race: detect expired timeouts and clear terminal states before re-triggering - Populate error messages in the tracker for timeouts and failures - Include error field in the update-status API response - Auto-expire completed entries after 60 seconds Frontend fixes: - Add retry (RotateCcw) and dismiss (X) buttons on failed/timed-out badges - Show error details via animated cursor hover (CursorFollow pattern) - Recheck button now batch-clears all terminal states before fetching - Recheck shows loading spinner and disables while checking - Extract NodeCardProps interface for readability * fix(fleet): detect update completion via process start time Remote nodes that cannot report their version (e.g. older builds) caused updates to always time out because completion detection relied solely on version comparison. The gateway now tracks the remote node's process start time from /api/meta and detects container restarts by comparing it across polls. Also extracts a createTracker() factory to eliminate repeated object construction across 5 call sites. * docs: add troubleshooting for first-update timeout on old nodes Adds a new troubleshooting entry explaining why the first remote update on nodes running pre-v0.40.0 always times out (neither version nor process start time can be detected). Documents the fix: dismiss, recheck, and confirm the node updated. Also adds a screenshot of the timed-out state with retry/dismiss buttons to the remote updates feature page. * fix(fleet): detect update completion via offline detection and error reporting The update completion detection relied on version change and process start time, both of which fail on nodes running older Sencho versions that report "unknown" and lack the startedAt field. This caused every update to time out after 5 minutes. Add three-signal detection: version change, process restart (startedAt), and offline/online detection (node went unreachable during update and came back). Also add a 90-second early failure heuristic for when the remote image pull fails silently, and surface pull errors from SelfUpdateService via /api/meta so the gateway can report them immediately. * fix(deps): bump vite to 8.0.5 to resolve high severity vulnerabilities Fixes GHSA-4w7w-66w2-5vf9, GHSA-v2wj-q39q-566r, GHSA-p9ff-h696-f583. * fix(deps): bump vite in backend lockfile to resolve audit failures Vitest pulls in vite as a transitive dependency. Bumps to 8.0.5. * fix(fleet): resolve version detection using package.json over stale generated constant resolveVersion() previously returned the build-time SENCHO_VERSION constant without checking the root package.json. When a branch fell behind a release-please version bump, the generated constant was stale, causing remote nodes to show "unknown" version and false "Update available" badges. The function now walks up to the root package.json first (authoritative source) and falls back to the generated constant only if the walk fails.
This commit is contained in:
@@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
### Fixed
|
||||
|
||||
* **fleet:** fix version detection returning stale value from `generated/version.ts` instead of the authoritative `package.json`. This caused remote nodes to show "unknown" version and false "Update available" badges when both nodes were on the same version. `resolveVersion()` now reads the root `package.json` first and only falls back to the build-time constant if the walk fails.
|
||||
* **fleet:** fix permanently stuck "Timed out" / "Failed" badges after node update attempts. The in-memory update tracker now supports clearing via a new DELETE endpoint, and terminal states are automatically clearable through the Recheck button.
|
||||
* **fleet:** fix update completion detection for remote nodes that cannot report their version. The gateway now uses three completion signals: version change, process restart detection (`startedAt`), and offline/online detection (node went unreachable during update and came back). This eliminates false timeouts on nodes running older Sencho versions.
|
||||
* **fleet:** fix 409 race condition where retrying a timed-out update was rejected because the tracker still showed "updating". The POST trigger now detects expired timeouts and allows re-triggering.
|
||||
|
||||
@@ -43,9 +43,9 @@ export function isValidVersion(v: string | null | undefined): v is string {
|
||||
|
||||
// Resolved once per process at import time, then cached.
|
||||
function resolveVersion(): string | null {
|
||||
if (SENCHO_VERSION !== '0.0.0-dev') return SENCHO_VERSION;
|
||||
|
||||
// Fallback for manual ts-node runs without the predev hook.
|
||||
// Primary: walk up to find the root package.json (always authoritative).
|
||||
// The generated SENCHO_VERSION constant can be stale when a branch falls
|
||||
// behind a release-please version bump, so we prefer the live value.
|
||||
let dir = __dirname;
|
||||
for (let i = 0; i < 5; i++) {
|
||||
const candidate = path.join(dir, 'package.json');
|
||||
@@ -55,6 +55,8 @@ function resolveVersion(): string | null {
|
||||
} catch { /* not found, keep walking */ }
|
||||
dir = path.dirname(dir);
|
||||
}
|
||||
// Fallback: build-time constant (may be stale in dev, but correct in Docker)
|
||||
if (SENCHO_VERSION !== '0.0.0-dev') return SENCHO_VERSION;
|
||||
console.warn('[CapabilityRegistry] Could not resolve Sencho version from any source');
|
||||
return null;
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 32 KiB |
@@ -389,6 +389,20 @@ docker compose pull && docker compose up -d
|
||||
|
||||
---
|
||||
|
||||
## Remote node version shows "unknown"
|
||||
|
||||
**Symptom:** A remote node appears online in the Fleet View but its version badge is missing or the Node Updates modal shows "unknown" in the current version column.
|
||||
|
||||
**Common causes:**
|
||||
|
||||
1. **Network issue:** The gateway cannot reach the remote node's `/api/meta` endpoint. Check that the API URL configured for the node is correct and accessible from the gateway host.
|
||||
2. **Old Sencho version:** Nodes running Sencho versions older than v0.39.0 do not report a version in their metadata. Update the remote node manually to resolve this.
|
||||
3. **Development build:** If running from source, ensure you have run `npm install` in the backend directory so the `predev` hook regenerates the version file.
|
||||
|
||||
**To verify:** Open your browser's developer tools and check the response from `GET /api/fleet/update-status`. Each node's `version` field should contain a semver string (e.g., `"0.39.4"`). If it shows `null`, the gateway could not determine the remote's version.
|
||||
|
||||
---
|
||||
|
||||
## Stack labels are not visible in the sidebar
|
||||
|
||||
**Symptom:** You assigned labels to stacks but no label pills appear in the sidebar.
|
||||
|
||||
Reference in New Issue
Block a user