Skip to content

Commit 7223126

Browse files
authored
Merge branch 'develop' into feature/fire_MPI
2 parents 2d8a7eb + a0fbb02 commit 7223126

58 files changed

Lines changed: 2417 additions & 1981 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/scripts/check_log_warnings_remarks.py

Lines changed: 99 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -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

145167
def 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

170216
if __name__ == "__main__": # pragma: no coverage

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,7 @@ tests/logs/log_*
8282
compile_0_time.log
8383
tests/modules.ufs_model.lua
8484
tests/ufs_common.lua
85+
86+
# Backup logs for local regression tests
87+
tests/logs/RegressionTests_*.log.bak
88+

tests/bl_date.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export BL_DATE=20260406
1+
export BL_DATE=20260417

tests/default_vars.sh

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1662,12 +1662,11 @@ export_fire_behavior() {
16621662
}
16631663

16641664

1665-
# Defaults for the coupled 5-component
1665+
# Defaults for the global coupled
16661666
export_cmeps() {
1667-
export UFS_CONFIGURE=ufs.configure.s2swa_fast.IN
1667+
export UFS_CONFIGURE=ufs.configure.s2sw_fast.IN
16681668
export med_model=cmeps
16691669
export atm_model=fv3
1670-
export chm_model=gocart
16711670
export ocn_model=mom6
16721671
export ice_model=cice6
16731672
export wav_model=ww3
@@ -1860,7 +1859,7 @@ export CPL=.true.
18601859
export CPLWAV=.true.
18611860
export CPLWAV2ATM=.true.
18621861
export USE_MED_FLUX=.false.
1863-
export CPLCHM=.true.
1862+
export CPLCHM=.false.
18641863
export CPLLND=.false.
18651864

18661865
# for FV3: default values will be changed if doing a warm-warm restart

0 commit comments

Comments
 (0)