From 568547b3049dc0698f906757c06e856547d7ee80 Mon Sep 17 00:00:00 2001 From: Pablo P Varela Date: Thu, 23 Apr 2026 20:02:08 +0200 Subject: [PATCH] fix: compare manifest digests correctly in update check - Use RepoDigests (manifest digest) instead of .Image (config blob digest) so local and remote digests are comparable - Filter tag list to date-prefixed tags only (YYYY-MM-DD-sha) so raw git SHA tags don't sort ahead of the real version --- src/actions/update.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/actions/update.ts b/src/actions/update.ts index af6c9934..c55ed943 100644 --- a/src/actions/update.ts +++ b/src/actions/update.ts @@ -87,7 +87,9 @@ async function fetchLatestTag(token: string): Promise { if (!response.ok) return "latest"; const data = (await response.json()) as { tags?: string[] }; - const tags = data.tags?.filter((t) => t !== "latest") ?? []; + // Only consider date-prefixed tags (YYYY-MM-DD-sha) to avoid raw git SHAs + const dateTagPattern = /^\d{4}-\d{2}-\d{2}-[a-f0-9]+$/; + const tags = data.tags?.filter((t) => dateTagPattern.test(t)) ?? []; tags.sort((a, b) => b.localeCompare(a)); return tags[0] ?? "latest"; @@ -97,11 +99,17 @@ async function fetchLatestTag(token: string): Promise { } async function getLocalImageDigest(): Promise { - const containerName = await getContainerName(); - + // Inspect the image directly for its RepoDigests, which contains the + // manifest digest (matches what GHCR returns). The container's .Image + // field is the image config blob digest, which is different. const result = await spawnCommand( "docker", - ["inspect", "--format", "{{.Image}}", containerName], + [ + "inspect", + "--format", + "{{if .RepoDigests}}{{index .RepoDigests 0}}{{end}}", + `${IMAGE_NAME}:latest`, + ], { timeout: 10000 }, ); @@ -109,7 +117,8 @@ async function getLocalImageDigest(): Promise { return null; } - return result.stdout.trim(); + const match = result.stdout.trim().match(/@(sha256:[a-f0-9]+)/); + return match?.[1] ?? null; } function isCacheValid(entry: CacheEntry | undefined): boolean {