mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-06 17:08:10 +00:00
fix(app-store): harden template deploy, registry fetch, and catalogue refresh (#1250)
* fix(app-store): harden template deploy, registry fetch, and catalogue refresh Serialize generated compose through the YAML emitter so registry-supplied values are escaped correctly instead of interpolated into hand-built lines. Cap the registry response size so an oversized or runaway catalogue cannot exhaust backend memory, and surface the fetch failure to the caller. Reload the catalogue when the active node changes, since the registry is node-scoped. Add developer-mode deploy diagnostics (counts only, no values) and extend the unit tests with YAML round-trip, LinuxServer.io mapping, and size-cap coverage. * fix(app-store): reset node-scoped catalogue state on fetch and bound deploy diagnostics Clear the templates list and Trivy availability at the start of each catalogue load so a failed fetch after a node switch shows the new node's empty state instead of the previous node's catalogue or scan toggle. Bound the developer-mode diagnostic template title/source length, and document that the registry cache serves the last-known-good catalogue on a transient fetch failure (the size cap still protects memory in every case).
This commit is contained in:
@@ -59,28 +59,37 @@ export function AppStoreView({ onDeploySuccess }: AppStoreViewProps) {
|
||||
const [trivyAvailable, setTrivyAvailable] = useState(false);
|
||||
const [sheetTab, setSheetTab] = useState<'essentials' | 'advanced'>('essentials');
|
||||
|
||||
// The template registry is node-scoped, so the catalogue (and Trivy
|
||||
// availability) must reload when the active node changes. Both are reset at
|
||||
// the start of every run so a failed fetch shows the new node's empty state
|
||||
// rather than leaving the previous node's catalogue or scan toggle on
|
||||
// screen. The cancelled flag drops a slow response from a previous node so
|
||||
// it cannot overwrite the current node's catalogue after a fast switch.
|
||||
useEffect(() => {
|
||||
fetchTemplates();
|
||||
let cancelled = false;
|
||||
(async () => {
|
||||
setLoading(true);
|
||||
setTemplates([]);
|
||||
setTrivyAvailable(false);
|
||||
try {
|
||||
const res = await apiFetch('/templates');
|
||||
if (!res.ok) throw new Error('Failed to fetch templates');
|
||||
const data = await res.json();
|
||||
if (!cancelled) setTemplates(data || []);
|
||||
} catch (err) {
|
||||
if (!cancelled) toast.error(err instanceof Error ? err.message : 'Failed to load App Store');
|
||||
} finally {
|
||||
if (!cancelled) setLoading(false);
|
||||
}
|
||||
})();
|
||||
apiFetch('/security/trivy-status')
|
||||
.then(r => r.ok ? r.json() : null)
|
||||
.then(d => { if (d) setTrivyAvailable(!!d.available); })
|
||||
.then(d => { if (!cancelled && d) setTrivyAvailable(!!d.available); })
|
||||
.catch((err) => {
|
||||
console.error('Failed to fetch Trivy status:', err);
|
||||
});
|
||||
}, []);
|
||||
|
||||
const fetchTemplates = async () => {
|
||||
try {
|
||||
const res = await apiFetch('/templates');
|
||||
if (!res.ok) throw new Error('Failed to fetch templates');
|
||||
const data = await res.json();
|
||||
setTemplates(data || []);
|
||||
} catch (err) {
|
||||
toast.error((err as Error).message || 'Failed to load App Store');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
return () => { cancelled = true; };
|
||||
}, [activeNode?.id]);
|
||||
|
||||
const handleSelectTemplate = (t: Template) => {
|
||||
const envsCopy = [...(t.env || [])];
|
||||
|
||||
Reference in New Issue
Block a user