Skip to content

Conversation

@rockythorn
Copy link
Collaborator

@rockythorn rockythorn commented Dec 10, 2025

This PR fixes two bugs identified in the new updateinfo_v2 endpoint and strengthens tests for updateinfo XML generation. See https://bugs.rockylinux.org/view.php?id=11320

1. Product Information Missing from Updateinfo Elements

Problem:

The and XML elements in the generated updateinfo were missing the expected product context, producing output such as:

<pkglist>
  <collection short="none-baseos-rpms">
    <name>none-baseos-rpms</name>

Cause:

The v2 endpoint previously did not pass the necessary product_name_for_packages argument to the updateinfo XML string builder.

Solution:

Update the endpoint to correctly pass product_name_for_packages, ensuring that product information appears as expected in both and elements.

2. Duplicate Packages in pkglist Element

Problem:

Identical packages appeared multiple times within , such as:

<package name="gsettings-desktop-schemas" ... />
<package name="gsettings-desktop-schemas" ... />
<package name="gsettings-desktop-schemas" ... />

Cause:

Because the v2 endpoint operates over multiple mirrors/products associated with the same advisory, duplicate package entries were not eliminated (unlike the original endpoint, which pre-filters by mirror/product).

Solution:

Added explicit deduplication logic for packages in the v2 endpoint’s pkglist generation.

3. Test Coverage

New and updated unit tests have been added to detect regressions and ensure that these XML generation issues are caught in the future.

Summary:

This PR improves the fidelity of updateinfo XML output for the v2 endpoint by restoring product context and eliminating duplicate packages, with accompanying tests for long-term stability.

Note:
The tests and some related changes in this PR were written with the assistance of Claude Code.

@rockythorn rockythorn marked this pull request as ready for review December 10, 2025 00:54
Copy link

@elguero elguero left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor comments. Otherwise, functionality looks good and tests look good.

@rockythorn rockythorn requested review from NeilHanlon, mstg and trinity-q and removed request for trinity-q December 12, 2025 19:46
Copy link
Contributor

@NeilHanlon NeilHanlon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent work as always @rockythorn :) Solid fix for both bugs that also improves test coverage. It's a Christmas miracle and it's only December!

The root cause explanation & its' fixes seem entirely logical and correct. NEVRA-based dedupe is the right approach for sure. Though I'm not a test expert, the tests appear extensive enough to help catch regressions in the future.

We may want to at some point take a pass at adding typing for the project, which would at least give the ability to lint a bit easier than waiting for CPython to throw a fit.

One small nit if I have to have one:

Docstring at line 104 in api_updateinfo.py mentions product_name_for_packages as "Optional", but it's technically not since it's required for V2's XML generation. Might be worth clarifying that role in a future pass, but again... a nit.

LGTM! Thanks again Sam. Happy holidays. 🎅🏼 🎁 🕎

Comment on lines 201 to +208
if supported_product_id is not None:
# v2: Filter by FK (normalized relational data)
filtered_packages = [
pkg for pkg in advisory.packages
if pkg.supported_product_id == supported_product_id and pkg.repo_name == repo_name
]
seen_nevras = set()
filtered_packages = []
for pkg in advisory.packages:
if pkg.supported_product_id == supported_product_id and pkg.repo_name == repo_name:
if pkg.nevra not in seen_nevras:
seen_nevras.add(pkg.nevra)
filtered_packages.append(pkg)
Copy link
Contributor

@NeilHanlon NeilHanlon Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This dedupe implementation is clean, but I'd be remiss (i.e., exiled by ##python on Libera.chat) if I didn't take the opportunity to mention a
possibly more "pythonic" way to do it:

if supported_product_id is not None:
    filtered_packages = list({
        pkg.nevra: pkg
        for pkg in advisory.packages
        if pkg.supported_product_id == supported_product_id
        and pkg.repo_name == repo_name
    }.values())

As long as we definitely want the first match and don't need side effects or logging during the filtering, then using a dict naturally performs the
"keep the first NEVRA" like you want.

Another option would be to remove the nesting and perform the check in a single pass instead:

    # ...
    for pkg in advisory.packages:
        if (
            pkg.supported_product_id != supported_product_id
            or pkg.repo_name != repo_name
            or pkg.nevra in seen_nevras
        ):
            continue

        seen_nevras.add(pkg.nevra)
        filtered_packages.append(pkg)

Either way, the code is fine as is :)

@brianclemens brianclemens merged commit 9291046 into resf:main Jan 4, 2026
1 check passed
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.

7 participants