diff --git a/tests/ui/perfherder/alerts-view/alerts_test.jsx b/tests/ui/perfherder/alerts-view/alerts_test.jsx index 6a4077bc9cc..b072aba15c8 100644 --- a/tests/ui/perfherder/alerts-view/alerts_test.jsx +++ b/tests/ui/perfherder/alerts-view/alerts_test.jsx @@ -16,6 +16,7 @@ import { alertBackfillResultVisual, alertBackfillResultStatusMap, notSupportedAlertFiltersMessage, + summaryStatusMap, } from '../../../../ui/perfherder/perf-helpers/constants'; import repos from '../../mock/repositories'; import { getApiUrl } from '../../../../ui/helpers/url'; @@ -1189,6 +1190,12 @@ test('Prev push revision is displayed in dropdown', async () => { }); }); +test('"untriaged regressions" and "untriaged improvements" options appear in the status dropdown', () => { + const statusOptions = Object.keys(summaryStatusMap); + expect(statusOptions).toContain('untriaged regressions'); + expect(statusOptions).toContain('untriaged improvements'); +}); + test('Current push revision is displayed in dropdown', async () => { const { getAllByTestId } = alertsViewControls(); const pushRevision = testAlertSummaries[0].revision.slice(0, 12); diff --git a/tests/ui/perfherder/helpers.test.js b/tests/ui/perfherder/helpers.test.js index d6613d8e976..628bd3f83cf 100644 --- a/tests/ui/perfherder/helpers.test.js +++ b/tests/ui/perfherder/helpers.test.js @@ -260,6 +260,18 @@ describe('getStatus', () => { expect(result).toBe('untriaged'); }); + + it('handles untriaged regressions status', () => { + const result = getStatus(summaryStatusMap['untriaged regressions']); + + expect(result).toBe('untriaged regressions'); + }); + + it('handles untriaged improvements status', () => { + const result = getStatus(summaryStatusMap['untriaged improvements']); + + expect(result).toBe('untriaged improvements'); + }); }); describe('containsText', () => { diff --git a/tests/webapp/api/test_performance_alertsummary_api.py b/tests/webapp/api/test_performance_alertsummary_api.py index 831c2da2438..22c06fca620 100644 --- a/tests/webapp/api/test_performance_alertsummary_api.py +++ b/tests/webapp/api/test_performance_alertsummary_api.py @@ -703,3 +703,111 @@ def test_filter_text_accounts_for_related_alerts_also( assert summary_id in summary_ids # also ensure original & related summary are both fetched assert len(summary_ids) == 2 + + +def test_untriaged_regressions_filter( + client, + test_perf_alert_summary, + test_perf_alert_summary_2, + test_perf_signature, + test_perf_signature_2, +): + # Summary 1: 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: 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 + summary_ids = [summary["id"] for summary in resp.json()["results"]] + assert test_perf_alert_summary.id in summary_ids + assert test_perf_alert_summary_2.id not in summary_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 + summary_ids = [summary["id"] for summary in resp.json()["results"]] + assert test_perf_alert_summary.id not in summary_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: 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: 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 + summary_ids = [summary["id"] for summary in resp.json()["results"]] + assert test_perf_alert_summary.id in summary_ids + assert test_perf_alert_summary_2.id not in summary_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 + summary_ids = [summary["id"] for summary in resp.json()["results"]] + assert test_perf_alert_summary.id not in summary_ids diff --git a/treeherder/perf/tasks.py b/treeherder/perf/tasks.py index d5d289ee853..d3cceddb848 100644 --- a/treeherder/perf/tasks.py +++ b/treeherder/perf/tasks.py @@ -4,10 +4,7 @@ from celery.exceptions import SoftTimeLimitExceeded from treeherder.model.models import Job, JobLog -from treeherder.perf.alerts import ( - generate_new_alerts_in_series, - generate_new_test_alerts_in_series, -) +from treeherder.perf.alerts import generate_new_alerts_in_series from treeherder.perf.models import PerformanceSignature from treeherder.workers.task import retryable_task @@ -19,25 +16,25 @@ def generate_alerts(signature_id): newrelic.agent.add_custom_attribute("signature_id", str(signature_id)) signature = PerformanceSignature.objects.get(id=signature_id) generate_new_alerts_in_series(signature) - try: - generate_new_test_alerts_in_series( - signature, - voting_strategy="priority", - min_method_agreement=3, - detection_index_tolerance=1, - replicates_enabled=False, - ) - generate_new_test_alerts_in_series( - signature, - voting_strategy="equal", - min_method_agreement=3, - detection_index_tolerance=1, - replicates_enabled=False, - ) - except Exception as e: - logger.exception( - "Failed to generate test alerts for signature %s: %s", signature_id, str(e) - ) + # try: + # generate_new_test_alerts_in_series( + # signature, + # voting_strategy="priority", + # min_method_agreement=3, + # detection_index_tolerance=1, + # replicates_enabled=False, + # ) + # generate_new_test_alerts_in_series( + # signature, + # voting_strategy="equal", + # min_method_agreement=3, + # detection_index_tolerance=1, + # replicates_enabled=False, + # ) + # except Exception as e: + # logger.exception( + # "Failed to generate test alerts for signature %s: %s", signature_id, str(e) + # ) @retryable_task(name="ingest-perfherder-data", max_retries=10) diff --git a/treeherder/webapp/api/performance_data.py b/treeherder/webapp/api/performance_data.py index eb4ac27b814..d55e44c6e50 100644 --- a/treeherder/webapp/api/performance_data.py +++ b/treeherder/webapp/api/performance_data.py @@ -414,6 +414,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") @@ -480,6 +482,22 @@ def _hide_related_and_invalid(self, queryset, name, value): ] ) + def _untriaged_regressions(self, queryset, name, value): + if value: + return queryset.filter( + alerts__is_regression=True, + alerts__status=PerformanceAlert.UNTRIAGED, + ).distinct() + return queryset + + def _untriaged_improvements(self, queryset, name, value): + if value: + return queryset.filter( + alerts__is_regression=False, + alerts__status=PerformanceAlert.UNTRIAGED, + ).distinct() + return queryset + def _with_assignee(self, queryset, name, value): return queryset.filter(assignee__username=value) @@ -502,6 +520,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 dab1265c4aa..c838130e813 100644 --- a/ui/perfherder/alerts/AlertsView.jsx +++ b/ui/perfherder/alerts/AlertsView.jsx @@ -199,6 +199,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 2787567be27..f1d840e1519 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 = {