Skip to content

Commit

Permalink
feat(api): match ecosystem names without variants (#2986)
Browse files Browse the repository at this point in the history
Resolves #2963

Updates the API query to support variant-insensitive matching of
affected package ecosystem names. A match is found if the package
ecosystem name, after removing all variants, is the same as the queried
ecosystem name.

TODO:
- [ ] Add integration tests after reput Ubuntu records on prod (after
the end-of-year release freeze)
  • Loading branch information
hogo6002 authored Dec 16, 2024
1 parent ef25c66 commit e100a02
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 15 deletions.
27 changes: 15 additions & 12 deletions gcp/api/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -981,9 +981,8 @@ def _is_version_affected(affected_packages,

if ecosystem:
# If package ecosystem has a :, also try ignoring parts after it.
if (affected_package.package.ecosystem != ecosystem and
ecosystems.normalize(
affected_package.package.ecosystem) != ecosystem):
if not is_matching_package_ecosystem(affected_package.package.ecosystem,
ecosystem):
continue

if normalize:
Expand Down Expand Up @@ -1237,9 +1236,6 @@ def _query_by_comparing_versions(context: QueryContext, query: ndb.Query,

it: ndb.QueryIterator = query.iter(start_cursor=context.cursor_at_current())

# Checks if the query specifies a release (e.g., "Debian:12")
has_release = ':' in ecosystem

while (yield it.has_next_async()):
if context.should_break_page(len(bugs)):
context.save_cursor_at_page_break(it)
Expand All @@ -1255,14 +1251,9 @@ def _query_by_comparing_versions(context: QueryContext, query: ndb.Query,
# compare against packages in all releases (e.g., "Debian:X").
# Otherwise, only compare within
# the specified release (e.g., "Debian:11").
package_ecosystem: str = package.ecosystem # type: ignore
if not has_release:
# Extracts ecosystem name for broader comparison (e.g., "Debian")
package_ecosystem = package_ecosystem.split(':')[0]

# Skips if the affected package ecosystem does not match
# the queried ecosystem.
if package_ecosystem != ecosystem:
if not is_matching_package_ecosystem(package.ecosystem, ecosystem):
continue

# Skips if the affected package name does not match
Expand Down Expand Up @@ -1403,6 +1394,18 @@ def _is_affected(ecosystem: str, version: str,
return False


def is_matching_package_ecosystem(package_ecosystem: str,
ecosystem: str) -> bool:
"""Checks if the queried ecosystem matches the affected package's ecosystem,
considering potential variations in the package's ecosystem.
"""
return any(eco == ecosystem for eco in (
package_ecosystem,
ecosystems.normalize(package_ecosystem),
ecosystems.remove_variants(package_ecosystem),
))


def main():
"""Entrypoint."""
if is_cloud_run():
Expand Down
15 changes: 12 additions & 3 deletions osv/ecosystems/_ecosystems.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,15 @@ def normalize(ecosystem_name: str):
return ecosystem_name.split(':')[0]


def remove_variants(ecosystem_name: str) -> str | None:
result = None
# For Ubuntu, remove ":Pro" and ":LTS"
if ecosystem_name.startswith('Ubuntu'):
result = ecosystem_name.replace(':Pro', '').replace(':LTS', '')

return result


def add_matching_ecosystems(original_set: set[str]) -> set[str]:
"""
For Linux distributions, some release versions may have different variants.
Expand All @@ -163,9 +172,9 @@ def add_matching_ecosystems(original_set: set[str]) -> set[str]:
new_set = set(original_set)
for ecosystem in original_set:
# For Ubuntu, remove ":Pro" and ":LTS"
if ecosystem.startswith('Ubuntu'):
new_item = ecosystem.replace(':Pro', '').replace(':LTS', '')
new_set.add(new_item)
new_ecosystem = remove_variants(ecosystem)
if new_ecosystem:
new_set.add(new_ecosystem)
return new_set


Expand Down

0 comments on commit e100a02

Please sign in to comment.