From fc2505273f3d67a00c479926b4e03a8045d70428 Mon Sep 17 00:00:00 2001 From: Alex Finder Date: Fri, 27 Mar 2026 20:05:32 +0200 Subject: [PATCH] Filter by untriaged regressions or improvements --- .../api/test_performance_alertsummary_api.py | 108 ++++++++++++++++++ treeherder/webapp/api/performance_data.py | 16 +++ ui/perfherder/alerts/AlertsView.jsx | 6 + ui/perfherder/perf-helpers/constants.js | 2 + 4 files changed, 132 insertions(+) diff --git a/tests/webapp/api/test_performance_alertsummary_api.py b/tests/webapp/api/test_performance_alertsummary_api.py index 50333f0b46f..493bf301e4c 100644 --- a/tests/webapp/api/test_performance_alertsummary_api.py +++ b/tests/webapp/api/test_performance_alertsummary_api.py @@ -901,3 +901,111 @@ def test_alert_summaries_filter_with_assignee( summary_ids = [summary["id"] for summary in retrieved_summaries] assert summary_ids == [test_perf_alert_summary.id] + + +def test_untriaged_regressions_filter( + client, + test_perf_alert_summary, + test_perf_alert_summary_2, + test_perf_signature, + test_perf_signature_2, +): + # Summary 1: one untriaged regression alert should be returned + create_perf_alert( + summary=test_perf_alert_summary, + series_signature=test_perf_signature, + is_regression=True, + status=PerformanceAlert.UNTRIAGED, + ) + # Summary 2: one untriaged improvement alert should NOT be returned + create_perf_alert( + summary=test_perf_alert_summary_2, + series_signature=test_perf_signature_2, + is_regression=False, + status=PerformanceAlert.UNTRIAGED, + ) + + resp = client.get( + reverse("performance-alert-summaries-list"), + data={"untriaged_regressions": "true"}, + ) + assert resp.status_code == 200 + result_ids = [summary["id"] for summary in resp.json()["results"]] + assert test_perf_alert_summary.id in result_ids + assert test_perf_alert_summary_2.id not in result_ids + + +def test_untriaged_regressions_excludes_acknowledged( + client, + test_perf_alert_summary, + test_perf_signature, +): + # Acknowledged regression should NOT be returned by untriaged_regressions filter + create_perf_alert( + summary=test_perf_alert_summary, + series_signature=test_perf_signature, + is_regression=True, + status=PerformanceAlert.ACKNOWLEDGED, + ) + + resp = client.get( + reverse("performance-alert-summaries-list"), + data={"untriaged_regressions": "true"}, + ) + assert resp.status_code == 200 + result_ids = [summary["id"] for summary in resp.json()["results"]] + assert test_perf_alert_summary.id not in result_ids + + +def test_untriaged_improvements_filter( + client, + test_perf_alert_summary, + test_perf_alert_summary_2, + test_perf_signature, + test_perf_signature_2, +): + # Summary 1: one untriaged improvement alert should be returned + create_perf_alert( + summary=test_perf_alert_summary, + series_signature=test_perf_signature, + is_regression=False, + status=PerformanceAlert.UNTRIAGED, + ) + # Summary 2: one untriaged regression alert should NOT be returned + create_perf_alert( + summary=test_perf_alert_summary_2, + series_signature=test_perf_signature_2, + is_regression=True, + status=PerformanceAlert.UNTRIAGED, + ) + + resp = client.get( + reverse("performance-alert-summaries-list"), + data={"untriaged_improvements": "true"}, + ) + assert resp.status_code == 200 + result_ids = [summary["id"] for summary in resp.json()["results"]] + assert test_perf_alert_summary.id in result_ids + assert test_perf_alert_summary_2.id not in result_ids + + +def test_untriaged_improvements_excludes_acknowledged( + client, + test_perf_alert_summary, + test_perf_signature, +): + # Acknowledged improvement should NOT be returned by untriaged_improvements filter + create_perf_alert( + summary=test_perf_alert_summary, + series_signature=test_perf_signature, + is_regression=False, + status=PerformanceAlert.ACKNOWLEDGED, + ) + + resp = client.get( + reverse("performance-alert-summaries-list"), + data={"untriaged_improvements": "true"}, + ) + assert resp.status_code == 200 + result_ids = [summary["id"] for summary in resp.json()["results"]] + assert test_perf_alert_summary.id not in result_ids diff --git a/treeherder/webapp/api/performance_data.py b/treeherder/webapp/api/performance_data.py index be7b1038535..1ff9f4a0ba2 100644 --- a/treeherder/webapp/api/performance_data.py +++ b/treeherder/webapp/api/performance_data.py @@ -415,6 +415,8 @@ class PerformanceAlertSummaryFilter(django_filters.FilterSet): filter_text = django_filters.CharFilter(method="_filter_text") hide_improvements = django_filters.BooleanFilter(method="_hide_improvements") hide_related_and_invalid = django_filters.BooleanFilter(method="_hide_related_and_invalid") + untriaged_regressions = django_filters.BooleanFilter(method="_untriaged_regressions") + untriaged_improvements = django_filters.BooleanFilter(method="_untriaged_improvements") with_assignee = django_filters.CharFilter(method="_with_assignee") timerange = django_filters.NumberFilter(method="_timerange") show_sheriffed_frameworks = django_filters.BooleanFilter(method="_show_sheriffed_frameworks") @@ -481,6 +483,18 @@ def _hide_related_and_invalid(self, queryset, name, value): ] ) + def _untriaged_regressions(self, queryset, name, value): + return queryset.filter( + alerts__is_regression=True, + alerts__status=PerformanceAlert.UNTRIAGED, + ).distinct() + + def _untriaged_improvements(self, queryset, name, value): + return queryset.filter( + alerts__is_regression=False, + alerts__status=PerformanceAlert.UNTRIAGED, + ).distinct() + def _with_assignee(self, queryset, name, value): return queryset.filter(assignee__username=value) @@ -503,6 +517,8 @@ class Meta: "filter_text", "hide_improvements", "hide_related_and_invalid", + "untriaged_regressions", + "untriaged_improvements", "with_assignee", "timerange", ] diff --git a/ui/perfherder/alerts/AlertsView.jsx b/ui/perfherder/alerts/AlertsView.jsx index 3ef9974d937..29ad604d8a2 100644 --- a/ui/perfherder/alerts/AlertsView.jsx +++ b/ui/perfherder/alerts/AlertsView.jsx @@ -221,6 +221,12 @@ function AlertsView({ if (status === 'all regressions') { delete params.status; params.hide_improvements = true; + } else if (status === 'untriaged regressions') { + delete params.status; + params.untriaged_regressions = true; + } else if (status === 'untriaged improvements') { + delete params.status; + params.untriaged_improvements = true; } if (hideDownstream) { params.hide_related_and_invalid = hideDownstream; diff --git a/ui/perfherder/perf-helpers/constants.js b/ui/perfherder/perf-helpers/constants.js index f9a6196bbdc..7fe150631cf 100644 --- a/ui/perfherder/perf-helpers/constants.js +++ b/ui/perfherder/perf-helpers/constants.js @@ -84,6 +84,8 @@ export const summaryStatusMap = { fixed: 7, backedout: 8, 'all regressions': 9, + 'untriaged regressions': 10, + 'untriaged improvements': 11, }; export const alertStatusMap = {