Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature #2562 version lookup documentation and automated tests #2773

Merged
merged 18 commits into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
57c2a8c
set default input version to the latest official release, which is th…
georgemccabe Oct 28, 2024
f12e3b9
per #2562, update Release Guide to include instructions for updating …
georgemccabe Nov 5, 2024
1221420
Per #2562 and #2597, replace automated test logic that used manage_ex…
georgemccabe Nov 5, 2024
5439d17
clean up SonarQube complaints
georgemccabe Nov 5, 2024
83afcde
turn on some use cases to test changes
georgemccabe Nov 5, 2024
a7cd29c
fix clone
georgemccabe Nov 5, 2024
dd0f5b5
do not get python dependencies for METplotpy/METcalcpy/METdataio inst…
georgemccabe Nov 5, 2024
ea2ea6b
use full path to package to import
georgemccabe Nov 5, 2024
67ddee6
clone METplus Analysis repos on the same level as METplus to match pr…
georgemccabe Nov 6, 2024
aa1f031
clean up linter complaints
georgemccabe Nov 6, 2024
b5d1409
turn off use cases after confirming that they run successfully
georgemccabe Nov 6, 2024
e00c62e
clean up usage statement formatting
georgemccabe Nov 6, 2024
debc3e9
remove info about updating manage_externals config files used in auto…
georgemccabe Nov 6, 2024
b9ce427
added description of component versions script to Contributor's Guide…
georgemccabe Nov 6, 2024
fc6c968
change format of example results and add text to describe what is bei…
georgemccabe Nov 6, 2024
cff594c
fix formatting
georgemccabe Nov 6, 2024
efeee53
fixed bad variable replacement
georgemccabe Nov 6, 2024
138289e
Update docs/Contributors_Guide/utilities.rst
jprestop Nov 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 90 additions & 76 deletions .github/jobs/get_use_case_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from metplus.util.string_manip import expand_int_string_to_list
from docker_utils import VERSION_EXT
from metplus import get_metplus_version
from metplus.component_versions import get_component_version

# path to METplus install location in Docker
METPLUS_DOCKER_LOC = '/metplus/METplus'
Expand All @@ -39,7 +40,7 @@
]


def handle_automation_env(host_name, reqs, work_dir):
def handle_automation_env(host_name, reqs):
# if no env is specified, use metplus base environment
conda_env = METPLUS_BASE_ENV

Expand All @@ -60,8 +61,9 @@ def handle_automation_env(host_name, reqs, work_dir):
conda_env_w_ext = f'{conda_env}{VERSION_EXT}'

# start building commands to run before run_metplus.py in Docker
setup_env = []
setup_env.append(_add_to_bashrc('# BELOW WAS ADDED BY TEST SCRIPT'))
setup_env = [
_add_to_bashrc('# BELOW WAS ADDED BY TEST SCRIPT')
]

