Skip to content

feat(preprod): Add install_groups as a filterable key in artifact search#115818

Open
mtopo27 wants to merge 4 commits into
masterfrom
maxtopolsky/eme-1160-add-install_groups-as-a-filterable-key-in-artifact_searchpy
Open

feat(preprod): Add install_groups as a filterable key in artifact search#115818
mtopo27 wants to merge 4 commits into
masterfrom
maxtopolsky/eme-1160-add-install_groups-as-a-filterable-key-in-artifact_searchpy

Conversation

@mtopo27
Copy link
Copy Markdown
Contributor

@mtopo27 mtopo27 commented May 19, 2026

Support filtering artifacts by install_groups in artifact_search.py so that all search consumers (builds list, sequential base resolution, quota matching, and the upcoming latest-build route) can narrow results by install group.

install_groups is stored as a JSON array in PreprodArtifact.extras, so it gets a special-case handler in apply_filters() that builds an OR of JSON containment queries — matching the same semantics as the existing build_install_groups_q() helper. Supports single value (install_groups:beta), IN filter (install_groups:[beta, internal]), and negation (!install_groups:beta).

Special-case handler

Unlike flat-column filters that fall through to the generic handler, install_groups needs extras__install_groups__contains containment lookups, so it's handled explicitly alongside size_state, distribution_error_code, and snapshot_status.

Refs EME-1160

Support filtering artifacts by install_groups in artifact_search.py so
that builds list, sequential base resolution, quota matching, and the
upcoming latest-build route can narrow results by install group.
@linear-code
Copy link
Copy Markdown

linear-code Bot commented May 19, 2026

EME-1160

@github-actions github-actions Bot added the Scope: Backend Automatically applied to PRs that change backend components label May 19, 2026
@mtopo27 mtopo27 marked this pull request as ready for review May 21, 2026 14:47
@mtopo27 mtopo27 requested a review from a team as a code owner May 21, 2026 14:47
Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
Comment thread src/sentry/preprod/artifact_search.py Outdated
Comment thread src/sentry/preprod/artifact_search.py
Copy link
Copy Markdown
Contributor

@chromy chromy left a comment

Choose a reason for hiding this comment

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

lgtm % 1 comment

Comment thread src/sentry/preprod/artifact_search.py
has:install_groups produced a SearchFilter with an empty-string value,
which silently built Q(extras__install_groups__contains=[""]) instead of
checking key existence. Reject it with InvalidSearchQuery, matching how
size_state and distribution_error_code implicitly reject empty values
via their validation functions.

Also replace the inline OR-of-contains loop with the existing
build_install_groups_q() helper from build_distribution_utils to
eliminate duplication.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 5b65e69. Configure here.

if token.is_negation:
queryset = queryset.exclude(q)
else:
queryset = queryset.filter(q)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Unhandled None return from build_install_groups_q

Medium Severity

build_install_groups_q has return type Q | None and returns None when passed an empty sequence. In the is_in_filter branch, token.value.value (a list) is passed directly, and if it's empty, the returned None is passed to queryset.filter() or queryset.exclude(), which will raise a TypeError. The existing caller in build_distribution_utils.py handles this defensively with a guard check, but this new caller does not.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 5b65e69. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Backend Automatically applied to PRs that change backend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants