From e83c7014c654bb398c4e95b11a0d001d43632717 Mon Sep 17 00:00:00 2001 From: David Miculit Date: Wed, 29 Apr 2026 17:34:11 +0300 Subject: [PATCH] feat: add alert id to duplicated summaries with the reassigned status --- treeherder/webapp/api/performance_data.py | 21 +++++++--- .../webapp/api/performance_serializers.py | 19 ++++++++- ui/perfherder/alerts/AlertHeader.jsx | 42 +++++++++++++------ 3 files changed, 61 insertions(+), 21 deletions(-) diff --git a/treeherder/webapp/api/performance_data.py b/treeherder/webapp/api/performance_data.py index be7b1038535..92f4d6a7e4d 100644 --- a/treeherder/webapp/api/performance_data.py +++ b/treeherder/webapp/api/performance_data.py @@ -571,14 +571,23 @@ def _build_duplicated_summaries_map(self, page): for push_id, framework_id in keys: q |= Q(push_id=push_id, framework_id=framework_id) rows = PerformanceAlertSummary.objects.filter(q).values( - "id", "status", "push_id", "framework_id" + "id", "status", "push_id", "framework_id", "alerts__related_summary_id" ) - result = defaultdict(list) + result_map = defaultdict(dict) for row in rows: - result[(row["push_id"], row["framework_id"])].append( - {"id": row["id"], "status": row["status"]} - ) - return dict(result) + key = (row["push_id"], row["framework_id"]) + summary_id = row["id"] + + if summary_id not in result_map[key]: + result_map[key][summary_id] = { + "id": summary_id, + "status": row["status"], + "reassigned_to": row["alerts__related_summary_id"], + } + elif row["alerts__related_summary_id"]: + result_map[key][summary_id]["reassigned_to"] = row["alerts__related_summary_id"] + + return {k: list(v.values()) for k, v in result_map.items()} def _build_tc_metadata_map(self, page): """ diff --git a/treeherder/webapp/api/performance_serializers.py b/treeherder/webapp/api/performance_serializers.py index d2ef2145670..cfcb49db58f 100644 --- a/treeherder/webapp/api/performance_serializers.py +++ b/treeherder/webapp/api/performance_serializers.py @@ -342,14 +342,29 @@ def get_duplicated_summaries(self, performance_alert_summary): for summary in duplicated_summaries_map.get(key, []) if summary["id"] != performance_alert_summary.id ] - return list( + + rows = ( PerformanceAlertSummary.objects.filter( push=performance_alert_summary.push, framework=performance_alert_summary.framework ) .exclude(id=performance_alert_summary.id) - .values("id", "status") + .values("id", "status", "alerts__related_summary_id") ) + result_map = {} + for row in rows: + summary_id = row["id"] + if summary_id not in result_map: + result_map[summary_id] = { + "id": summary_id, + "status": row["status"], + "reassigned_to": row["alerts__related_summary_id"], + } + elif row["alerts__related_summary_id"]: + result_map[summary_id]["reassigned_to"] = row["alerts__related_summary_id"] + + return list(result_map.values()) + class Meta: model = PerformanceAlertSummary fields = [ diff --git a/ui/perfherder/alerts/AlertHeader.jsx b/ui/perfherder/alerts/AlertHeader.jsx index 11bc4000324..29a3c7371cb 100644 --- a/ui/perfherder/alerts/AlertHeader.jsx +++ b/ui/perfherder/alerts/AlertHeader.jsx @@ -14,6 +14,7 @@ import { import { getJobsUrl, getPerfCompareBaseURL } from '../../helpers/url'; import { toMercurialShortDateStr } from '../../helpers/display'; import SimpleTooltip from '../../shared/SimpleTooltip'; +import Clipboard from '../../shared/Clipboard'; import Assignee from './Assignee'; import TagsList from './TagsList'; @@ -230,19 +231,34 @@ const AlertHeader = ({ {alertSummary.duplicated_summaries.length > 0 && ( Duplicated summaries: - {alertSummary.duplicated_summaries.map((summary, index) => ( - - Alert #{summary.id} - {getStatus(summary.status)} - {alertSummary.duplicated_summaries.length - 1 !== index && ', '} - - ))} + {alertSummary.duplicated_summaries.map((summary, index) => { + const isReassigned = getStatus(summary.status) === 'reassigned'; + return ( + + + Alert #{summary.id} - {getStatus(summary.status)} + {isReassigned && summary.reassigned_to && ` to #${summary.reassigned_to}`} + + {isReassigned && summary.reassigned_to && ( + + )} + {alertSummary.duplicated_summaries.length - 1 !== index && ', '} + + ); + })} )}