From 28ad161062aa9b0c94536b2e0e28b5412d39694c Mon Sep 17 00:00:00 2001 From: Valentin Rigal Date: Tue, 21 Jan 2025 15:38:48 +0100 Subject: [PATCH 1/2] WIP: New endpoint to create an internal issue --- treeherder/webapp/api/internal_issue.py | 57 +++++++++++++++++++++++++ treeherder/webapp/api/urls.py | 4 ++ 2 files changed, 61 insertions(+) create mode 100644 treeherder/webapp/api/internal_issue.py diff --git a/treeherder/webapp/api/internal_issue.py b/treeherder/webapp/api/internal_issue.py new file mode 100644 index 00000000000..ba5422da0e0 --- /dev/null +++ b/treeherder/webapp/api/internal_issue.py @@ -0,0 +1,57 @@ +from datetime import timedelta + +from django.db import transaction +from django.utils import timezone +from rest_framework import generics, serializers + +from treeherder.model.models import Bugscache, FailureLine + +# Only track occurences of a bug on a specific time window +BUGSCACHE_OCCURENCES_WINDOW = timedelta(days=7) + + +class InternalIssueSerializer(serializers.Serializer): + failure_line_id = serializers.PrimaryKeyRelatedField( + write_only=True, + source="failure_line", + queryset=FailureLine.objects.all(), + ) + occurences = serializers.SerializerMethodField(read_only=True) + + def get_occurences(self, bug): + return bug.occurences.filter(created__gte=timezone.now() - BUGSCACHE_OCCURENCES_WINDOW) + + @transaction.atomic + def create(self, validated_data): + failure_line = validated_data["failure_line"] + + # TODO: Fetch all the similar failure lines + similar_failure_lines = [failure_line.id] + + # Build or retrieve a bug already reported for a similar FailureLine + bug = Bugscache.objects.filter(occurences__failure_line__in=similar_failure_lines).first() + if bug is None: + # TODO: Support writting summary field from the FailureLine information + bug = Bugscache.objects.create() + + bug.occurences.get_or_create( + user=self.context["request"].user, + failure_line=failure_line, + bug=bug, + ) + return bug + + class Meta: + model = Bugscache + fields = ["failure_line_id", "occurences"] + + +class InternalIssue(generics.CreateAPIView): + """ + Create a Bugscache entry, not necessarilly linked to a real Bugzilla ticket.µ + In case it already exists, update its occurences. + + Returns the number of occurences of this bug in the last week. + """ + + serializer_class = InternalIssueSerializer diff --git a/treeherder/webapp/api/urls.py b/treeherder/webapp/api/urls.py index f9e596c61b1..1172be69435 100644 --- a/treeherder/webapp/api/urls.py +++ b/treeherder/webapp/api/urls.py @@ -13,6 +13,7 @@ groups, infra_compare, intermittents_view, + internal_issue, investigated_test, job_log_url, jobs, @@ -175,4 +176,7 @@ ), re_path(r"^csp-report/$", csp_report.csp_report_collector, name="csp-report"), re_path(r"^schema/", get_schema_view(title="Treeherder Rest API"), name="openapi-schema"), + re_path( + r"^internal_issue/", internal_issue.CreateInternalIssue.as_view(), name="internal_issue" + ), ] From 22d704c031e35b1819f91439a460667c4a34c71b Mon Sep 17 00:00:00 2001 From: Valentin Rigal Date: Thu, 23 Jan 2025 17:33:25 +0100 Subject: [PATCH 2/2] Suggestions --- treeherder/webapp/api/internal_issue.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/treeherder/webapp/api/internal_issue.py b/treeherder/webapp/api/internal_issue.py index ba5422da0e0..2c19a6bbed9 100644 --- a/treeherder/webapp/api/internal_issue.py +++ b/treeherder/webapp/api/internal_issue.py @@ -6,7 +6,7 @@ from treeherder.model.models import Bugscache, FailureLine -# Only track occurences of a bug on a specific time window +# Only track occurrences of a bug on a specific time window BUGSCACHE_OCCURENCES_WINDOW = timedelta(days=7) @@ -16,10 +16,10 @@ class InternalIssueSerializer(serializers.Serializer): source="failure_line", queryset=FailureLine.objects.all(), ) - occurences = serializers.SerializerMethodField(read_only=True) + occurrences = serializers.SerializerMethodField(read_only=True) - def get_occurences(self, bug): - return bug.occurences.filter(created__gte=timezone.now() - BUGSCACHE_OCCURENCES_WINDOW) + def get_occurrences(self, bug): + return bug.occurrences.filter(created__gte=timezone.now() - BUGSCACHE_OCCURENCES_WINDOW) @transaction.atomic def create(self, validated_data): @@ -29,12 +29,12 @@ def create(self, validated_data): similar_failure_lines = [failure_line.id] # Build or retrieve a bug already reported for a similar FailureLine - bug = Bugscache.objects.filter(occurences__failure_line__in=similar_failure_lines).first() + bug = Bugscache.objects.filter(occurrences__failure_line__in=similar_failure_lines).first() if bug is None: # TODO: Support writting summary field from the FailureLine information bug = Bugscache.objects.create() - bug.occurences.get_or_create( + bug.occurrences.get_or_create( user=self.context["request"].user, failure_line=failure_line, bug=bug, @@ -43,15 +43,15 @@ def create(self, validated_data): class Meta: model = Bugscache - fields = ["failure_line_id", "occurences"] + fields = ["failure_line_id", "occurrences"] -class InternalIssue(generics.CreateAPIView): +class CreateInternalIssue(generics.CreateAPIView): """ - Create a Bugscache entry, not necessarilly linked to a real Bugzilla ticket.µ - In case it already exists, update its occurences. + Create a Bugscache entry, not necessarilly linked to a real Bugzilla ticket. + In case it already exists, update its occurrences. - Returns the number of occurences of this bug in the last week. + Returns the number of occurrences of this bug in the last week. """ serializer_class = InternalIssueSerializer