Skip to content

Commit 9a8a4ba

Browse files
committed
Detect E3SM-Unified version and dev labels in deployment
To share infrastructure, the functions for detecting the E3SM-Unified version and building a list of dev labels has been moved to `shared.py`, which is now symlinked into the recipe directory and used in `build_packages.py`
1 parent cbc3e2a commit 9a8a4ba

File tree

4 files changed

+103
-74
lines changed

4 files changed

+103
-74
lines changed

e3sm_supported_machines/bootstrap.py

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from shared import (
1515
check_call,
1616
get_conda_base,
17+
get_rc_dev_labels,
1718
install_miniforge3,
1819
parse_args,
1920
)
@@ -132,24 +133,20 @@ def build_env(is_test, recreate, compiler, mpi, conda_mpi, version,
132133

133134
if is_test:
134135

135-
nco_dev = ('alpha' in nco_spec or 'beta' in nco_spec)
136-
137136
channels = '--override-channels'
138137
if local_conda_build is not None:
139138
channels = f'{channels} -c {local_conda_build}'
140139

141-
if nco_dev:
142-
channels = f'{channels} -c conda-forge/label/nco_dev'
143-
for package in ['moab']:
144-
spec = config.get('spack_specs', package)
145-
if 'rc' in spec.lower():
146-
channels = f'{channels} -c conda-forge/label/{package}_dev'
147-
148-
# edit if not using a release candidate for a given package
149-
dev_labels = ['e3sm_unified', 'chemdyg', 'e3sm_diags',
150-
'mpas_analysis', 'zppy', 'zstash']
151-
for package in dev_labels:
152-
channels = f'{channels} -c conda-forge/label/{package}_dev'
140+
meta_yaml_path = os.path.join(
141+
os.path.dirname(__file__),
142+
"..",
143+
"recipes",
144+
"e3sm-unified",
145+
"meta.yaml"
146+
)
147+
dev_labels = get_rc_dev_labels(meta_yaml_path)
148+
for dev_label in dev_labels:
149+
channels = f'{channels} -c conda-forge/label/{dev_label}'
153150
channels = f'{channels} ' \
154151
f'-c conda-forge '
155152
else:

e3sm_supported_machines/shared.py

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,28 @@
88
try:
99
from urllib.request import urlopen, Request
1010
except ImportError:
11+
# For Python 2 compatibility
1112
from urllib2 import urlopen, Request
1213

14+
LABELS = {
15+
"chemdyg": "chemdyg_dev",
16+
"e3sm_diags": "e3sm_diags_dev",
17+
"e3sm_to_cmip": "e3sm_to_cmip_dev",
18+
"mache": "mache_dev",
19+
"moab": "moab_dev",
20+
"mpas-analysis": "mpas_analysis_dev",
21+
"mpas_tools": "mpas_tools_dev",
22+
"nco": "nco_dev",
23+
"xcdat": "xcdat_dev",
24+
"zppy": "zppy_dev",
25+
"zstash": "zstash_dev",
26+
}
27+
1328

1429
def parse_args(bootstrap):
1530
parser = argparse.ArgumentParser(
1631
description='Deploy E3SM-Unified')
17-
parser.add_argument("--version", dest="version", default="1.11.1",
32+
parser.add_argument("--version", dest="version",
1833
help="The version of E3SM-Unified to deploy")
1934
parser.add_argument("--conda", dest="conda_base",
2035
help="Path for the conda base")
@@ -56,6 +71,16 @@ def parse_args(bootstrap):
5671
raise ValueError('You must supply both or neither of '
5772
'--mache_fork and --mache_branch')
5873

74+
if args.version is None:
75+
meta_yaml_path = os.path.join(
76+
os.path.dirname(__file__),
77+
"..",
78+
"recipes",
79+
"e3sm-unified",
80+
"meta.yaml"
81+
)
82+
args.version = get_version_from_meta(meta_yaml_path)
83+
5984
return args
6085

6186

@@ -125,3 +150,64 @@ def get_conda_base(conda_base, config, shared):
125150
# handle "~" in the path
126151
conda_base = os.path.abspath(os.path.expanduser(conda_base))
127152
return conda_base
153+
154+
155+
def get_rc_dev_labels(meta_yaml_path):
156+
"""Parse meta.yaml and return a list of dev labels for RC dependencies."""
157+
158+
# a rare case where module-level imports are not a good idea because
159+
# the deploy_e3sm_unified.py script may be called from an environment
160+
# where jinja2 and yaml are not installed.
161+
import yaml
162+
from jinja2 import Template
163+
164+
labels_dict = LABELS
165+
166+
# Render the jinja template with dummy/default values
167+
with open(meta_yaml_path) as f:
168+
template_text = f.read()
169+
# Provide dummy/default values for all jinja variables used in meta.yaml
170+
template = Template(template_text)
171+
rendered = template.render(
172+
mpi='mpich', # or any valid value
173+
py='310', # or any valid value
174+
CONDA_PY='310', # used in build string
175+
)
176+
meta = yaml.safe_load(rendered)
177+
dev_labels = []
178+
run_reqs = meta.get("requirements", {}).get("run", [])
179+
for req in run_reqs:
180+
# req can be a string like "pkgname version" or just "pkgname"
181+
if isinstance(req, str):
182+
parts = req.split()
183+
pkg = parts[0]
184+
version = " ".join(parts[1:]) if len(parts) > 1 else ""
185+
186+
# NCO is special: it has a dev label for alpha/beta versions
187+
if pkg == "nco" and ('alpha' in version or 'beta' in version):
188+
label = labels_dict[pkg]
189+
if label not in dev_labels:
190+
dev_labels.append(label)
191+
192+
# Only match 'rc' in version, not in pkg name
193+
if "rc" in version and pkg in labels_dict:
194+
label = labels_dict[pkg]
195+
if label not in dev_labels:
196+
dev_labels.append(label)
197+
return dev_labels
198+
199+
200+
def get_version_from_meta(meta_yaml_path):
201+
"""Parse the version from the {% set version = ... %} line in meta.yaml."""
202+
with open(meta_yaml_path) as f:
203+
for line in f:
204+
if line.strip().startswith("{% set version"):
205+
# e.g., {% set version = "1.11.1rc1" %}
206+
parts = line.split("=")
207+
if len(parts) >= 2:
208+
version = (
209+
parts[1].strip().strip('%}').strip().strip(
210+
'"').strip("'")
211+
)
212+
return version
213+
raise ValueError("Could not find version in meta.yaml")

recipes/e3sm-unified/build_packages.py

Lines changed: 4 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,10 @@
33
import shutil
44
import subprocess
55
import argparse
6+
67
from jinja2 import Template
7-
import yaml
8-
9-
LABELS = {
10-
"chemdyg": "chemdyg_dev",
11-
"e3sm_diags": "e3sm_diags_dev",
12-
"e3sm_to_cmip": "e3sm_to_cmip_dev",
13-
"mache": "mache_dev",
14-
"mpas-analysis": "mpas_analysis_dev",
15-
"mpas_tools": "mpas_tools_dev",
16-
"xcdat": "xcdat_dev",
17-
"zppy": "zppy_dev",
18-
"zstash": "zstash_dev",
19-
}
8+
9+
from shared import get_rc_dev_labels, get_version_from_meta
2010

2111
DEV_PYTHON_VERSIONS = ["3.10"]
2212
DEV_MPI_VERSIONS = ["nompi", "hpc"]
@@ -46,51 +36,6 @@ def generate_matrix_files(dev):
4636
return matrix_files
4737

4838

49-
def get_rc_dev_labels(meta_yaml_path, labels_dict):
50-
"""Parse meta.yaml and return a list of dev labels for RC dependencies."""
51-
# Render the jinja template with dummy/default values
52-
with open(meta_yaml_path) as f:
53-
template_text = f.read()
54-
# Provide dummy/default values for all jinja variables used in meta.yaml
55-
template = Template(template_text)
56-
rendered = template.render(
57-
mpi='mpich', # or any valid value
58-
py='310', # or any valid value
59-
CONDA_PY='310', # used in build string
60-
)
61-
meta = yaml.safe_load(rendered)
62-
dev_labels = []
63-
run_reqs = meta.get("requirements", {}).get("run", [])
64-
for req in run_reqs:
65-
# req can be a string like "pkgname version" or just "pkgname"
66-
if isinstance(req, str):
67-
parts = req.split()
68-
pkg = parts[0]
69-
version = " ".join(parts[1:]) if len(parts) > 1 else ""
70-
# Only match 'rc' in version, not in pkg name
71-
if "rc" in version and pkg in labels_dict:
72-
label = labels_dict[pkg]
73-
if label not in dev_labels:
74-
dev_labels.append(label)
75-
return dev_labels
76-
77-
78-
def get_version_from_meta(meta_yaml_path):
79-
"""Parse the version from the {% set version = ... %} line in meta.yaml."""
80-
with open(meta_yaml_path) as f:
81-
for line in f:
82-
if line.strip().startswith("{% set version"):
83-
# e.g., {% set version = "1.11.1rc1" %}
84-
parts = line.split("=")
85-
if len(parts) >= 2:
86-
version = (
87-
parts[1].strip().strip('%}').strip().strip(
88-
'"').strip("'")
89-
)
90-
return version
91-
raise ValueError("Could not find version in meta.yaml")
92-
93-
9439
def main():
9540
parser = argparse.ArgumentParser(
9641
description="Build E3SM-Unified conda packages."
@@ -118,7 +63,7 @@ def main():
11863

11964
dev_labels = []
12065
if dev:
121-
dev_labels = get_rc_dev_labels(meta_yaml_path, LABELS)
66+
dev_labels = get_rc_dev_labels(meta_yaml_path)
12267

12368
channels = []
12469
for label in dev_labels:

recipes/e3sm-unified/shared.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../e3sm_supported_machines/shared.py

0 commit comments

Comments
 (0)