|
| 1 | +#!/usr/bin/env python3 |
| 2 | +############################################################################## |
| 3 | +# (c) Crown copyright Met Office. All rights reserved. |
| 4 | +# The file LICENCE, distributed with this code, contains details of the terms |
| 5 | +# under which the code may be used. |
| 6 | +############################################################################## |
| 7 | + |
| 8 | +""" |
| 9 | +Launch fortitude on list of directories. Run on all and print outputs. |
| 10 | +Fail if any style changes required. |
| 11 | +""" |
| 12 | + |
| 13 | +import sys |
| 14 | +import subprocess |
| 15 | +import argparse |
| 16 | +from pathlib import Path |
| 17 | + |
| 18 | + |
| 19 | +def launch_fortitude( |
| 20 | + config_path: Path, app_path: Path |
| 21 | +) -> subprocess.CompletedProcess[str]: |
| 22 | + """ |
| 23 | + Launch fortitude as a subprocess command and check the output |
| 24 | + """ |
| 25 | + |
| 26 | + command: list[str] = [ |
| 27 | + "fortitude", |
| 28 | + "--config-file", |
| 29 | + str(config_path), |
| 30 | + "check", |
| 31 | + str(app_path), |
| 32 | + ] |
| 33 | + result = subprocess.run(command, capture_output=True, text=True) |
| 34 | + |
| 35 | + print(result.stdout) |
| 36 | + return result |
| 37 | + |
| 38 | + |
| 39 | +if __name__ == "__main__": |
| 40 | + parser = argparse.ArgumentParser( |
| 41 | + description="Run fortitude on all applications. If " |
| 42 | + "application/fortitude.toml exists use that file, otherwise " |
| 43 | + "use one in rose-stem/app/check_fortitude_linter/file. " |
| 44 | + "Print output, raise error if any changes required." |
| 45 | + ) |
| 46 | + parser.add_argument("source", help="The top level of lfric_apps directory.") |
| 47 | + args = parser.parse_args() |
| 48 | + |
| 49 | + source_path: Path = Path(args.source) |
| 50 | + |
| 51 | + failed_apps: dict[str, str] = {} |
| 52 | + |
| 53 | + for top_dir_path in source_path.iterdir(): |
| 54 | + # e.g. applications,science,interfaces |
| 55 | + if not top_dir_path.is_dir(): # don't try to loop over files |
| 56 | + continue |
| 57 | + for app_path in top_dir_path.iterdir(): |
| 58 | + # e.g. adjoint_tests, adjoint, coupled_interface |
| 59 | + if not app_path.is_dir(): |
| 60 | + continue |
| 61 | + app_name: str = app_path.name |
| 62 | + print(f"Running on {app_name}\n") |
| 63 | + config_path: Path = app_path / "fortitude.toml" |
| 64 | + if not config_path.exists(): |
| 65 | + print( |
| 66 | + "Using universal config (toml) file." |
| 67 | + " (Some apps use their own config file.)" |
| 68 | + ) |
| 69 | + config_path: Path = ( |
| 70 | + source_path |
| 71 | + / "rose-stem" |
| 72 | + / "app" |
| 73 | + / "check_fortitude_linter" |
| 74 | + / "file" |
| 75 | + / "fortitude.toml" |
| 76 | + ) |
| 77 | + result: subprocess.CompletedProcess[str] = launch_fortitude( |
| 78 | + config_path, app_path |
| 79 | + ) |
| 80 | + if result.returncode: |
| 81 | + # prints the app run on if there are errors of any kind |
| 82 | + print(f"Checking: {app_name} \n", file=sys.stderr) |
| 83 | + if not result.stderr: |
| 84 | + # prints if no other/config errors are found |
| 85 | + print("Found lint errors:", file=sys.stderr) |
| 86 | + # prints the lint errors |
| 87 | + print(result.stdout, file=sys.stderr) |
| 88 | + if result.stderr: |
| 89 | + # prints if there are other/config errors |
| 90 | + print("Found non-lint errors: \n", file=sys.stderr) |
| 91 | + # prints the other/config errors |
| 92 | + print(result.stderr, "\n\n\n", file=sys.stderr) |
| 93 | + failed_apps[app_name] = result.stderr |
| 94 | + |
| 95 | + if failed_apps: |
| 96 | + error_message: str = "" |
| 97 | + print( |
| 98 | + "\n\n\nSummary: Fortitude found errors in the following repositories:\n", |
| 99 | + file=sys.stderr, |
| 100 | + ) |
| 101 | + for failed in failed_apps: |
| 102 | + error_message += f"{failed}\n" |
| 103 | + sys.exit(error_message) |
0 commit comments