Skip to content

Commit d4cf7fc

Browse files
authored
Merge branch 'main' into Improve_umdp3_checks_I
2 parents 4266c59 + 2f6b95b commit d4cf7fc

6 files changed

Lines changed: 96 additions & 48 deletions

File tree

github_scripts/get_git_sources.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,13 @@
55
# -----------------------------------------------------------------------------
66
"""
77
Helper functions for cloning git sources in command line builds
8+
9+
Reads CONFLICT_IGNORES environment variable to get a list of comma-separated
10+
files/directories to ignore merge conflicts in. These should be relative to the
11+
top-level of the repo. If not set, then a default list is defined below.
812
"""
913

14+
import os
1015
import re
1116
import subprocess
1217
from datetime import datetime
@@ -231,17 +236,24 @@ def handle_merge_conflicts(source: str, ref: str, loc: Path, dependency: str) ->
231236
If merge conflicts are in `rose-stem/` or `dependencies.yaml` then accept the
232237
current changes and mark as resolved.
233238
If others remain then raise an error
239+
If CONFLICT_IGNORES environment variable is set, use that as a comma-separated list
240+
of files/directories to ignore. If not set, use a default list below.
234241
"""
235242

236243
# For suites, merge conflicts in these files/directories are unimportant so accept
237244
# the current changes
238-
for filepath in ("dependencies.yaml", "rose-stem"):
245+
ignores = os.environ.get(
246+
"CONFLICT_IGNORES", "dependencies.yaml,rose-stem,CONTRIBUTORS.md"
247+
).split(",")
248+
need_commit = False
249+
for filepath in ignores:
239250
full_path = loc / filepath
240251
if not full_path.exists():
241252
continue
242253
logger.warning(f"Ignoring merge conflicts in {filepath}")
243254
run_command(f"git -C {loc} checkout --ours -- {filepath}")
244-
run_command(f"git -C {loc} add {filepath}")
255+
run_command(f"git -C {loc} add -f {filepath}")
256+
need_commit = True
245257

246258
# Check if there are any remaining merge conflicts
247259
unmerged = get_unmerged(loc)
@@ -254,6 +266,10 @@ def handle_merge_conflicts(source: str, ref: str, loc: Path, dependency: str) ->
254266
"\n\nThese will need changing in the source branches to be useable together"
255267
)
256268

269+
# Need to commit the ignored conflict fixes
270+
if need_commit:
271+
run_command(f"git -C {loc} commit -m 'fix conflict'")
272+
257273

258274
def get_unmerged(loc: Path) -> list[str]:
259275
"""

