feat(watcher): report remote version and build date for digest updates - #1178
Open
weirdtangent wants to merge 1 commit into
Open
feat(watcher): report remote version and build date for digest updates#1178weirdtangent wants to merge 1 commit into
weirdtangent wants to merge 1 commit into
Conversation
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
force-pushed
the
feat/remote-image-version-on-digest-update
branch
from
September 3, 2026 19:24
5103451 to
9b5667f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A digest-watched container can only report "sha A -> sha B", which says nothing about what changed. Both the remote
org.opencontainers.image.versionlabel and the remote build date live in the image config blob, so reading it lets consumers describe the update as2.3.6 -> 2.3.7, or as a build-date change when the label is a floating value such aslatestornightly.result.createdwas already assigned in the watcher and already part of the container model, butgetImageManifestDigestonly 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 newresult.version. Both flow to the API and every trigger through the existing flatten step, with no per-trigger changes.result_versionis 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
getImageManifestDigestnow 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.versionlabel is normalized to undefined. Images built withARG VERSION+LABEL ...version=$VERSIONand no build arg publish an empty label, and''fails container validation -- which is raised outside the per-container try/catch inwatchContainer, so a single such container would abort the whole watch cycle.Refs #820, #175