Skip to content

Feat/tree tests rollup populate command#1874

Draft
gustavobtflores wants to merge 2 commits intokernelci:mainfrom
gustavobtflores:feat/tree-tests-rollup-populate-command
Draft

Feat/tree tests rollup populate command#1874
gustavobtflores wants to merge 2 commits intokernelci:mainfrom
gustavobtflores:feat/tree-tests-rollup-populate-command

Conversation

@gustavobtflores
Copy link
Copy Markdown
Contributor

No description provided.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a one-off Django management command to (re)populate tree_tests_rollup from existing Tests/Builds/Incidents data, and centralizes the rollup processed-item key hashing helper so both streaming aggregation and backfill paths use the same key generator.

Changes:

  • Introduces populate_tree_tests_rollup management command to recompute/upsert tree_tests_rollup and upsert corresponding ProcessedListingItems entries.
  • Moves get_rollup_key() into process_pending_helpers and reuses it from process_pending_aggregations.
  • Tightens typing in process_pending_helpers to use RollupKey for rollup dictionaries.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.

File Description
backend/kernelCI_app/management/commands/process_pending_aggregations.py Imports shared get_rollup_key() instead of defining a local version.
backend/kernelCI_app/management/commands/populate_tree_tests_rollup.py New command that aggregates tests into rollup buckets and writes rollup + processed markers.
backend/kernelCI_app/management/commands/helpers/process_pending_helpers.py Adds shared get_rollup_key() and updates rollup typing to use RollupKey.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +28 to +43
def _fetch_test_issues(test_ids: list[str]) -> dict[str, dict]:
"""Bulk-fetch the first incident per test_id, returning {test_id: {issue_id, issue_version}}."""
issues_map: dict[str, dict] = {}
incidents = Incidents.objects.filter(
test_id__in=test_ids,
).values("test_id", "issue_id", "issue_version")

for inc in incidents:
issues_map.setdefault(
inc["test_id"],
{
"issue_id": inc["issue_id"],
"issue_version": inc["issue_version"],
},
)

Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

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

_fetch_test_issues claims to return the “first incident per test_id”, but the queryset has no ordering, so which incident is chosen is not deterministic. Either add a deterministic order_by(...) that matches the intended definition of “first” or adjust the docstring to avoid implying determinism.

Copilot uses AI. Check for mistakes.
"""Iterate over checkouts matching the filter criteria."""
checkouts_qs = Checkouts.objects.order_by("-start_time", "-id")

if since_days:
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

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

_iter_checkouts uses if since_days: which will skip filtering when --since-days 0 is provided. Use an explicit is not None check so 0 behaves as a valid value (now - 0 days).

Suggested change
if since_days:
if since_days is not None:

Copilot uses AI. Check for mistakes.
self.stderr.write(f"ERROR: Checkout with id={checkout_id} not found")
exit(1)

if limit:
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

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

_iter_checkouts uses if limit: which ignores --limit 0 and treats it like “no limit”. Use if limit is not None (and optionally validate non-negative) to make CLI behavior predictable.

Suggested change
if limit:
if limit is not None:

Copilot uses AI. Check for mistakes.
Comment on lines +153 to +155
if not checkouts_qs.exists():
self.stderr.write(f"ERROR: Checkout with id={checkout_id} not found")
exit(1)
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

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

Avoid calling exit(1) inside a Django management command; it bypasses Django’s error handling and can make failures harder to test/compose. Prefer raising CommandError (or SystemExit via sys.exit) after writing the message.

Copilot uses AI. Check for mistakes.
Comment on lines +191 to +198
processed_rows.extend(
ProcessedListingItems(
listing_item_key=get_rollup_key(t.id),
checkout_id=checkout.id,
status=simplify_status(t.status),
)
for t in test_chunk
)
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

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

This command chunks DB iteration, but still accumulates all ProcessedListingItems for the checkout in processed_rows before writing. For large checkouts this can create high memory pressure; consider bulk-upserting processed items per chunk (or flushing the list periodically) instead of buffering the full set.

Copilot uses AI. Check for mistakes.
Comment on lines +181 to +183
tests_qs = Tests.objects.filter(build_id__in=builds.keys()).select_related(
"build__checkout"
)
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

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

tests_qs uses select_related("build__checkout"), but the loop only reads fields directly on Tests and you already fetched Builds (with checkout) separately. This adds an unnecessary join and extra data transfer; consider dropping the select_related here to reduce query cost.

Suggested change
tests_qs = Tests.objects.filter(build_id__in=builds.keys()).select_related(
"build__checkout"
)
tests_qs = Tests.objects.filter(build_id__in=builds.keys())

Copilot uses AI. Check for mistakes.
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.

2 participants