Skip to content
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
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
3 changes: 2 additions & 1 deletion CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@
| thomasmelvin | Thomas Melvin | Met Office | 2026-01-15 |
| tinyendian | Wolfgang Hayek | Earth Sciences New Zealand | 2026-02-02 |
| DanStoneMO | Daniel Stone | Met Office | 2026-02-26 |
| ericaneininger | Erica Neininger | Met Office | 2026-03-02 |
| ericaneininger | Erica Neininger | Met Office | 2026-03-02 |
| mo-lucy-gordon | Lucy Gordon | Met Office | 2026-03-11 |
11 changes: 11 additions & 0 deletions applications/lfricinputs/fortitude.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
##############################################################################
# (c) Crown copyright Met Office. All rights reserved.
# The file LICENCE, distributed with this code, contains details of the terms
# under which the code may be used.
##############################################################################

[check]
file-extensions= ["f90", "F90", "X90", "x90", "pf"] #check these file types
select = ["S101", "PORT011"]
output-format = "grouped" #group results by file

18 changes: 18 additions & 0 deletions interfaces/coupled_interface/fortitude.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
##############################################################################
# (c) Crown copyright Met Office. All rights reserved.
# The file LICENCE, distributed with this code, contains details of the terms
# under which the code may be used.
##############################################################################

[check]

file-extensions= ["f90", "F90", "X90", "x90", "pf"] #check these file types

select = ["S101", "PORT011"]

output-format = "grouped" #group results by file

[check.per-file-ignores]

"process_send_fields_2d_mod.X90" = ["S101"]
"set_r_ocean_fraction_mod.F90" = ["S101"]
18 changes: 18 additions & 0 deletions interfaces/jedi_lfric_interface/fortitude.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
##############################################################################
# (c) Crown copyright Met Office. All rights reserved.
# The file LICENCE, distributed with this code, contains details of the terms
# under which the code may be used.
##############################################################################

[check]

file-extensions= ["f90", "F90", "X90", "x90", "pf"] #check these file types

select = ["S101", "PORT011"]

output-format = "grouped" #group results by file

[check.per-file-ignores]

"jedi_lfric_linear_modeldb_driver_mod.f90" = ["S101"]
"atlas_field_interface_mod.F90" = ["S101"]
20 changes: 20 additions & 0 deletions interfaces/jules_interface/fortitude.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
##############################################################################
# (c) Crown copyright Met Office. All rights reserved.
# The file LICENCE, distributed with this code, contains details of the terms
# under which the code may be used.
##############################################################################

[check]

file-extensions= ["f90", "F90", "X90", "x90", "pf"] #check these file types

select = ["S101", "PORT011"]

output-format = "grouped" #group results by file

[check.per-file-ignores]

"update_ancils_alg_mod.x90" = ["S101"]
"jules_exp_kernel_mod.F90" = ["S101"]
"jules_extra_kernel_mod.F90" = ["S101"]
"jules_imp_kernel_mod.F90" = ["S101"]
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ contains
integer(tik) :: id

if ( LPROF ) call start_timing( id, 'jules.explicit' )

call log_event( 'slow_physics: Running explicit JULES layer', LOG_LEVEL_DEBUG )

! Cannot pass null pointers to invoke calls. Therefore non-pointer variables
Expand Down
13 changes: 13 additions & 0 deletions interfaces/physics_schemes_interface/fortitude.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
##############################################################################
# (c) Crown copyright Met Office. All rights reserved.
# The file LICENCE, distributed with this code, contains details of the terms
# under which the code may be used.
##############################################################################

[check]

file-extensions= ["f90", "F90", "X90", "x90", "pf"] #check these file types

select = ["PORT011"]

output-format = "grouped" #group results by file
19 changes: 19 additions & 0 deletions interfaces/socrates_interface/fortitude.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
##############################################################################
# (c) Crown copyright Met Office. All rights reserved.
# The file LICENCE, distributed with this code, contains details of the terms
# under which the code may be used.
##############################################################################

[check]

file-extensions= ["f90", "F90", "X90", "x90", "pf"] #check these file types

select = ["S101", "PORT011"]

output-format = "grouped" #group results by file

[check.per-file-ignores]

"init_radiation_fields_alg_mod.x90" = ["S101"]
"rad_cloud_alg_mod.x90" = ["S101"]
"lw_kernel_mod.F90" = ["S101"]
29 changes: 29 additions & 0 deletions rose-stem/app/check_fortitude_linter/file/fortitude.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
##############################################################################
# (c) Crown copyright Met Office. All rights reserved.
# The file LICENCE, distributed with this code, contains details of the terms
# under which the code may be used.
##############################################################################

[check]

file-extensions= ["f90", "F90", "X90", "x90", "pf"] #check these file types

