diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index f571704fc..d0523a6b2 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -10,4 +10,5 @@ | oakleybrunt | Oakley Brunt | Met Office | 2025-12-19 | | harry-shepherd | Harry Shepherd | Met Office | 2026-01-08 | | DrTVockerodtMO | Terence Vockerodt | Met Office | 2026-01-08 | +| mo-lucy-gordon | Lucy Gordon | Met Office | 2026-01-14 | | MetBenjaminWent | Benjamin Went | Met Office | 2026-01-15 | diff --git a/applications/lfricinputs/fortitude.toml b/applications/lfricinputs/fortitude.toml new file mode 100644 index 000000000..c4e5e9ab7 --- /dev/null +++ b/applications/lfricinputs/fortitude.toml @@ -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 = ["S101"] + +output-format = "grouped" #group results by file diff --git a/rose-stem/app/check_fortitude_linter/file/fortitude.toml b/rose-stem/app/check_fortitude_linter/file/fortitude.toml new file mode 100644 index 000000000..c4e5e9ab7 --- /dev/null +++ b/rose-stem/app/check_fortitude_linter/file/fortitude.toml @@ -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 = ["S101"] + +output-format = "grouped" #group results by file diff --git a/rose-stem/app/check_fortitude_linter/rose-app.conf b/rose-stem/app/check_fortitude_linter/rose-app.conf new file mode 100644 index 000000000..452d4c196 --- /dev/null +++ b/rose-stem/app/check_fortitude_linter/rose-app.conf @@ -0,0 +1,2 @@ +[command] +default=$CYLC_WORKFLOW_RUN_DIR/bin/fortitude_launcher.py -s $SOURCE_ROOT/lfric_apps diff --git a/rose-stem/bin/fortitude_launcher.py b/rose-stem/bin/fortitude_launcher.py new file mode 100755 index 000000000..3acca0a2b --- /dev/null +++ b/rose-stem/bin/fortitude_launcher.py @@ -0,0 +1,87 @@ +#!/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 os +import subprocess +import argparse + + +def launch_fortitude(config_path, app_path): + """ + Launch fortitude as a subprocess command and check the output + """ + + command = f"fortitude --config-file {config_path} check {app_path}" + result = subprocess.run(command.split(), 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( + "-s", + "--source", + help="The top level of lfric_apps directory.", + required=True, + ) + args = parser.parse_args() + + failed_apps = {} + + for top_dir in ["applications", "science"]: + applications = os.listdir(os.path.join(args.source, top_dir)) + for app in applications: + print(f"Running on {app}\n") + app_path = os.path.join(args.source, top_dir, app) + config_path = os.path.join(app_path, "fortitude.toml") + if not os.path.exists(os.path.join(config_path)): + print("Using universal config (toml) file." + " (Some apps use their own config file.)") + config_path = os.path.join( + args.source, + "rose-stem", + "app", + "check_fortitude_linter", + "file", + "fortitude.toml", + ) + result = 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} \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] = result.stderr + + if failed_apps: + error_message = "" + 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) diff --git a/rose-stem/site/azngarch/groups.cylc b/rose-stem/site/azngarch/groups.cylc index dfd4c44d9..6a861533a 100644 --- a/rose-stem/site/azngarch/groups.cylc +++ b/rose-stem/site/azngarch/groups.cylc @@ -9,6 +9,7 @@ "scripts": [ "config_dump_checker", "style_checker", + "fortitude_linter", "extract_checker", "site_validator", "validate_rose_meta", diff --git a/rose-stem/site/meto/groups.cylc b/rose-stem/site/meto/groups.cylc index fa3a62574..2e3efc1cf 100644 --- a/rose-stem/site/meto/groups.cylc +++ b/rose-stem/site/meto/groups.cylc @@ -9,6 +9,7 @@ "scripts": [ "config_dump_checker", "style_checker", + "fortitude_linter", "extract_checker", "site_validator", "validate_rose_meta", diff --git a/rose-stem/site/nci/groups.cylc b/rose-stem/site/nci/groups.cylc index f3f6e5457..da9f508df 100644 --- a/rose-stem/site/nci/groups.cylc +++ b/rose-stem/site/nci/groups.cylc @@ -22,6 +22,7 @@ "scripts": [ "config_dump_checker", "style_checker", + "fortitude_linter", "extract_checker", "site_validator", "validate_rose_meta", diff --git a/rose-stem/site/uoe/groups.cylc b/rose-stem/site/uoe/groups.cylc index f0c011f3b..40b68874b 100644 --- a/rose-stem/site/uoe/groups.cylc +++ b/rose-stem/site/uoe/groups.cylc @@ -10,6 +10,7 @@ "scripts": [ "config_dump_checker", "style_checker", + "fortitude_linter", "extract_checker", "site_validator", ], diff --git a/rose-stem/templates/graph/populate_graph_scripts.cylc b/rose-stem/templates/graph/populate_graph_scripts.cylc index 41c90a45c..1f70d9baf 100644 --- a/rose-stem/templates/graph/populate_graph_scripts.cylc +++ b/rose-stem/templates/graph/populate_graph_scripts.cylc @@ -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 #} diff --git a/rose-stem/templates/runtime/generate_runtime_scripts.cylc b/rose-stem/templates/runtime/generate_runtime_scripts.cylc index bd602ad7c..a1ce6f61a 100644 --- a/rose-stem/templates/runtime/generate_runtime_scripts.cylc +++ b/rose-stem/templates/runtime/generate_runtime_scripts.cylc @@ -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}}