@@ -35,8 +35,7 @@ def call_API(self, endpoint):
3535 api_call = APICall (endpoint )
3636 response = requests .get (api_call .url , headers = api_call .header )
3737 if response .status_code != 200 :
38- logging .warning (response )
39- print (response )
38+ logging .error (f"{ response } : API call failed for { api_call .url } " )
4039 sys .exit (1 )
4140 response = json .loads (response .text )
4241
@@ -61,44 +60,37 @@ def _fetch_log_text(self, commit):
6160 r = requests .get (url , headers = api_call .header )
6261 return r .text
6362 except :
64- logging .error ("An appropriate commit(s) was not provided. Call _get_commits() first." )
65-
66- def _get_test_data (self , log_instance ):
67- """For each instance of a log at a given commit, extract runtime and memory data from the log text
68- Args:
69- log_instance: Log text for a given commit
70- Returns:
71- tests_for_log_instance: A dictionary of tests (keys) with a tuple of warnings and remarks as the value for each test
72- """
63+ logging .error (f"No commit found for the ref { commit } " )
64+ sys .exit (1 )
7365
74- tests_for_log_instance = {}
66+ def _get_data (self , log_text , pattern , handler , to_clean = True ):
67+ """Extract data on warnings, remarks, and failed compiles/tests
68+ Args:
69+ log_text: Text from a log file at a given commit
70+ pattern: regex pattern to match
71+ handler: function indicating how to handle the incoming data
72+ to_clean: Flag indicating whether the data needs to be cleaned (True) or not (False)
73+ """
7574
76- # Use non-capturing groups in pattern to indicate warnings/remarks may or may not be present.
77- pattern = r"COMPILE \'(.*)\' \[\d+:\d+, \d+:\d+\](?: \( (?:(\d+) warnings)?\s*(?:(\d+) remarks)? \))?"
75+ data = {}
7876
79- log_instance = log_instance .splitlines ()
77+ log_text = log_text .splitlines ()
8078
81- for line in log_instance :
79+ for line in log_text :
8280 test_match = re .search (pattern , line )
8381 if test_match :
84- test_name , warnings , remarks = test_match .groups ()
85- tests_for_log_instance [test_name ] = (warnings , remarks )
82+ handler (data , * test_match .groups ())
83+
84+ if to_clean :
85+ data = self ._clean_data (data )
86+
87+ return data
8688
87- return tests_for_log_instance
89+ def handle_warn_rmk (self , data_dict , test_name , warnings , remarks ):
90+ data_dict .update ({test_name : (warnings , remarks )})
8891
89- def _get_pr_data (self , commit ):
90- """Extract warnings/remarks data for a particular commit.
91- Returns:
92- log_data: A dictionary of tests as the key with a tuple of (warnings, remarks) as the value
93- """
94- try :
95- log_text = self ._fetch_log_text (commit )
96- log_data = self ._get_test_data (log_text )
97- log_data = self ._clean_data (log_data )
98- return log_data
99- except :
100- logging .error (f"No commit found for the ref { commit } " )
101- sys .exit (1 )
92+ def handle_failures (self , data_dict , reason , test ):
93+ data_dict .setdefault (reason , []).append (test )
10294
10395 def _clean_data (self , test_data ):
10496 """Convert None values to zeros in the test_data dictionary"""
@@ -126,45 +118,99 @@ def compare_results(self, pr_log, base_log):
126118
127119 return increases
128120
129- def print_html_results (dict ):
130- """Print the comparison results in HTML."""
121+ def print_html_results (data_dict , title , file_name ):
122+ """Print results in HTML format.
123+
124+ Args:
125+ data_dict: Dictionary with structure {machine: {category: tests, ...}, ...}
126+ where values can be either:
127+ - A dict with {test: count, ...} (for warnings/remarks)
128+ - A list of tests (for failures)
129+ title: Title for the markdown file
130+ file_name: Name for the markdown file
131+
132+ Returns:
133+ Formatted markdown string
134+ """
135+ mdFile = MdUtils (file_name = file_name , title = title )
136+
137+ for machine , machine_data in data_dict .items ():
138+ # Skip if there is no data for the machine (cases: (1) where all RTs pass on the machine or (2) there is no increase in warnings & remarks)
139+ if not machine_data :
140+ continue
141+
142+ # Skip if all categories (warnings/remarks/failure reasons) are empty
143+ if all (not category for category in machine_data .values ()):
144+ continue
145+
146+ mdFile .write (f"\n <h3>{ machine .upper ()} </h3>\n " )
147+
148+ for category , tests in machine_data .items ():
149+ # Skip printing info if there are no tests listed for a given category
150+ if not tests :
151+ continue
152+
153+ unordered_list = [f"**{ category .title ()} :**" , []]
154+
155+ # Handle both dict (warnings/remarks) and list (failures)
156+ if isinstance (tests , dict ):
157+ for test , count in tests .items ():
158+ unordered_list [1 ].append (f"{ test } : { count } " )
159+ else : # list
160+ for test in tests :
161+ unordered_list [1 ].append (test )
162+
163+ mdFile .new_list (unordered_list , marked_with = '*' )
131164
132- pr_num = os .environ .get ('PR_NUM' )
133- mdFile = MdUtils (file_name = 'summary.md' , title = f'Increased Warnings/Remarks for PR #{ pr_num } ' )
134-
135- for machine , results in dict .items ():
136- for category in results .keys ():
137- if results [category ]:
138- mdFile .write (f"\n <h3>{ machine .upper ()} </h3>\n " )
139- unordered_list = [f"**{ category .title ()} :**" , []]
140- for test , value in dict [machine ][category ].items ():
141- unordered_list [1 ].append (f"{ test } : { value } " )
142- mdFile .new_list (unordered_list , marked_with = '*' )
143165 return mdFile .get_md_text ()
144166
145167def main ():
146168 """For each machine, create a log object, get current PR data, and determine
147169 which tests increase warnings and/or remarks on each machine."""
148170
149171 machines = os .environ .get ('MACHINES' ).split ()
172+ # Use non-capturing groups in pattern to indicate warnings/remarks may or may not be present.
173+ compile_pattern = r"COMPILE \'(.*)\' \[\d+:\d+, \d+:\d+\](?: \( (?:(\d+) warnings)?\s*(?:(\d+) remarks)? \))?"
174+ # failure_pattern = r"^(?:FAILED|SKIPPED): (?!UNABLE TO (?:COMPLETE COMPARISON|START TEST))(.+?) -- (?:TEST|COMPILE) '([^']+)"
175+ failure_pattern = r"^(?:FAILED|SKIPPED): (.+?) -- (?:TEST|COMPILE) '([^']+)"
176+
150177
151- # For each machine, tests where warnings and/or remarks increase
178+ # For each machine, increased_warnings_remarks records where warnings and/or remarks increase
152179 increased_warnings_remarks = {}
180+ # For each machine, failures records which tests fail by reason
181+ failures = {}
153182
154183 for machine in machines :
155184 log = Log (machine )
156185 log ._get_commits ()
157- log .pr_log_data = log ._get_pr_data (log .pr_head_commit )
158- log .base_log_data = log ._get_pr_data (log .pr_base_commit )
159-
160- increased_warnings_remarks [machine ] = log .compare_results (log .pr_log_data , log .base_log_data )
186+ log .pr_log_text = log ._fetch_log_text (log .pr_head_commit )
187+ log .pr_warn_rmk = log ._get_data (log .pr_log_text , compile_pattern , log .handle_warn_rmk )
188+ log .pr_failures = log ._get_data (log .pr_log_text , failure_pattern , log .handle_failures , to_clean = False )
161189
162- results = print_html_results (increased_warnings_remarks )
190+ log .base_log_text = log ._fetch_log_text (log .pr_base_commit )
191+ log .base_warn_rmk = log ._get_data (log .base_log_text , compile_pattern , log .handle_warn_rmk )
192+
193+ increased_warnings_remarks [machine ] = log .compare_results (log .pr_warn_rmk , log .base_warn_rmk )
194+ failures [machine ] = log .pr_failures
163195
164- if len (results ) > 81 : # Length of HTML header
165- print (results )
196+ pr_num = os .environ .get ('PR_NUM' )
197+ warn_rmk_results = print_html_results (increased_warnings_remarks ,
198+ f"Increased Warnings/Remarks for PR #{ pr_num } " ,
199+ "warn_rmk.md" )
200+ failure_results = print_html_results (failures ,
201+ f"Compile and Test Failures for PR #{ pr_num } " ,
202+ "failures.md" )
203+
204+ if len (warn_rmk_results .splitlines ()) > 3 : # HTML header is 3 lines long
205+ print (warn_rmk_results )
206+ if len (failure_results .splitlines ()) > 3 :
207+ print (failure_results )
166208 sys .exit (1 )
209+ elif len (failure_results .splitlines ()) > 3 :
210+ print (failure_results )
211+ sys .exit (0 )
167212 else :
213+ print (f"No increase in warnings or remarks. All RTs passed." )
168214 sys .exit (0 )
169215
170216if __name__ == "__main__" : # pragma: no coverage
0 commit comments