-
Notifications
You must be signed in to change notification settings - Fork 112
Version Chooser: deal (badly) with dockerhub api changes #3490
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Version Chooser: deal (badly) with dockerhub api changes #3490
Conversation
Reviewer's GuideThis PR adds a workaround for DockerHub API changes by injecting placeholder tag metadata when no image entries are returned, and introduces an integration test for the TagFetcher to validate real-world behavior. Sequence diagram for fetch_remote_tags handling DockerHub API changessequenceDiagram
participant TagFetcher
participant DockerHubAPI
participant TagMetadata
TagFetcher->>DockerHubAPI: Request tags for repository
DockerHubAPI-->>TagFetcher: Return tags (some with empty images[])
TagFetcher->>TagMetadata: Create placeholder TagMetadata if images[] is empty
TagFetcher->>TagMetadata: Create TagMetadata for valid architecture if images[] present
TagFetcher-->>TagFetcher: Append TagMetadata to valid_images
Class diagram for TagMetadata and fetch_remote_tags workaroundclassDiagram
class TagMetadata {
+repository: str
+image: str
+tag: str
+last_modified: str
+sha: str | None
+digest: str
}
class TagFetcher {
+fetch_remote_tags(repository: str, local_images: List[str])
}
TagFetcher --> TagMetadata : creates
File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
9943e07
to
501ed97
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey there - I've reviewed your changes - here's some feedback:
- The hardcoded digest "------" may lead to unexpected downstream behavior; consider using None or a dedicated sentinel and handling it explicitly in consumer logic instead of a magic string.
- TestTagFetcher currently makes live calls to DockerHub and risks CI flakiness; either mock the network responses or mark this as an integration test that’s skipped by default.
- It might be clearer to extract the empty-
images
handling into a separate helper function with its own tests and documentation to encapsulate this workaround.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The hardcoded digest "------" may lead to unexpected downstream behavior; consider using None or a dedicated sentinel and handling it explicitly in consumer logic instead of a magic string.
- TestTagFetcher currently makes live calls to DockerHub and risks CI flakiness; either mock the network responses or mark this as an integration test that’s skipped by default.
- It might be clearer to extract the empty-`images` handling into a separate helper function with its own tests and documentation to encapsulate this workaround.
## Individual Comments
### Comment 1
<location> `core/services/versionchooser/utils/dockerhub.py:114` </location>
<code_context>
valid_images = []
for tag in tags:
+ images = tag["images"]
+ if len(images) == 0:
+ # this is a hack to deal with https://github.com/docker/hub-feedback/issues/2484
+ # we lost the ability to properly identify the images as we dont have the digest,
+ # and also the ability to filter for compatible architectures.
</code_context>
<issue_to_address>
Consider logging or surfacing when tags have no images for better traceability.
Logging a warning when this fallback is triggered will help with monitoring and debugging, especially if Docker Hub's behavior changes or unexpected tags appear.
Suggested implementation:
```python
import logging
logger = logging.getLogger(__name__)
my_architecture = get_current_arch()
valid_images = []
for tag in tags:
images = tag["images"]
if len(images) == 0:
logger.warning(
"Tag '%s' in repository '%s' has no images. Fallback logic triggered. See https://github.com/docker/hub-feedback/issues/2484",
tag.get("name", "<unknown>"),
repository,
)
# this is a hack to deal with https://github.com/docker/hub-feedback/issues/2484
# we lost the ability to properly identify the images as we dont have the digest,
# and also the ability to filter for compatible architectures.
# so we just add the tag and hope for the best.
tag = TagMetadata(
repository=repository,
image=repository.split("/")[-1],
tag=tag["name"],
last_modified=tag["last_updated"],
sha=None,
digest="------",
)
valid_images.append(tag)
```
If your project already has a logger instance (e.g., `logger` defined at the module level), use that instead of creating a new one with `logging.getLogger(__name__)`. Remove the import and logger assignment if not needed.
</issue_to_address>
### Comment 2
<location> `core/services/versionchooser/test_versionchooser.py:258` </location>
<code_context>
+ assert len(tags) > 0, "Should have found some tags for bluerobotics/blueos-core"
+
+ # Verify tag structure
+ for tag in tags[:3]: # Check first 3 tags
+ assert isinstance(tag, TagMetadata)
+ assert tag.repository == "bluerobotics/blueos-core"
+ assert tag.image == "blueos-core"
+ assert tag.tag is not None
+ assert len(tag.tag) > 0
+ assert tag.last_modified is not None
+ assert tag.digest is not None
+
+ # Should find the 'master' tag
</code_context>
<issue_to_address>
Test does not cover edge case for tags with missing images (digest set to '------').
Please add a test for tags with missing images (digest set to '------') to confirm TagMetadata is constructed correctly and downstream code handles this case.
</issue_to_address>
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
if len(images) == 0: | ||
# this is a hack to deal with https://github.com/docker/hub-feedback/issues/2484 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: Consider logging or surfacing when tags have no images for better traceability.
Logging a warning when this fallback is triggered will help with monitoring and debugging, especially if Docker Hub's behavior changes or unexpected tags appear.
Suggested implementation:
import logging
logger = logging.getLogger(__name__)
my_architecture = get_current_arch()
valid_images = []
for tag in tags:
images = tag["images"]
if len(images) == 0:
logger.warning(
"Tag '%s' in repository '%s' has no images. Fallback logic triggered. See https://github.com/docker/hub-feedback/issues/2484",
tag.get("name", "<unknown>"),
repository,
)
# this is a hack to deal with https://github.com/docker/hub-feedback/issues/2484
# we lost the ability to properly identify the images as we dont have the digest,
# and also the ability to filter for compatible architectures.
# so we just add the tag and hope for the best.
tag = TagMetadata(
repository=repository,
image=repository.split("/")[-1],
tag=tag["name"],
last_modified=tag["last_updated"],
sha=None,
digest="------",
)
valid_images.append(tag)
If your project already has a logger instance (e.g., logger
defined at the module level), use that instead of creating a new one with logging.getLogger(__name__)
. Remove the import and logger assignment if not needed.
for tag in tags[:3]: # Check first 3 tags | ||
assert isinstance(tag, TagMetadata) | ||
assert tag.repository == "bluerobotics/blueos-core" | ||
assert tag.image == "blueos-core" | ||
assert tag.tag is not None | ||
assert len(tag.tag) > 0 | ||
assert tag.last_modified is not None | ||
assert tag.digest is not None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion (testing): Test does not cover edge case for tags with missing images (digest set to '------').
Please add a test for tags with missing images (digest set to '------') to confirm TagMetadata is constructed correctly and downstream code handles this case.
I've mentioned some relevant ideas here and here. I think having a test for this is useful, but agree with you that the implemented fix approach is not great, and given the API rollback doesn't seem necessary. I think you should either remove/replace the fix, or change this PR back to a draft (in case it becomes relevant again) :-) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so we just add the tag and hope for the best.
I'm not against this quick fallback, but I want to understand what can happen in this case.
# we lost the ability to properly identify the images as we dont have the digest, | ||
# and also the ability to filter for compatible architectures. | ||
# so we just add the tag and hope for the best. | ||
tag = TagMetadata( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should log a warning here
Okay, I'm good with the behavior -- versionchooser lists the wrong architecture images, but it fails when trying to apply. It would only be better if it had warnings to tell us (and also the frontend) what's happening. |
We should move this to 1.4 and 1.3 |
"Fix" #3489

Summary by Sourcery
Handle DockerHub API change by falling back to placeholder TagMetadata for tags with no image data and add an integration test to validate TagFetcher against a real repository
Bug Fixes:
Tests: