This is an automated email from the ASF dual-hosted git repository.

davidarthur pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/kafka.git


The following commit(s) were added to refs/heads/trunk by this push:
     new bb24d8596e1 MINOR Fixup develocity report (#19179)
bb24d8596e1 is described below

commit bb24d8596e1a33358a5ebcdaf41ef707aa656b1e
Author: David Arthur <[email protected]>
AuthorDate: Tue Mar 18 10:17:44 2025 -0400

    MINOR Fixup develocity report (#19179)
    
    After our recent build task changes, this report no longer works. This
    patch fixes the script to use the new test task and tags.
    
    Reviewers: Chia-Ping Tsai <[email protected]>
---
 .github/scripts/develocity_reports.py | 110 +++++++++++++++++++++-------------
 1 file changed, 70 insertions(+), 40 deletions(-)

diff --git a/.github/scripts/develocity_reports.py 
b/.github/scripts/develocity_reports.py
index 8502c774d75..2d30cbffa55 100644
--- a/.github/scripts/develocity_reports.py
+++ b/.github/scripts/develocity_reports.py
@@ -191,7 +191,13 @@ class TestAnalyzer:
                 provider.save_cache(self.build_cache)
                 logger.info(f"Saved cache to {provider.__class__.__name__}")
 
-    def build_query(self, project: str, chunk_start: datetime, chunk_end: 
datetime, test_type: str) -> str:
+    def build_query(
+            self,
+            project: str,
+            chunk_start: datetime,
+            chunk_end: datetime,
+            test_tags: List[str]
+        ) -> str:
         """
         Constructs the query string to be used in both build info and test 
containers API calls.
         
@@ -199,19 +205,30 @@ class TestAnalyzer:
             project: The project name.
             chunk_start: The start datetime for the chunk.
             chunk_end: The end datetime for the chunk.
-            test_type: The type of tests to query.
+            test_tags: A list of tags to include.
         
         Returns:
             A formatted query string.
         """
-        return f'project:{project} buildStartTime:[{chunk_start.isoformat()} 
TO {chunk_end.isoformat()}] gradle.requestedTasks:{test_type} tag:github 
tag:trunk'
+        test_tags.append("+github")
+        tags = []
+        for tag in test_tags:
+            if tag.startswith("+"):
+                tags.append(f"tag:{tag[1:]}")
+            elif tag.startswith("-"):
+                tags.append(f"-tag:{tag[1:]}")
+            else:
+                raise ValueError("Tag should include + or - to indicate 
inclusion or exclusion.")
+
+        tags = " ".join(tags)
+        return f"project:{project} buildStartTime:[{chunk_start.isoformat()} 
TO {chunk_end.isoformat()}] gradle.requestedTasks:test {tags}"
     
     def process_chunk(
         self,
         chunk_start: datetime,
         chunk_end: datetime,
         project: str,
-        test_type: str,
+        test_tags: List[str],
         remaining_build_ids: set | None,
         max_builds_per_request: int
     ) -> Dict[str, BuildInfo]:
@@ -219,7 +236,7 @@ class TestAnalyzer:
         chunk_builds = {}
         
         # Use the helper method to build the query
-        query = self.build_query(project, chunk_start, chunk_end, test_type)
+        query = self.build_query(project, chunk_start, chunk_end, test_tags)
         
         # Initialize pagination for this chunk
         from_build = None
@@ -292,14 +309,23 @@ class TestAnalyzer:
             time.sleep(0.5)  # Rate limiting between pagination requests
             
         return chunk_builds
-    def get_build_info(self, build_ids: List[str] = None, project: str = None, 
test_type: str = None, query_days: int = None, bypass_cache: bool = False, 
fetch_all: bool = False) -> Dict[str, BuildInfo]:
+
+    def get_build_info(
+            self,
+            build_ids: List[str] = None,
+            project: str = None,
+            test_tags: List[str] = None,
+            query_days: int = None,
+            bypass_cache: bool = False,
+            fetch_all: bool = False
+    ) -> Dict[str, BuildInfo]:
         builds = {}
         max_builds_per_request = 100
         cutoff_date = datetime.now(pytz.UTC) - timedelta(days=query_days)
         current_time = datetime.now(pytz.UTC)
         
         if not fetch_all and not build_ids:
-            raise ValueError("Either build_ids must be provided or fetch_all 
must be True")
+            raise ValueError(f"Either build_ids must be provided or fetch_all 
must be True: {build_ids} {fetch_all}")
         
         # Get builds from cache if available and bypass_cache is False
         if not bypass_cache and self.build_cache:
@@ -353,7 +379,7 @@ class TestAnalyzer:
                     chunk[0], 
                     chunk[1], 
                     project, 
-                    test_type, 
+                    test_tags,
                     remaining_build_ids.copy() if remaining_build_ids else 
None,
                     max_builds_per_request
                 ): chunk for chunk in chunks
@@ -385,8 +411,15 @@ class TestAnalyzer:
             self._save_cache()
         
         return builds
-    def get_test_results(self, project: str, threshold_days: int, test_type: 
str = "quarantinedTest",
-                        outcomes: List[str] = None) -> List[TestResult]:
+
+    def get_test_results(
+        self,
+        project: str,
+        threshold_days: int,
+        test_tags: List[str],
+        outcomes: List[str] = None
+    ) -> List[TestResult]:
+
         """Fetch test results with timeline information"""
         if outcomes is None:
             outcomes = ["failed", "flaky"]
@@ -408,7 +441,7 @@ class TestAnalyzer:
             logger.debug(f"Processing chunk: {chunk_start} to {chunk_end}")
             
             # Use the helper method to build the query
-            query = self.build_query(project, chunk_start, chunk_end, 
test_type)
+            query = self.build_query(project, chunk_start, chunk_end, 
test_tags)
             
             query_params = {
                 'query': query,
@@ -452,7 +485,10 @@ class TestAnalyzer:
         logger.debug(f"Total unique build IDs collected: {len(build_ids)}")
         
         # Fetch build information using the updated get_build_info method
-        builds = self.get_build_info(list(build_ids), project, test_type, 
threshold_days)
+        print(build_ids)
+        print(list(build_ids))
+
+        builds = self.get_build_info(list(build_ids), project, test_tags, 
threshold_days)
         logger.debug(f"Retrieved {len(builds)} builds from API")
         logger.debug(f"Retrieved build IDs: {sorted(builds.keys())}")
 
@@ -549,7 +585,7 @@ class TestAnalyzer:
                                 "kafka", 
                                 chunk_start,
                                 current_time,
-                                test_type="quarantinedTest"
+                                test_tags=["+trunk", "+flaky"]
                             )
                             
                             problematic_tests[result.name] = {
@@ -570,7 +606,7 @@ class TestAnalyzer:
         project: str,
         chunk_start: datetime,
         chunk_end: datetime,
-        test_type: str = "quarantinedTest"
+        test_tags: List[str]
     ) -> List[TestCaseResult]:
         """
         Fetch detailed test case results for a specific container.
@@ -580,10 +616,10 @@ class TestAnalyzer:
             project: The project name
             chunk_start: Start time for the query
             chunk_end: End time for the query
-            test_type: Type of tests to query (default: "quarantinedTest")
+            test_tags: List of tags to query
         """
         # Use the helper method to build the query, similar to get_test_results
-        query = self.build_query(project, chunk_start, chunk_end, test_type)
+        query = self.build_query(project, chunk_start, chunk_end, test_tags)
         
         query_params = {
             'query': query,
@@ -612,7 +648,7 @@ class TestAnalyzer:
                         build_ids.update(ids)
             
             # Get build info for all build IDs
-            builds = self.get_build_info(list(build_ids), project, test_type, 
7)  # 7 days for test cases
+            builds = self.get_build_info(list(build_ids), project, test_tags, 
7)  # 7 days for test cases
             
             for test in content:
                 outcome_data = test['outcomeDistribution']
@@ -741,7 +777,7 @@ class TestAnalyzer:
                             project,
                             chunk_start,
                             current_time,
-                            test_type="quarantinedTest"
+                            test_tags=["+trunk", "+flaky"]
                         )
                         
                         # Only include if all test cases are also passing 
consistently
@@ -845,7 +881,7 @@ class TestAnalyzer:
                         "kafka",
                         chunk_start,
                         current_time,
-                        test_type="test"
+                        test_tags=["+trunk", "-flaky"]
                     )
                     
                     failing_test_cases = {}
@@ -880,14 +916,13 @@ class TestAnalyzer:
         
         return persistent_failures
 
-def get_develocity_class_link(class_name: str, threshold_days: int, test_type: 
str = None) -> str:
+def get_develocity_class_link(class_name: str, threshold_days: int) -> str:
     """
     Generate Develocity link for a test class
     
     Args:
         class_name: Name of the test class
         threshold_days: Number of days to look back in search
-        test_type: Type of test (e.g., "quarantinedTest", "test")
     """
     base_url = "https://develocity.apache.org/scans/tests";
     params = {
@@ -895,15 +930,13 @@ def get_develocity_class_link(class_name: str, 
threshold_days: int, test_type: s
         "search.tags": "github,trunk",
         "search.timeZoneId": "UTC",
         "search.relativeStartTime": f"P{threshold_days}D",
-        "tests.container": class_name
+        "tests.container": class_name,
+        "search.tasks": "test"
     }
-    
-    if test_type:
-        params["search.tasks"] = test_type
         
     return f"{base_url}?{'&'.join(f'{k}={requests.utils.quote(str(v))}' for k, 
v in params.items())}"
 
-def get_develocity_method_link(class_name: str, method_name: str, 
threshold_days: int, test_type: str = None) -> str:
+def get_develocity_method_link(class_name: str, method_name: str, 
threshold_days: int) -> str:
     """
     Generate Develocity link for a test method
     
@@ -911,7 +944,6 @@ def get_develocity_method_link(class_name: str, 
method_name: str, threshold_days
         class_name: Name of the test class
         method_name: Name of the test method
         threshold_days: Number of days to look back in search
-        test_type: Type of test (e.g., "quarantinedTest", "test")
     """
     base_url = "https://develocity.apache.org/scans/tests";
     
@@ -925,15 +957,13 @@ def get_develocity_method_link(class_name: str, 
method_name: str, threshold_days
         "search.timeZoneId": "UTC",
         "search.relativeStartTime": f"P{threshold_days}D",
         "tests.container": class_name,
-        "tests.test": method_name
+        "tests.test": method_name,
+        "search.tasks": "test"
     }
-    
-    if test_type:
-        params["search.tasks"] = test_type
         
     return f"{base_url}?{'&'.join(f'{k}={requests.utils.quote(str(v))}' for k, 
v in params.items())}"
 
-def print_most_problematic_tests(problematic_tests: Dict[str, Dict], 
threshold_days: int, test_type: str = None):
+def print_most_problematic_tests(problematic_tests: Dict[str, Dict], 
threshold_days: int):
     """Print a summary of the most problematic tests"""
     print("\n## Most Problematic Tests")
     if not problematic_tests:
@@ -949,7 +979,7 @@ def print_most_problematic_tests(problematic_tests: 
Dict[str, Dict], threshold_d
     for test_name, details in sorted(problematic_tests.items(), 
                                    key=lambda x: x[1]['failure_rate'],
                                    reverse=True):
-        class_link = get_develocity_class_link(test_name, threshold_days, 
test_type=test_type)
+        class_link = get_develocity_class_link(test_name, threshold_days)
         print(f"<tr><td colspan=\"4\">{test_name}</td><td><a 
href=\"{class_link}\">↗️</a></td></tr>")
         
         for test_case in sorted(details['test_cases'],
@@ -958,7 +988,7 @@ def print_most_problematic_tests(problematic_tests: 
Dict[str, Dict], threshold_d
                               reverse=True):
             method_name = test_case.name.split('.')[-1]
             if method_name != 'N/A':
-                method_link = get_develocity_method_link(test_name, 
test_case.name, threshold_days, test_type="quarantinedTest")
+                method_link = get_develocity_method_link(test_name, 
test_case.name, threshold_days)
                 total_runs = test_case.outcome_distribution.total
                 failure_rate = (test_case.outcome_distribution.failed + 
test_case.outcome_distribution.flaky) / total_runs if total_runs > 0 else 0
                 print(f"<tr><td></td><td>{method_name}</td>"
@@ -1107,7 +1137,7 @@ def print_persistent_failing_tests(persistent_failures: 
Dict[str, Dict], thresho
     
     print("</details>")
 
-def print_cleared_tests(cleared_tests: Dict[str, Dict], threshold_days: int, 
test_type: str = None):
+def print_cleared_tests(cleared_tests: Dict[str, Dict], threshold_days: int):
     """Print tests that are ready to be unquarantined"""
     print("\n## Cleared Tests (Ready for Unquarantine)")
     if not cleared_tests:
@@ -1127,7 +1157,7 @@ def print_cleared_tests(cleared_tests: Dict[str, Dict], 
threshold_days: int, tes
     for test_name, details in sorted(cleared_tests.items(),
                                    key=lambda x: x[1]['success_rate'],
                                    reverse=True):
-        class_link = get_develocity_class_link(test_name, threshold_days, 
test_type=test_type)
+        class_link = get_develocity_class_link(test_name, threshold_days)
         print(f"<tr><td colspan=\"5\">{test_name}</td><td><a 
href=\"{class_link}\">↗️</a></td></tr>")
         print(f"<tr><td></td><td>Class Overall</td>"
               f"<td>{details['success_rate']:.2%}</td>"
@@ -1207,13 +1237,13 @@ def main():
         quarantined_results = analyzer.get_test_results(
             PROJECT, 
             threshold_days=QUARANTINE_THRESHOLD_DAYS,
-            test_type="quarantinedTest"
+            test_tags=["+trunk", "+flaky", "-new"]
         )
         
         regular_results = analyzer.get_test_results(
             PROJECT,
             threshold_days=7,  # Last 7 days for regular tests
-            test_type="test"
+            test_tags=["+trunk", "-flaky", "-new"]
         )
         
         # Generate reports
@@ -1249,10 +1279,10 @@ def main():
         print(f"This report was run on 
{datetime.now(pytz.UTC).strftime('%Y-%m-%d %H:%M:%S')} UTC")
         
         # Print each section
-        print_most_problematic_tests(problematic_tests, 
QUARANTINE_THRESHOLD_DAYS, test_type="quarantinedTest")
+        print_most_problematic_tests(problematic_tests, 
QUARANTINE_THRESHOLD_DAYS)
         print_flaky_regressions(flaky_regressions, QUARANTINE_THRESHOLD_DAYS)
         print_persistent_failing_tests(persistent_failures, 
QUARANTINE_THRESHOLD_DAYS)
-        print_cleared_tests(cleared_tests, QUARANTINE_THRESHOLD_DAYS, 
test_type="quarantinedTest")
+        print_cleared_tests(cleared_tests, QUARANTINE_THRESHOLD_DAYS)
 
     except Exception as e:
         logger.exception("Error occurred during report generation")

Reply via email to