Skip to content

feat(watcher): report remote version and build date for digest updates - #1178

Open
weirdtangent wants to merge 1 commit into
getwud:mainfrom
weirdtangent:feat/remote-image-version-on-digest-update
Open

feat(watcher): report remote version and build date for digest updates#1178
weirdtangent wants to merge 1 commit into
getwud:mainfrom
weirdtangent:feat/remote-image-version-on-digest-update

Conversation

@weirdtangent

Copy link
Copy Markdown

A digest-watched container can only report "sha A -> sha B", which says nothing about what changed. Both the remote org.opencontainers.image.version label and the remote build date live in the image config blob, so reading it lets consumers describe the update as 2.3.6 -> 2.3.7, or as a build-date change when the label is a floating value such as latest or nightly.

result.created was already assigned in the watcher and already part of the container model, but getImageManifestDigest only ever populates it on the legacy schemaVersion 1 path -- so it is undefined for every modern v2/OCI image, which is every image watched by digest.

Adds Registry.getImageConfig() and a new result.version. Both flow to the API and every trigger through the existing flatten step, with no per-trigger changes. result_version is also declared in the Prometheus gauge label names: the gauge is populated from the flattened container and prom-client rejects an undeclared label, which would otherwise drop the whole container from /metrics with a warning.

Request cost is kept minimal in two ways. A remote digest is resolved at most once -- a pending update is not re-resolved on every scan, since the stored result for the same digest is reused -- and getImageManifestDigest now returns the config digest it already saw for a single-platform manifest, so resolving the config takes one blob request rather than a manifest request plus a blob request. An up-to-date container costs nothing extra. This matters for registries that rate limit anonymous pulls (Docker Hub allows 100 per 6h per IP, and manifest GETs count).

An empty org.opencontainers.image.version label is normalized to undefined. Images built with ARG VERSION + LABEL ...version=$VERSION and no build arg publish an empty label, and '' fails container validation -- which is raised outside the per-container try/catch in watchContainer, so a single such container would abort the whole watch cycle.

Refs #820, #175

A digest-watched container can only report "sha A -> sha B", which says
nothing about what changed. Both the remote `org.opencontainers.image.version`
label and the remote build date live in the image config blob, so reading it
lets consumers describe the update as `2.3.6 -> 2.3.7`, or as a build-date
change when the label is a floating value such as `latest` or `nightly`.

`result.created` was already assigned in the watcher and already part of the
container model, but `getImageManifestDigest` only ever populates it on the
legacy schemaVersion 1 path -- so it is undefined for every modern v2/OCI
image, which is every image watched by digest.

Adds `Registry.getImageConfig()` and a new `result.version`. Both flow to the
API and every trigger through the existing flatten step, with no per-trigger
changes. `result_version` is also declared in the Prometheus gauge label
names: the gauge is populated from the flattened container and prom-client
rejects an undeclared label, which would otherwise drop the whole container
from /metrics with a warning.

Request cost is kept minimal in two ways. A remote digest is resolved at most
once -- a pending update is not re-resolved on every scan, since the stored
result for the same digest is reused -- and `getImageManifestDigest` now
returns the config digest it already saw for a single-platform manifest, so
resolving the config takes one blob request rather than a manifest request
plus a blob request. An up-to-date container costs nothing extra. This
matters for registries that rate limit anonymous pulls (Docker Hub allows
100 per 6h per IP, and manifest GETs count).

An empty `org.opencontainers.image.version` label is normalized to undefined.
Images built with `ARG VERSION` + `LABEL ...version=$VERSION` and no build arg
publish an empty label, and `''` fails container validation -- which is raised
outside the per-container try/catch in `watchContainer`, so a single such
container would abort the whole watch cycle.

Refs getwud#820, getwud#175

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@weirdtangent
weirdtangent force-pushed the feat/remote-image-version-on-digest-update branch from 5103451 to 9b5667f Compare September 3, 2026 19:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant