Skip to content

Commit

Permalink
feat: add issue version in filter
Browse files Browse the repository at this point in the history
- create a function to validate issue id and issue version for a issue
- pass issue versino in functions to validate build/test (tree and hardware)
- use formatter function to issue label
- send the issue version in frontend

Close #739
  • Loading branch information
Francisco2002 committed Jan 31, 2025
1 parent 3e2a20b commit 70754e0
Showing 10 changed files with 170 additions and 33 deletions.
4 changes: 2 additions & 2 deletions backend/kernelCI_app/helpers/commonDetails.py
Original file line number Diff line number Diff line change
@@ -5,6 +5,6 @@ def add_unfiltered_issue(
*, issue_id, issue_version, should_increment, issue_set, is_invalid
):
if issue_id is not None and issue_version is not None and should_increment:
issue_set.add(issue_id)
issue_set.add((issue_id, issue_version))
elif is_invalid is True:
issue_set.add(UNKNOWN_STRING)
issue_set.add((UNKNOWN_STRING, None))
84 changes: 72 additions & 12 deletions backend/kernelCI_app/helpers/filters.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Optional, Dict, List, Tuple, TypedDict, Literal, Any
from typing import Optional, Dict, List, Tuple, TypedDict, Literal, Any, Union
from django.http import HttpResponseBadRequest
import re
from kernelCI_app.typeModels.databases import PASS_STATUS, failure_status_list
@@ -48,13 +48,42 @@ def is_issue_from_build(*, issue_id: Optional[str], incident_test_id: Optional[s
return is_possible_build_issue


# TODO: consider issue_version in the filter
def is_issue_filtered_out(issue_id: Optional[str], issue_filters: set) -> bool:
return issue_id not in issue_filters
def verify_issue_in_filter(
issue_filter_data: Union[Dict, str],
issue_id: Optional[str],
issue_version: Optional[str]
) -> bool:
is_unknown_issue = False
if issue_filter_data == UNKNOWN_STRING:
filter_issue_id = UNKNOWN_STRING
filter_issue_version = None
is_unknown_issue = True
else:
filter_issue_id, filter_issue_version = issue_filter_data

is_issue_id_in_filter = filter_issue_id == issue_id
is_issue_version_filter = is_unknown_issue or filter_issue_version == issue_version

return is_issue_id_in_filter and is_issue_version_filter


def is_issue_filtered_out(
*,
issue_id: Optional[str],
issue_filters: set,
issue_version: Optional[str]
) -> bool:
in_filter = any(verify_issue_in_filter(issue, issue_id, issue_version) for issue in issue_filters)
return not in_filter


def should_filter_test_issue(
issue_filters: set, issue_id: Optional[str], incident_test_id: Optional[str], test_status: Optional[str]
*,
issue_filters: set,
issue_id: Optional[str],
issue_version: Optional[str],
incident_test_id: Optional[str],
test_status: Optional[str]
) -> bool:
has_issue_filter = len(issue_filters) > 0
if not has_issue_filter:
@@ -74,7 +103,11 @@ def should_filter_test_issue(
if is_exclusively_build_issue_result:
issue_id = UNKNOWN_STRING

is_issue_filtered_out_result = is_issue_filtered_out(issue_id, issue_filters)
is_issue_filtered_out_result = is_issue_filtered_out(
issue_id=issue_id,
issue_version=issue_version,
issue_filters=issue_filters
)

return is_issue_filtered_out_result

@@ -83,8 +116,9 @@ def should_filter_build_issue(
*,
issue_filters: set,
issue_id: Optional[str],
issue_version: Optional[str],
incident_test_id: Optional[str],
build_valid: Optional[bool],
build_valid: Optional[bool]
) -> bool:
has_issue_filter = len(issue_filters) > 0
if not has_issue_filter:
@@ -104,7 +138,11 @@ def should_filter_build_issue(
if is_exclusively_test_issue_result:
issue_id = UNKNOWN_STRING

is_issue_filtered_out_result = is_issue_filtered_out(issue_id, issue_filters)
is_issue_filtered_out_result = is_issue_filtered_out(
issue_id=issue_id,
issue_version=issue_version,
issue_filters=issue_filters
)

return is_issue_filtered_out_result

@@ -290,7 +328,17 @@ def _handle_build_duration(self, current_filter: ParsedFilter) -> None:

def _handle_issues(self, current_filter: ParsedFilter) -> None:
tab = current_filter["field"].split(".")[0]
self.filterIssues[tab].add(current_filter["value"])

filter_value = current_filter["value"]
if filter_value == UNKNOWN_STRING:
self.filterIssues[tab].add((UNKNOWN_STRING, None))
else:
issue_data = filter_value.split(",")

issue_id = ','.join(issue_data[:-1])
issue_version = issue_data[-1]

self.filterIssues[tab].add((issue_id, int(issue_version)))

def _handle_platforms(self, current_filter: ParsedFilter) -> None:
tab = current_filter["field"].split(".")[0]
@@ -410,6 +458,7 @@ def is_build_filtered_out(
duration: Optional[int],
valid: Optional[bool],
issue_id: Optional[str],
issue_version: Optional[str],
incident_test_id: Optional[str],
) -> bool:
return (
@@ -436,8 +485,9 @@ def is_build_filtered_out(
should_filter_build_issue(
issue_filters=self.filterIssues["build"],
issue_id=issue_id,
issue_version=issue_version,
incident_test_id=incident_test_id,
build_valid=valid,
build_valid=valid
)
)
)
@@ -493,6 +543,7 @@ def is_boot_filtered_out(
status: Optional[str],
duration: Optional[int],
issue_id: Optional[str] = None,
issue_version: Optional[str] = None,
incident_test_id: Optional[str] = "incident_test_id",
platform: Optional[str] = None,
) -> bool:
@@ -517,7 +568,11 @@ def is_boot_filtered_out(
and (toIntOrDefault(duration, 0) < self.filterBootDurationMin)
)
or should_filter_test_issue(
self.filterIssues["boot"], issue_id, incident_test_id, status
issue_filters=self.filterIssues["boot"],
issue_id=issue_id,
issue_version=issue_version,
incident_test_id=incident_test_id,
test_status=status
)
or (
len(self.filterPlatforms["boot"]) > 0
@@ -535,6 +590,7 @@ def is_test_filtered_out(
status: Optional[str],
duration: Optional[int],
issue_id: Optional[str] = None,
issue_version: Optional[str] = None,
incident_test_id: Optional[str] = "incident_test_id",
platform: Optional[str] = None,
) -> bool:
@@ -559,7 +615,11 @@ def is_test_filtered_out(
and (toIntOrDefault(duration, 0) < self.filterTestDurationMin)
)
or should_filter_test_issue(
self.filterIssues["test"], issue_id, incident_test_id, status
issue_filters=self.filterIssues["test"],
issue_id=issue_id,
issue_version=issue_version,
incident_test_id=incident_test_id,
test_status=status
)
or (
len(self.filterPlatforms["test"]) > 0
4 changes: 4 additions & 0 deletions backend/kernelCI_app/helpers/hardwareDetails.py
Original file line number Diff line number Diff line change
@@ -746,6 +746,7 @@ def decide_if_is_build_in_filter(
valid=build["valid"],
duration=build["duration"],
issue_id=build["issue_id"],
issue_version=build["issue_version"],
incident_test_id=incident_test_id,
)
return is_build_not_processed and not is_build_filtered_out_result
@@ -764,6 +765,7 @@ def decide_if_is_test_in_filter(
duration = record["duration"]
path = record["path"]
issue_id = record["incidents__issue__id"]
issue_version = record["incidents__issue__version"]
incidents_test_id = record["incidents__test_id"]
platform = env_misc_value_or_default(
handle_environment_misc(record["environment_misc"])
@@ -775,6 +777,7 @@ def decide_if_is_test_in_filter(
duration=duration,
path=path,
issue_id=issue_id,
issue_version=issue_version,
incident_test_id=incidents_test_id,
platform=platform,
)
@@ -784,6 +787,7 @@ def decide_if_is_test_in_filter(
duration=duration,
path=path,
issue_id=issue_id,
issue_version=issue_version,
incident_test_id=incidents_test_id,
platform=platform,
)
4 changes: 4 additions & 0 deletions backend/kernelCI_app/helpers/treeDetails.py
Original file line number Diff line number Diff line change
@@ -378,6 +378,7 @@ def process_boots_issue(instance, row_data):

def decide_if_is_build_filtered_out(instance, row_data):
issue_id = row_data["issue_id"]
issue_version = row_data["issue_version"]
build_valid = row_data["build_valid"]
build_duration = row_data["build_duration"]
incident_test_id = row_data["incident_test_id"]
@@ -386,6 +387,7 @@ def decide_if_is_build_filtered_out(instance, row_data):
valid=build_valid,
duration=build_duration,
issue_id=issue_id,
issue_version=issue_version,
incident_test_id=incident_test_id,
)
return is_build_filtered_out
@@ -395,12 +397,14 @@ def decide_if_is_boot_filtered_out(instance, row_data):
test_status = row_data["test_status"]
test_duration = row_data["test_duration"]
issue_id = row_data["issue_id"]
issue_version = row_data["issue_version"]
test_path = row_data["test_path"]
incident_test_id = row_data["incident_test_id"]

return instance.filters.is_boot_filtered_out(
duration=test_duration,
issue_id=issue_id,
issue_version=issue_version,
path=test_path,
status=test_status,
incident_test_id=incident_test_id,
23 changes: 17 additions & 6 deletions backend/kernelCI_app/unitTests/treeDetails.test.py
Original file line number Diff line number Diff line change
@@ -7,23 +7,34 @@ class TestShouldFilterTestIssue(unittest.TestCase):

def test_no_issue_filters(self):
self.assertFalse(
should_filter_test_issue(set(), UNKNOWN_STRING, "incident_test_1", "FAIL")
should_filter_test_issue(
issue_filters=set(),
issue_id=UNKNOWN_STRING,
issue_version=None,
incident_test_id="incident_test_1",
test_status="FAIL"
)
)

def test_unknown_filter_with_exclusively_build_issue(self):
self.assertTrue(
should_filter_test_issue(
{UNKNOWN_STRING}, "issue1", "incident_test_1", "PASS"
issue_filters={UNKNOWN_STRING},
issue_id="issue1",
issue_version="1",
incident_test_id="incident_test_1",
test_status="PASS"
)
)

def test_unknown_issue_but_not_from_test(self):
self.assertFalse(
should_filter_test_issue(
{UNKNOWN_STRING},
"maestro:72697a4efbbd0eff7080781839b405bbf0902f79",
None,
"FAIL",
issue_filters={UNKNOWN_STRING},
issue_id="maestro:72697a4efbbd0eff7080781839b405bbf0902f79",
issue_version='0',
incident_test_id=None,
test_status="FAIL",
)
)

33 changes: 27 additions & 6 deletions backend/kernelCI_app/views/treeCommitsHistory.py
Original file line number Diff line number Diff line change
@@ -76,7 +76,8 @@ def sanitize_rows(self, rows: Dict) -> List:
"test_id": row[15],
"incidents_id": row[16],
"incidents_test_id": row[17],
"issue_id": row[18]
"issue_id": row[18],
"issue_version": row[19],
}
for row in rows
]
@@ -111,13 +112,15 @@ def _process_builds_count(
duration: int,
commit_hash: str,
issue_id: str,
issue_version: str,
incident_test_id: Optional[str],
) -> None:
is_filtered_out = self.filterParams.is_build_filtered_out(
duration=duration,
valid=build_valid,
issue_id=issue_id,
incident_test_id=incident_test_id,
issue_version=issue_version,
incident_test_id=incident_test_id
)
if is_filtered_out:
return
@@ -136,11 +139,13 @@ def _process_boots_count(
test_duration: int,
test_path: str,
issue_id: str,
issue_version: str,
incident_test_id: str
) -> None:
is_boot_filter_out = self.filterParams.is_boot_filtered_out(
duration=test_duration,
issue_id=issue_id,
issue_version=issue_version,
path=test_path,
status=test_status,
incident_test_id=incident_test_id
@@ -163,11 +168,13 @@ def _process_nonboots_count(
test_duration: int,
test_path: str,
issue_id: str,
issue_version: str,
incident_test_id: str
) -> None:
is_nonboot_filter_out = self.filterParams.is_test_filtered_out(
duration=test_duration,
issue_id=issue_id,
issue_version=issue_version,
path=test_path,
status=test_status,
incident_test_id=incident_test_id
@@ -226,6 +233,7 @@ def _process_tests(self, row: Dict) -> None:
test_duration = row["test_duration"]
test_path = row["test_path"]
issue_id = row["issue_id"]
issue_version = row["issue_version"]
incident_test_id = row["incidents_test_id"]
build_valid = row["build_valid"]

@@ -248,6 +256,7 @@ def _process_tests(self, row: Dict) -> None:
test_duration=test_duration,
test_path=test_path,
issue_id=issue_id,
issue_version=issue_version,
incident_test_id=incident_test_id
)
else:
@@ -258,18 +267,29 @@ def _process_tests(self, row: Dict) -> None:
test_duration=test_duration,
test_path=test_path,
issue_id=issue_id,
issue_version=issue_version,
incident_test_id=incident_test_id
)

def _process_builds(self, row: Dict) -> None:
if row["build_id"] is not None and row["build_id"] not in self.processed_builds:
build_id = row["build_id"]
issue_id = row["issue_id"]
issue_version = row["issue_version"]

if len(self.filterParams.filterIssues['build']) > 0:
key = f"{build_id}_{issue_id}_{issue_version}"
else:
key = build_id

if build_id is not None and key not in self.processed_builds:
commit_hash = row["git_commit_hash"]
self.processed_builds.add(row["build_id"])
self.processed_builds.add(key)
self._process_builds_count(
build_valid=row["build_valid"],
duration=row["build_duration"],
commit_hash=commit_hash,
issue_id=row['issue_id'],
issue_id=issue_id,
issue_version=issue_version,
incident_test_id=row['incidents_test_id']
)

@@ -432,7 +452,8 @@ def get(self, request, commit_hash):
t.id AS test_id,
ic.id AS incidents_id,
ic.test_id AS incidents_test_id,
i.id AS issues_id
i.id AS issues_id,
i.version AS issues_version
FROM earliest_commits AS c
INNER JOIN builds AS b
ON
Loading

0 comments on commit 70754e0

Please sign in to comment.