select = ["S101", "PORT011"]

output-format = "grouped" #group results by file


# "./interfaces/coupled_interface/source/algorithm/process_send_fields_2d_mod.X90" = ["S101"]

# "./interfaces/socrates_interface*" = ["S101"]
# "../coupled_interface/*" = ["S101"]


# "./interfaces/coupled_interface/* = ["S101"]


# "../socrates_interface/*" = ["S101"]
# "physics_schemes_interface/*" = ["S101"]
# "jules_interface/*" = ["S101"]
# "jedi_lfric_interface/*" = ["S101"]

2 changes: 2 additions & 0 deletions rose-stem/app/check_fortitude_linter/rose-app.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[command]
default=$CYLC_WORKFLOW_RUN_DIR/bin/fortitude_launcher.py $SOURCE_ROOT/lfric_apps
84 changes: 84 additions & 0 deletions rose-stem/bin/fortitude_launcher.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#!/usr/bin/env python3
##############################################################################
# (c) Crown copyright Met Office. All rights reserved.
# The file LICENCE, distributed with this code, contains details of the terms
# under which the code may be used.
##############################################################################

"""
Launch fortitude on list of directories. Run on all and print outputs.
Fail if any style changes required.
"""

import sys
import subprocess
import argparse
from pathlib import Path


def launch_fortitude(config_path: Path, app_path: Path) -> subprocess.CompletedProcess[str]:
"""
Launch fortitude as a subprocess command and check the output
"""

command: list[str] = ["fortitude", "--config-file", str(config_path), "check", str(app_path)]
result = subprocess.run(command, capture_output=True, text=True)

print(result.stdout)
return result


if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Run fortitude on all applications. If "
"application/fortitude.toml exists use that file, otherwise "
"use one in rose-stem/app/check_fortitude_linter/file. "
"Print output, raise error if any changes required."
)
parser.add_argument(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be a positional argument as it's required. You can force that by removing the -s argument and changing --source to just source. Then you'll need to remove the -s from the call in the rose-app.conf

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

"source",
help="The top level of lfric_apps directory."
)
args = parser.parse_args()

source_path: Path = Path(args.source)

failed_apps: dict[str, str] = {}

for top_dir_path in source_path.iterdir(): #e.g. applications,science,interfaces
if not top_dir_path.is_dir(): # don't try to loop over files
continue
for app_path in top_dir_path.iterdir(): #e.g. adjoint_tests, adjoint, coupled_interface
if not app_path.is_dir():
continue
app_name: str = app_path.name
print(f"Running on {app_name}\n")
config_path: Path = app_path/"fortitude.toml"
if not config_path.exists():
print("Using universal config (toml) file."
" (Some apps use their own config file.)")
config_path: Path = (source_path / "rose-stem" / "app" / "check_fortitude_linter" / "file" / "fortitude.toml")
result: subprocess.CompletedProcess[str] = launch_fortitude(config_path, app_path)
if result.returncode:
# prints the app run on if there are errors of any kind
print(f"Checking: {app_name} \n", file=sys.stderr)
if not result.stderr:
# prints if no other/config errors are found
print("Found lint errors:", file=sys.stderr)
# prints the lint errors
print(result.stdout, file=sys.stderr)
if result.stderr:
# prints if there are other/config errors
print("Found non-lint errors: \n", file=sys.stderr)
# prints the other/config errors
print(result.stderr, "\n\n\n", file=sys.stderr)
failed_apps[app_name] = result.stderr


if failed_apps:
error_message: str = ""
print("\n\n\nSummary: Fortitude found errors in"
" the following repositories:\n", file=sys.stderr)
for failed in failed_apps:
error_message += f"{failed}\n"
sys.exit(error_message)
1 change: 1 addition & 0 deletions rose-stem/site/meto/groups.cylc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"scripts": [
"config_dump_checker",
"style_checker",
"fortitude_linter",
"extract_checker",
"site_validator",
"validate_rose_meta",
Expand Down
1 change: 1 addition & 0 deletions rose-stem/templates/graph/populate_graph_scripts.cylc
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
{# All other scripts have the same simple graph. These are: #}
{# * config_dump_checker #}
{# * style_checker #}
{# * fortitude_linter #}
{# * site_validator #}
{# * rose-stem_lint_checker #}
{# * validate_rose_meta #}
Expand Down
5 changes: 5 additions & 0 deletions rose-stem/templates/runtime/generate_runtime_scripts.cylc
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@
inherit={{inherit.str|upper}}
script="rose task-run --app-key=check_style"

{% elif "fortitude_linter" in task %}

inherit={{inherit.str|upper}}
script="rose task-run --app-key=check_fortitude_linter"

{% elif "extract_checker" in task %}

inherit={{inherit.str|upper}}
Expand Down
Loading