From 367a2d8a27f3f8c243416fa16fed61b3559e96d0 Mon Sep 17 00:00:00 2001 From: Syco21 Date: Sat, 16 May 2026 18:00:15 +0200 Subject: [PATCH] Fix lscr.io image update verification; tighten Docker widget MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit lscr.io is backed by ghcr.io and requires a GitHub token for registry auth — passing it fixes the silent null return from the token endpoint. Widget now shows only confirmed outdated/current containers, with unverified and unsupported-registry images summarised as a footer count. --- server/routes/updates.ts | 3 +- .../widgets/DockerUpdatesWidget.tsx | 50 ++++++++----------- 2 files changed, 24 insertions(+), 29 deletions(-) diff --git a/server/routes/updates.ts b/server/routes/updates.ts index 17dfc7e..e1f3550 100644 --- a/server/routes/updates.ts +++ b/server/routes/updates.ts @@ -119,7 +119,8 @@ async function getGhcrLatestDigest(image: string, tag: string): Promise { - return getGenericRegistryDigest('lscr.io', image, tag) + // lscr.io is backed by ghcr.io and requires the same GitHub token auth + return getGenericRegistryDigest('lscr.io', image, tag, process.env.GITHUB_TOKEN) } router.get('/docker', async (_req, res) => { diff --git a/src/components/widgets/DockerUpdatesWidget.tsx b/src/components/widgets/DockerUpdatesWidget.tsx index 055eaad..103ab26 100644 --- a/src/components/widgets/DockerUpdatesWidget.tsx +++ b/src/components/widgets/DockerUpdatesWidget.tsx @@ -9,6 +9,8 @@ interface ContainerInfo { endpoint: string } +const KNOWN = ['docker.io', 'ghcr.io', 'lscr.io'] + export function DockerUpdatesWidget() { const [containers, setContainers] = useState([]) const [error, setError] = useState(null) @@ -17,25 +19,26 @@ export function DockerUpdatesWidget() { useEffect(() => { fetch('/api/updates/docker') .then(r => r.json()) - .then(d => { - if (d.error) setError(d.error) - else setContainers(d.containers) - }) + .then(d => { if (d.error) setError(d.error); else setContainers(d.containers) }) .catch(() => setError('Failed to connect')) .finally(() => setLoading(false)) }, []) - const outdated = containers.filter(c => c.upToDate === false).length - const knownRegistries = ['docker.io', 'ghcr.io', 'lscr.io'] - const unknown = containers.filter(c => c.upToDate === null && !knownRegistries.includes(c.registry)).length + const outdated = containers.filter(c => c.upToDate === false) + const upToDate = containers.filter(c => c.upToDate === true) + const unverified = containers.filter(c => c.upToDate === null && KNOWN.includes(c.registry)) + const external = containers.filter(c => !KNOWN.includes(c.registry)) + + // Show: outdated first, then up to date. Unverified and ext only as a footer count. + const visible = [...outdated, ...upToDate] return (
Docker
{!loading && !error && ( - 0 ? { background: 'rgba(248,113,113,0.15)', color: 'var(--red)' } : {}}> - {outdated > 0 ? `${outdated} outdated` : 'all current'} + 0 ? { background: 'rgba(248,113,113,0.15)', color: 'var(--red)' } : {}}> + {outdated.length > 0 ? `${outdated.length} outdated` : 'all current'} )}
@@ -45,13 +48,7 @@ export function DockerUpdatesWidget() { {!loading && !error && (
- {[...containers] - .sort((a, b) => { - const rank = (c: ContainerInfo) => - c.upToDate === false ? 0 : c.upToDate === null ? 1 : 2 - return rank(a) - rank(b) - }) - .map(c => ( + {visible.map(c => (
{c.name} @@ -59,20 +56,17 @@ export function DockerUpdatesWidget() { {c.image}:{c.tag.startsWith('sha256:') ? c.tag.slice(0, 15) + '…' : c.tag} · {c.endpoint}
- {c.upToDate === null && !knownRegistries.includes(c.registry) ? ( - ext - ) : c.upToDate === true ? ( - - ) : c.upToDate === false ? ( - ↑ update - ) : ( - ? - )} + {c.upToDate === true + ? + : ↑ update + }
))} - {unknown > 0 && ( -
- {unknown} non-Docker Hub image{unknown > 1 ? 's' : ''} not checked + + {(unverified.length > 0 || external.length > 0) && ( +
+ {unverified.length > 0 &&
{unverified.length} image{unverified.length > 1 ? 's' : ''} could not be verified
} + {external.length > 0 &&
{external.length} image{external.length > 1 ? 's' : ''} on unsupported registry
}
)}