# add conda bin to beginning of PATH
python_dir = os.path.join('/usr', 'local', 'conda', 'envs',
Expand All @@ -76,35 +78,34 @@ def handle_automation_env(host_name, reqs, work_dir):
else:
py_embed_arg = ''

# get METplus version to determine Externals file to use
# to get METplotpy/METcalcpy/METdataio
# get METplus version to determine which version of
# METplotpy/METcalcpy/METdataio to use
# If stable release, get main branch, otherwise get develop
is_stable_release = len(get_metplus_version().split('-')) == 1
externals_ext = '_stable.cfg' if is_stable_release else '.cfg'
metplus_version = get_metplus_version()

# if any metplotpy/metcalcpy keywords are in requirements list,
# add command to obtain and install METplotpy and METcalcpy
components = []
if any([item for item in PLOTCALC_KEYWORDS if item in str(reqs).lower()]):
ce_file = os.path.join(work_dir, '.github', 'parm',
f'Externals_metplotcalcpy{externals_ext}')
setup_env.extend((
f'cd {METPLUS_DOCKER_LOC}',
f'{work_dir}/manage_externals/checkout_externals -e {ce_file}',
f'{python_path} -m pip install {METPLUS_DOCKER_LOC}/../METplotpy',
f'{python_path} -m pip install {METPLUS_DOCKER_LOC}/../METcalcpy',
'cd -',
))
components.extend(('METplotpy', 'METcalcpy'))

# if metdataio is in requirements list, add command to obtain METdataio
if 'metdataio' in str(reqs).lower():
ce_file = os.path.join(work_dir, '.github', 'parm',
f'Externals_metdataio{externals_ext}')
components.append('METdataio')

setup_env.append(f'cd {METPLUS_DOCKER_LOC}/..')
for component in components:
version = get_component_version(input_component='METplus',
input_version=metplus_version,
output_component=component,
output_format='main_v{X}.{Y}',
get_dev=False)
setup_env.extend((
f'cd {METPLUS_DOCKER_LOC}',
f'{work_dir}/manage_externals/checkout_externals -e {ce_file}',
f'{python_path} -m pip install {METPLUS_DOCKER_LOC}/../METdataio',
'cd -',
'git --version',
f'git clone --single-branch --branch {version} https://github.com/dtcenter/{component}',
f'{python_path} -m pip install --no-deps {METPLUS_DOCKER_LOC}/../{component}',
))
setup_env.append('cd -')

# if metplus is in requirements list,
# add top of METplus repo to PYTHONPATH so metplus can be imported
Expand All @@ -118,7 +119,7 @@ def handle_automation_env(host_name, reqs, work_dir):
setup_env.extend((
f'echo Using environment: dtcenter/metplus-envs:{conda_env_w_ext}',
f'echo cat /usr/local/conda/envs/{conda_env_w_ext}/environments.yml',
f'echo ----------------------------------------',
'echo ----------------------------------------',
f'cat /usr/local/conda/envs/{conda_env_w_ext}/environments.yml',
'echo ----------------------------------------',
))
Expand All @@ -140,6 +141,24 @@ def main(categories, subset_list, work_dir=None,
test_suite = METplusUseCaseSuite()
test_suite.add_use_case_groups(categories, subset_list)

for group_name, use_cases_by_req in test_suite.category_groups.items():
for use_case_by_requirement in use_cases_by_req:
reqs = use_case_by_requirement.requirements

setup_env, py_embed_arg = handle_automation_env(host_name, reqs)

use_case_cmds = _get_use_case_cmds(host_name, use_case_by_requirement, work_dir, group_name, py_embed_arg)

# add commands to set up environment before use case commands
all_commands.append((setup_env, use_case_cmds, reqs))

return all_commands


def _get_use_case_cmds(host_name, use_case_by_requirement, work_dir, group_name, py_embed_arg):
# use status variable to track if any use cases failed
use_case_cmds = []

output_top_dir = os.environ.get('METPLUS_TEST_OUTPUT_BASE', '/data/output')

# use METPLUS_TEST_SETTINGS_CONF if set
Expand All @@ -150,58 +169,53 @@ def main(categories, subset_list, work_dir=None,
'parm',
'test_settings.conf')

for group_name, use_cases_by_req in test_suite.category_groups.items():
for use_case_by_requirement in use_cases_by_req:
reqs = use_case_by_requirement.requirements
if host_name != 'docker':
use_case_cmds.append('status=0')
for use_case in use_case_by_requirement.use_cases:
# add parm/use_cases path to config args if they are conf files
config_args = _get_config_args(use_case.config_args, work_dir, host_name)

output_base = os.path.join(output_top_dir,
group_name.split('-')[0],
use_case.name)
use_case_cmd = (f"run_metplus.py"
f" {' '.join(config_args)}"
f" {py_embed_arg}{test_settings_conf}"
f" config.OUTPUT_BASE={output_base}")
use_case_cmds.append(use_case_cmd)
# check exit code from use case command and
# set status to non-zero value on error
if host_name != 'docker':
use_case_cmds.append("if [ $? != 0 ]; then status=1; fi")

# if any use cases failed, force non-zero exit code with false
if host_name != 'docker':
use_case_cmds.append("if [ $status != 0 ]; then false; fi")

setup_env, py_embed_arg = handle_automation_env(host_name, reqs,
work_dir)

# use status variable to track if any use cases failed
use_case_cmds = []
if host_name != 'docker':
use_case_cmds.append('status=0')
for use_case in use_case_by_requirement.use_cases:
# add parm/use_cases path to config args if they are conf files
config_args = []
ci_overrides = None
for config_arg in use_case.config_args:
if config_arg.endswith('.conf'):
config_arg = os.path.join(work_dir, 'parm',
'use_cases', config_arg)

# look for CI overrides conf file
override_path = os.path.join(config_arg[0:-5],
'ci_overrides.conf')
if os.path.exists(override_path):
ci_overrides = override_path

config_args.append(config_arg)

# add CI overrides config file if running in docker
if ci_overrides and host_name == 'docker':
config_args.append(ci_overrides)

output_base = os.path.join(output_top_dir,
group_name.split('-')[0],
use_case.name)
use_case_cmd = (f"run_metplus.py"
f" {' '.join(config_args)}"
f" {py_embed_arg}{test_settings_conf}"
f" config.OUTPUT_BASE={output_base}")
use_case_cmds.append(use_case_cmd)
# check exit code from use case command and
# set status to non-zero value on error
if host_name != 'docker':
use_case_cmds.append("if [ $? != 0 ]; then status=1; fi")

# if any use cases failed, force non-zero exit code with false
if host_name != 'docker':
use_case_cmds.append("if [ $status != 0 ]; then false; fi")
# add commands to set up environment before use case commands
all_commands.append((setup_env, use_case_cmds, reqs))
return use_case_cmds

return all_commands

def _get_config_args(input_config_args, work_dir, host_name):
config_args = []
ci_overrides = None
for config_arg in input_config_args:
if config_arg.endswith('.conf'):
config_arg = os.path.join(work_dir, 'parm',
'use_cases', config_arg)

# look for CI overrides conf file
override_path = os.path.join(config_arg[0:-5],
'ci_overrides.conf')
if os.path.exists(override_path):
ci_overrides = override_path

config_args.append(config_arg)

# add CI overrides config file if running in docker
if ci_overrides and host_name == 'docker':
config_args.append(ci_overrides)

return config_args


def handle_command_line_args():
Expand Down Expand Up @@ -232,9 +246,9 @@ def handle_command_line_args():


if __name__ == '__main__':
categories, subset_list, _ = handle_command_line_args()
all_commands = main(categories, subset_list)
for setup_commands, use_case_commands, requirements in all_commands:
input_categories, input_subset_list, _ = handle_command_line_args()
commands = main(input_categories, input_subset_list)
for setup_commands, use_case_commands, requirements in commands:
print(f"REQUIREMENTS: {','.join(requirements)}")
if setup_commands:
command_format = ';\\\n'.join(setup_commands.split(';'))
Expand Down
9 changes: 0 additions & 9 deletions .github/parm/Externals_metdataio.cfg

This file was deleted.

9 changes: 0 additions & 9 deletions .github/parm/Externals_metdataio_stable.cfg

This file was deleted.

16 changes: 0 additions & 16 deletions .github/parm/Externals_metplotcalcpy.cfg

This file was deleted.

16 changes: 0 additions & 16 deletions .github/parm/Externals_metplotcalcpy_stable.cfg

This file was deleted.

2 changes: 1 addition & 1 deletion .github/parm/use_case_groups.json
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@
},
{
"category": "medium_range",
"index_list": "3-5,10",
"index_list": "3-5,10",
"run": false
},
{
Expand Down
1 change: 1 addition & 0 deletions docs/Contributors_Guide/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Contributor's Guide
:numbered:

coding_standards
utilities
basic_components
create_wrapper
conda_env
Expand Down
Loading