Skip to content

Commit 175c405

Browse files
committed
Merge remote-tracking branch 'upstream/develop' into wind_vinterp_and_openmp_updates_rebased
2 parents cbb00de + de0da94 commit 175c405

28 files changed

Lines changed: 2521 additions & 2387 deletions
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
import requests
2+
from mdutils.mdutils import MdUtils
3+
import os, sys
4+
import json
5+
import re
6+
import logging
7+
8+
class APICall():
9+
"""A GitHub API call"""
10+
11+
def __init__(self, endpoint='', num_commits=1):
12+
self.token = os.environ.get('GITHUB_TOKEN')
13+
self.base_url = os.environ.get('BASE_URL')
14+
self.endpoint = endpoint
15+
self.url = f"{self.base_url}/{self.endpoint}" #Could use a path join?
16+
self.num_commits = num_commits
17+
self.header = {
18+
"Accept": "application/vnd.github.v3+json",
19+
"Authorization": f"Bearer {self.token}",
20+
"X-GitHub-Api-Version": "2022-11-28",
21+
"Accept": "application/vnd.github.raw"
22+
}
23+
24+
class Log():
25+
"""A Regression Test log file."""
26+
27+
def __init__(self, machine):
28+
"""Create the log file object for a specific machine."""
29+
self.machine = machine.lower()
30+
self.text_per_log = []
31+
32+
def call_API(self, endpoint):
33+
"""Call the GitHub API to get information about the log file."""
34+
35+
api_call = APICall(endpoint)
36+
response = requests.get(api_call.url, headers=api_call.header)
37+
if response.status_code != 200:
38+
logging.warning(response)
39+
print(response)
40+
sys.exit(1)
41+
response = json.loads(response.text)
42+
43+
return response
44+
45+
def _get_commits(self):
46+
"""Get PR head and base commits. Structure of response:
47+
response = [{"head": {"sha": "a1b2c3d..."}, "base": {"sha": "b2c3d4e..."}}]
48+
See GitHub documentation for https://docs.github.com/en/rest/commits/commits?apiVersion=2022-11-28#list-commits
49+
"""
50+
response = self.call_API(f"pulls/{os.environ.get('PR_NUM')}")
51+
self.pr_head_commit = response['head']['sha']
52+
self.pr_base_commit = response['base']['sha']
53+
54+
def _fetch_log_text(self, commit):
55+
"""For each commit of a log, extract the log text."""
56+
57+
try:
58+
api_call = APICall(f"contents/tests/logs/RegressionTests_{self.machine}.log")
59+
60+
url = api_call.url + (f"?ref={commit}") #Could use a path join?
61+
r = requests.get(url, headers=api_call.header)
62+
return r.text
63+
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+
"""
73+
74+
tests_for_log_instance = {}
75+
76+
pattern = r"COMPILE \'(.*)\' \[\d+:\d+, \d+:\d+\] \( (\d+) warnings (\d+) remarks \)"
77+
log_instance = log_instance.splitlines()
78+
79+
for line in log_instance:
80+
test_match = re.search(pattern, line)
81+
if test_match:
82+
test_name, warnings, remarks = test_match.groups()
83+
tests_for_log_instance[test_name] = (int(warnings), int(remarks))
84+
85+
return tests_for_log_instance
86+
87+
def _get_pr_data(self, commit):
88+
"""Extract warnings/remarks data for a particular commit.
89+
Returns:
90+
log_data: A dictionary of tests as the key with a tuple of (warnings, remarks) as the value
91+
"""
92+
try:
93+
log_text = self._fetch_log_text(commit)
94+
log_data = self._get_test_data(log_text)
95+
return log_data
96+
except:
97+
logging.error(f"No commit found for the ref {commit}")
98+
sys.exit(1)
99+
100+
def compare_results(self, pr_log, base_log):
101+
"""Compare warnings/remarks for PR head and base commits to determine whether warnings/remarks have increased."""
102+
103+
increases = {'warnings': {}, 'remarks': {}}
104+
105+
for test in pr_log:
106+
# Check warnings
107+
if pr_log[test][0] > base_log[test][0]:
108+
increases['warnings'].update({test: pr_log[test][0] - base_log[test][0]})
109+
# Check remarks
110+
if pr_log[test][1] > base_log[test][1]:
111+
increases['remarks'].update({test: pr_log[test][1] - base_log[test][1]})
112+
113+
return increases
114+
115+
def print_html_results(dict):
116+
"""Print the comparison results in HTML."""
117+
118+
pr_num = os.environ.get('PR_NUM')
119+
mdFile = MdUtils(file_name='summary.md', title=f'Increased Warnings/Remarks for PR #{pr_num}')
120+
121+
for machine, results in dict.items():
122+
for category in results.keys():
123+
if results[category]:
124+
mdFile.write(f"\n<h3>{machine.upper()}</h3>\n")
125+
unordered_list = [f"**{category.title()}:**", []]
126+
for test, value in dict[machine][category].items():
127+
unordered_list[1].append(f"{test}: {value}")
128+
mdFile.new_list(unordered_list, marked_with='*')
129+
return mdFile.get_md_text()
130+
131+
def main():
132+
"""For each machine, create a log object, get current PR data, and determine
133+
which tests increase warnings and/or remarks on each machine."""
134+
135+
machines = os.environ.get('MACHINES').split()
136+
137+
# For each machine, tests where warnings and/or remarks increase
138+
increased_warnings_remarks = {}
139+
140+
for machine in machines:
141+
log = Log(machine)
142+
log._get_commits()
143+
log.pr_log_data = log._get_pr_data(log.pr_head_commit)
144+
log.base_log_data = log._get_pr_data(log.pr_base_commit)
145+
146+
increased_warnings_remarks[machine] = log.compare_results(log.pr_log_data, log.base_log_data)
147+
148+
results = print_html_results(increased_warnings_remarks)
149+
150+
if len(results) > 81: # Length of HTML header
151+
print(results)
152+
sys.exit(1)
153+
else:
154+
sys.exit(0)
155+
156+
if __name__ == "__main__": # pragma: no coverage
157+
158+
main()

.github/scripts/get_data.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ def _compare_runtime(self, current_log, previous_logs):
139139

140140
for test in current_log:
141141
try:
142-
hi_rt = self.test_stats[test][0] + self.test_stats[test][1]
142+
hi_rt = self.test_stats[test][0] + (2 * self.test_stats[test][1])
143143
if current_log[test][0] > hi_rt and previous_logs['last'][test][0] > hi_rt and previous_logs['second_to_last'][test][0] > hi_rt:
144144
self.runtime_results[test] = '❌'
145145
elif current_log[test][0] > hi_rt:
@@ -157,7 +157,7 @@ def _compare_memory(self, current_log, previous_logs):
157157

158158
for test in current_log:
159159
try:
160-
hi_mem = self.test_stats[test][2] + self.test_stats[test][3]
160+
hi_mem = self.test_stats[test][2] + (2 * self.test_stats[test][3])
161161
if current_log[test][1] > hi_mem and previous_logs['last'][test][1] > hi_mem and previous_logs['second_to_last'][test][1] > hi_mem:
162162
self.memory_results[test] = '❌'
163163
elif current_log[test][1] > hi_mem:
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: Check for Increased Warnings/Remarks
2+
3+
on:
4+
pull_request:
5+
branches: [develop]
6+
push:
7+
branches: ['**']
8+
workflow_dispatch:
9+
10+
defaults:
11+
run:
12+
shell: bash -leo pipefail {0}
13+
14+
concurrency:
15+
group: ${{ github.workflow }}-${{ github.ref }}
16+
cancel-in-progress: true
17+
18+
env:
19+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
20+
MACHINES: "acorn derecho gaeac6 hera hercules orion ursa wcoss2"
21+
BASE_URL: https://api.github.com/repos/ufs-community/ufs-weather-model
22+
PR_NUM: ${{ github.event.number }}
23+
24+
jobs:
25+
check-logs:
26+
runs-on: ubuntu-latest
27+
steps:
28+
- name: Checkout feature branch
29+
uses: actions/checkout@v4
30+
- name: Install dependencies
31+
run: |
32+
pip install requests mdutils
33+
- name: Compare PR head logs with PR base logs
34+
run: |
35+
python ${{ github.workspace }}/.github/scripts/check_log_warnings_remarks.py >> $GITHUB_STEP_SUMMARY

CMEPS-interface/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ list(APPEND _ufs_util_files
3838
CMEPS/ufs/ufs_kind_mod.F90
3939
CMEPS/ufs/perf_mod.F90
4040
CMEPS/ufs/ufs_const_mod.F90
41+
CMEPS/ufs/wtracers_mod.F90
4142
${PROJECT_SOURCE_DIR}/CDEPS-interface/CDEPS/share/shr_orb_mod.F90
4243
${PROJECT_SOURCE_DIR}/CDEPS-interface/CDEPS/share/shr_const_mod.F90
4344
${PROJECT_SOURCE_DIR}/CDEPS-interface/CDEPS/share/shr_abort_mod.F90
@@ -85,7 +86,8 @@ list(APPEND _mediator_files
8586
CMEPS/mediator/med_phases_post_glc_mod.F90
8687
CMEPS/mediator/med_phases_post_rof_mod.F90
8788
CMEPS/mediator/med_phases_post_wav_mod.F90
88-
CMEPS/mediator/med_ufs_trace_wrapper.F90)
89+
CMEPS/mediator/med_ufs_trace_wrapper.F90
90+
CMEPS/mediator/med_field_info_mod.F90)
8991

9092
if(CDEPS_INLINE)
9193
list(APPEND _mediator_files CMEPS/mediator/med_phases_cdeps_mod.F90)

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ set(CMEPS OFF CACHE BOOL "Enable CMEPS")
4040
set(CDEPS OFF CACHE BOOL "Enable CDEPS")
4141
set(NOAHMP OFF CACHE BOOL "Enable NOAHMP")
4242
set(FIRE_BEHAVIOR OFF CACHE BOOL "Enable Fire Behavior")
43+
set(WARN_AS_ERROR OFF CACHE BOOL "Enable compile option to treat warning as error")
4344

4445
# Configure selected application specific components
4546
message("")
@@ -61,6 +62,7 @@ message("CDEPS ............ ${CDEPS}")
6162
message("CMEPS ............ ${CMEPS}")
6263
message("NOAHMP ........... ${NOAHMP}")
6364
message("FIRE_BEHAVIOR .... ${FIRE_BEHAVIOR}")
65+
message("WARN_AS_ERROR .... ${WARN_AS_ERROR}")
6466

6567
###############################################################################
6668
### Build Options

MOM6-interface/MOM6

Submodule MOM6 updated 369 files

MOM6-interface/mom6_files.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ list(APPEND mom6_nuopc_src_files
336336
MOM6/config_src/drivers/nuopc_cap/mom_cap_time.F90
337337
MOM6/config_src/drivers/nuopc_cap/mom_ocean_model_nuopc.F90
338338
MOM6/config_src/drivers/nuopc_cap/mom_surface_forcing_nuopc.F90
339-
MOM6/config_src/drivers/nuopc_cap/mom_ufs_trace_wrapper.F90
339+
MOM6/config_src/drivers/nuopc_cap/mom_cap_profiling.F90
340340
MOM6/config_src/drivers/nuopc_cap/mom_inline_mod.F90
341341
MOM6/config_src/drivers/nuopc_cap/mom_cap_outputlog.F90
342342
MOM6/config_src/drivers/unit_tests/test_MOM_ANN.F90

cmake/GNU.cmake

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,7 @@ else()
2323
set(CMAKE_Fortran_FLAGS_RELEASE "-O2")
2424
set(CMAKE_C_FLAGS_RELEASE "-O2")
2525
endif()
26+
27+
if(WARN_AS_ERROR)
28+
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -Werror")
29+
endif()

0 commit comments

Comments
 (0)