lfric_macros/apply_macros.py

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#!/usr/bin/env python3
1+
#!/usr/bin/env python
22
##############################################################################
33
# (c) Crown copyright 2024 Met Office. All rights reserved.
44
# The file LICENCE, distributed with this code, contains details of the terms
@@ -249,9 +249,10 @@ def __init__(
249249
self,
250250
tag: str,
251251
cname: str | None,
252-
version: str,
252+
version: str | None,
253253
apps: Path,
254254
core: Path,
255+
jules: Path | None = None,
255256
testing: bool = False,
256257
) -> None:
257258
self.tag: str = tag
@@ -267,7 +268,8 @@ def __init__(
267268
self.root_path: Path = apps
268269
else:
269270
self.root_path: Path = get_root_path(apps)
270-
self.core_source: Path = self.get_dependency_paths(core)
271+
self.core_source: Path = self.get_dependency_paths(core, "lfric_core")
272+
self.jules_source: Path = self.get_dependency_paths(jules, "jules")
271273
self.set_rose_meta_path()
272274
if version is None:
273275
self.version: str = re.search(r".*vn(\d+\.\d+)(_.*)?", tag).group(1)
@@ -286,13 +288,15 @@ def __init__(
286288

287289
def set_rose_meta_path(self) -> None:
288290
"""
289-
Set up the ROSE_META_PATH environment variable in order to use the Core
290-
metadata. We also add the clone root path as this should allow the script to be
291-
run from anywhere.
291+
Set up the ROSE_META_PATH environment variable in order to use the Core and
292+
Jules metadata. We also add the clone root path as this should allow the script
293+
to be run from anywhere.
292294
Edit 02/2026 - remove backwards compatibility support for pre central-metadata
293295
"""
294296
rose_meta_path: str = (
295-
f"{self.root_path / 'rose-meta'}:{self.core_source / 'rose-meta'}"
297+
f"{self.root_path / 'rose-meta'}:"
298+
f"{self.core_source / 'rose-meta'}:"
299+
f"{self.jules_source / 'rose-meta'}"
296300
)
297301
os.environ["ROSE_META_PATH"] = rose_meta_path
298302

@@ -321,24 +325,23 @@ def parse_application_section(self, meta_dir: Path) -> Path:
321325
# Get Working Copy Functions
322326
############################################################################
323327

324-
def get_dependency_paths(self, source: str | None) -> Path:
328+
def get_dependency_paths(self, source: str | None, repo: str) -> Path:
325329
"""
326-
Parse the core command line arguments to get the path to a git clone.
330+
Parse the core/jules command line arguments to get the path to a git clone.
327331
If the source isn't defined, first populate the source by reading the
328332
dependencies.yaml file.
329333
If the source is a remote GitHub source clone it to a temporary location
330334
Inputs:
331335
- source, The command line argument for the source. If not set this will be
332336
None
337+
- repo, The name of the repository to clone
333338
Outputs:
334339
- The path to the source working copy to use
335340
"""
336341

337-
repo = "lfric_core"
338-
339342
# If source is None then read the dependencies.yaml file for the source
340343
if source is None:
341-
source, ref = self.read_dependencies()
344+
source, ref = self.read_dependencies(repo)
342345
if ":" in str(source):
343346
source_path = Path(source.split(":")[1]).expanduser()
344347
else:
@@ -361,7 +364,7 @@ def get_dependency_paths(self, source: str | None) -> Path:
361364
source = self.git_clone_temp(source, ref, repo)
362365
return source
363366

364-
def read_dependencies(self, repo: str = "lfric_core") -> tuple[str, str]:
367+
def read_dependencies(self, repo: str) -> tuple[str, str]:
365368
"""
366369
Read through the dependencies.yaml file for the source of the repo defined
367370
by repo. Uses self.root_path to locate the dependencies.yaml file.
@@ -1033,14 +1036,10 @@ def preprocess_macros(self, nproc: int) -> None:
10331036
if exception is not None:
10341037
executor.shutdown(wait=False, cancel_futures=True)
10351038
raise exception
1036-
print(
1037-
"[INFO] Processed macro successfully written to "
1038-
f"{
1039-
self.parse_application_section(
1040-
meta_order[write_tasks.index(task)]
1041-
)
1042-
}"
1039+
print_val = self.parse_application_section(
1040+
meta_order[write_tasks.index(task)]
10431041
)
1042+
print(f"[INFO] Processed macro successfully written to {print_val}")
10441043

10451044
############################################################################
10461045
# Upgrade Apps Functions
@@ -1265,7 +1264,15 @@ def parse_args() -> argparse.Namespace:
12651264
"--core",
12661265
default=None,
12671266
help="The LFRic Core source being used."
1268-
"Either a path to a working copy or a git source."
1267+
"Either a path to a local clone or a github source."
1268+
"If not set, will be read from the dependencies.yaml",
1269+
)
1270+
parser.add_argument(
1271+
"-j",
1272+
"--jules",
1273+
default=None,
1274+
help="The Jules source being used."
1275+
"Either a path to a local clone or a github source."
12691276
"If not set, will be read from the dependencies.yaml",
12701277
)
12711278
parser.add_argument(
@@ -1280,14 +1287,15 @@ def apply_macros_main(
12801287
version: str | None = None,
12811288
apps: Path = Path(".").absolute(),
12821289
core: str | None = None,
1290+
jules: str | None = None,
12831291
) -> None:
12841292
"""
12851293
Main function for this program
12861294
"""
12871295

12881296
check_environment()
12891297

1290-
macro_object: ApplyMacros = ApplyMacros(tag, cname, version, apps, core)
1298+
macro_object: ApplyMacros = ApplyMacros(tag, cname, version, apps, core, jules)
12911299

12921300
# Pre-process macros
12931301
banner_print("Pre-Processing Macros")
@@ -1316,4 +1324,6 @@ def apply_macros_main(
13161324

13171325
if __name__ == "__main__":
13181326
args = parse_args()
1319-
apply_macros_main(args.tag, args.cname, args.version, args.apps, args.core)
1327+
apply_macros_main(
1328+
args.tag, args.cname, args.version, args.apps, args.core, args.jules
1329+
)

lfric_macros/check_macro_chains.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,11 @@ def main() -> None:
135135

136136
source_apps = Path(os.environ["SOURCE_ROOT"]) / "lfric_apps"
137137
source_core = Path(os.environ["SOURCE_ROOT"]) / "lfric_core"
138+
source_jules = Path(os.environ["SOURCE_ROOT"]) / "jules"
138139

139-
macro_object = ApplyMacros("vn0.0_t0", None, "vn0.0", source_apps, source_core)
140+
macro_object = ApplyMacros(
141+
"vn0.0_t0", None, "vn0.0", source_apps, source_core, source_jules
142+
)
140143
apps_meta_dirs = macro_object.find_meta_dirs(macro_object.root_path / "rose-meta")
141144

142145
rose_apps = find_upgradeable_apps(

lfric_macros/release_lfric.py

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,9 @@ def copy_head_meta(meta_dirs: list[Path], apps: Path, core: Path, version: str)
241241
_ = run_command(command)
242242

243243

244-
def update_meta_import_path(meta_dirs: list[Path], version: str) -> None:
244+
def update_meta_import_path(
245+
meta_dirs: list[Path], version: str, jules_version: str
246+
) -> None:
245247
"""
246248
Change HEAD to vnX.Y in meta import statements in the newly created
247249
vnX.Y/rose-meta.conf files
@@ -261,7 +263,10 @@ def update_meta_import_path(meta_dirs: list[Path], version: str) -> None:
261263
elif in_imports and not line.strip().startswith("="):
262264
break
263265
if in_imports:
264-
line = line.replace("HEAD", version)
266+
if "jules-lfric" in line:
267+
line = line.replace("HEAD", jules_version)
268+
else:
269+
line = line.replace("HEAD", version)
265270
lines[i] = line
266271

267272
with open(meta_file, "w") as f:
@@ -412,6 +417,13 @@ def parse_args() -> argparse.Namespace:
412417
type=version_number,
413418
help="The new version number we are updating to (format X.Y)",
414419
)
420+
parser.add_argument(
421+
"-j",
422+
"--jules_version",
423+
required=True,
424+
help="The newly released version of Jules for jules-lfric metadata imports "
425+
"(format X.Y)",
426+
)
415427
parser.add_argument(
416428
"-t",
417429
"--ticket",
@@ -440,6 +452,7 @@ def parse_args() -> argparse.Namespace:
440452
args.core = args.core.expanduser().absolute()
441453
args.version = f"vn{args.version}"
442454
args.old_version = f"vn{args.old_version}"
455+
args.jules_version = f"vn{args.jules_version}"
443456

444457
return args
445458

@@ -457,29 +470,16 @@ def main() -> None:
457470

458471
set_dependency_path(args.apps, args.core)
459472

460-
# Find all metadata directories, excluing jules shared and lfric inputs as these
461-
# have metadata but no macros.
473+
# Find all metadata directories, excluing lfric-inputs as this has metadata but no
474+
# macros.
462475
exclude_dirs = (
463-
".svn",
476+
".git",
464477
"rose-stem",
465478
"integration-test",
466-
"lfric-jules-shared",
467479
"lfricinputs",
468480
)
469481
meta_dirs = find_meta_dirs([args.apps, args.core], exclude_dirs)
470482

471-
# Find JULES shared metadata directories and combine with all other metadirs for
472-
# where they are handled differently
473-
jules_meta_path = (
474-
args.apps
475-
/ "interfaces"
476-
/ "jules_interface"
477-
/ "rose-meta"
478-
/ "lfric-jules-shared"
479-
)
480-
jules_shared_meta_dirs = find_meta_dirs([jules_meta_path])
481-
meta_dirs_plus_jules = meta_dirs.union(jules_shared_meta_dirs)
482-
483483
update_version_number(args.apps, args.version)
484484

485485
update_variables_files(args.apps)
@@ -498,9 +498,9 @@ def main() -> None:
498498
)
499499
print("\n[INFO] Successfully upgraded apps")
500500

501-
copy_head_meta(meta_dirs_plus_jules, args.apps, args.core, args.version)
501+
copy_head_meta(meta_dirs, args.apps, args.core, args.version)
502502

503-
update_meta_import_path(meta_dirs, args.version)
503+
update_meta_import_path(meta_dirs, args.version, args.jules_version)
504504

505505
upgrade_file_name = copy_versions_files(
506506
meta_dirs, args.old_version, args.version, args.apps, args.core

lfric_macros/tests/test_apply_macros.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,15 @@ def __repr__(self):
7070

7171
# Create an instance of the apply_macros class
7272
# Use /tmp for Core and Jules as these are not required for testing
73-
applymacros = ApplyMacros("vn0.0_t001", None, None, TEST_APPS_DIR, Path("/tmp"), True)
73+
applymacros = ApplyMacros(
74+
tag="vn0.0_t001",
75+
cname=None,
76+
version=None,
77+
apps=TEST_APPS_DIR,
78+
core=Path("/tmp"),
79+
jules=Path("/tmp"),
80+
testing=True,
81+
)
7482

7583

7684
def test_read_versions_file():

lfric_macros/validate_rose_meta.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
INVALID_METADATA = [
2121
"jules-lfric",
2222
"jules-lsm",
23-
"lfric-jules-shared",
2423
"socrates-radiation",
2524
"um-aerosol",
2625
"um-boundary_layer",
@@ -191,6 +190,13 @@ def parse_args() -> argparse.Namespace:
191190
"required. If both are provided then it will be assumed that Apps is the "
192191
"repository to check.",
193192
)
193+
parser.add_argument(
194+
"-j",
195+
"--jules",
196+
default=None,
197+
help="The path to the JULES source required for jules-lfric & jules-shared "
198+
"metadata.",
199+
)
194200

195201
args = parser.parse_args()
196202

@@ -204,6 +210,8 @@ def parse_args() -> argparse.Namespace:
204210
args.apps = Path(args.apps).absolute().expanduser()
205211
if args.core:
206212
args.core = Path(args.core).absolute().expanduser()
213+
if args.jules:
214+
args.jules = Path(args.jules).absolute().expanduser()
207215

208216
return args
209217

@@ -229,6 +237,9 @@ def main() -> None:
229237
# Apps hasn't been set
230238
source_path = args.core
231239
rose_meta_path = f"{args.core / 'rose-meta'}"
240+
if args.jules:
241+
meta_paths += f"-M {args.jules / 'rose-meta'} "
242+
rose_meta_path += f":{args.jules / 'rose-meta'}"
232243

233244
if check_rose_metadata(rose_meta_path, source_path) or check_rose_stem_apps(
234245
meta_paths, source_path

0 commit comments

Comments
 (0)