Skip to content

Conversation

joaoantoniocardoso
Copy link
Member

@joaoantoniocardoso joaoantoniocardoso commented Aug 15, 2025

This is a backport of #3490 into 1.3

Summary by Sourcery

Backport the DockerHub workaround to handle missing images and add integration tests for tag fetching

Enhancements:

  • Handle empty DockerHub image lists by creating placeholder TagMetadata entries with dummy digests
  • Introduce TestTagFetcher integration test to verify fetching and validating tags from DockerHub

Tests:

  • Add integration test class TestTagFetcher for TagFetcher functionality

Copy link

sourcery-ai bot commented Aug 15, 2025

Reviewer's Guide

This backport implements a DockerHub workaround by adding fallback tag handling for entries with empty images and introduces integration tests for the TagFetcher in the 1.3 branch.

Sequence diagram for DockerHub tag fetching with empty images workaround

sequenceDiagram
    participant TagFetcher
    participant DockerHubAPI
    participant TagMetadata
    TagFetcher->>DockerHubAPI: fetch tags for repository
    DockerHubAPI-->>TagFetcher: return tags (some with empty images)
    loop for each tag
        alt images list is empty
            TagFetcher->>TagMetadata: create TagMetadata with digest="------" and sha=None
            TagFetcher->>TagFetcher: add tag to valid_images
        else images list is not empty
            TagFetcher->>TagMetadata: create TagMetadata for matching architecture
            TagFetcher->>TagFetcher: add tag to valid_images
        end
    end
Loading

Class diagram for TagMetadata creation in DockerHub workaround

classDiagram
    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
Loading

File-Level Changes

Change Details Files
Add fallback logic in fetch_remote_tags to handle tags missing image entries
  • Detect when tag["images"] is empty
  • Construct a TagMetadata instance with placeholder digest
  • Append this fallback tag to valid_images and skip further processing
core/services/versionchooser/utils/dockerhub.py
Introduce integration tests for TagFetcher and TagMetadata
  • Import TagFetcher and TagMetadata into the test module
  • Define TestTagFetcher with async test_fetch_real_blueos_core_tags
  • Verify returned tag list structure, presence of 'master' tag, and skip on network errors
core/services/versionchooser/test_versionchooser.py

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a 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 and they look great!

Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments

### Comment 1
<location> `core/services/versionchooser/test_versionchooser.py:272` </location>
<code_context>
+            assert "master" in tag_names, f"Expected to find 'master' tag in tags: {tag_names[:10]}"
+
+            # Errors should be empty string if successful
+            if errors:
+                print(f"Non-fatal errors during fetch: {errors}")
+
+        except Exception as e:
</code_context>

<issue_to_address>
Test does not assert on non-fatal errors returned from fetcher.

Add an assertion to check that errors are empty, or document why non-fatal errors are allowed, to clarify test expectations.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
            # Errors should be empty string if successful
            if errors:
                print(f"Non-fatal errors during fetch: {errors}")
=======
            # Errors should be empty string if successful
            assert not errors, f"Non-fatal errors during fetch: {errors}"
>>>>>>> REPLACE

</suggested_fix>

### Comment 2
<location> `core/services/versionchooser/test_versionchooser.py:275` </location>
<code_context>
+            if errors:
+                print(f"Non-fatal errors during fetch: {errors}")
+
+        except Exception as e:
+            # If this fails due to network issues, skip the test
+            pytest.skip(f"Could not fetch tags from DockerHub, likely network issue: {e}")
</code_context>

<issue_to_address>
Test skips on any exception, potentially hiding real bugs.

Limit exception handling to network-related errors, and log unexpected exceptions for further review.

Suggested implementation:

```python
        except requests.exceptions.RequestException as e:
            # If this fails due to network issues, skip the test
            pytest.skip(f"Could not fetch tags from DockerHub, likely network issue: {e}")
        except Exception as e:
            print(f"Unexpected exception during DockerHub tag fetch: {e}")
            raise

```

```python
import requests

```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Signed-off-by: Patrick José Pereira <patrickelectric@gmail.com>
@joaoantoniocardoso
Copy link
Member Author

joaoantoniocardoso commented Aug 15, 2025

container-diff diff daemon://bluerobotics/blueos-core:1.3.1 daemon://bluerobotics/blueos-core:ff3a0864 --type=file --type=history > container_diff.txt:

container_diff.txt

here's only the list of files diff:

listing_diff.txt

Untracked Python dependecies upgrades:

  • MarkupSafe: 2.1.5 -> removed
  • certifi: 2024.7.4 -> 2025.8.3
  • decorator: 5.1.1 -> 5.2.1
  • h11: 0.14.0 -> 0.16.0
  • jdatetime: 5.0.0 -> 5.2.0
  • mock: 5.1.0 -> 5.2.0
  • multidict: 6.0.5 -> 6.6.4
  • pluggy: 1.5.0 -> 1.6.0
  • iniconfig: 2.0.0 -> 2.1.0
  • pyparsing: 3.1.4 -> 3.2.3
  • pytest: 8.3.2 -> 8.4.1
  • pytz: 2024.1 -> 2025.2
  • soupsieve: 2.6 -> 2.7
  • six: 1.16.0 -> 1.17.0
  • typing_extensions: 4.12.2 -> 4.14.1
  • urllib3: 1.26.19 -> 1.26.20
  • yarl: 1.9.4 -> 1.20.1

@patrickelectric
Copy link
Member

@joaoantoniocardoso are we good to merge ? My idea is to release a stable for 1.3 with this patch

@joaoantoniocardoso
Copy link
Member Author

@joaoantoniocardoso are we good to merge ? My idea is to release a stable for 1.3 with this patch

Code-wise yes, but I haven't tested it, and we must.

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.

3 participants