From d24008ae28515b84e418abe004408773ea3d5c28 Mon Sep 17 00:00:00 2001
From: Frederik Hennig <frederik.hennig@fau.de>
Date: Thu, 23 Jan 2025 14:09:17 +0100
Subject: [PATCH] nonzero exit code if there are warnings. always generate
 artifacts.

---
 .gitlab-ci.yml                  |  1 +
 utilities/clang-tidy/analyze.py | 17 +++++++++++------
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index cc3c33f17..b36f7eb19 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -2052,6 +2052,7 @@ clang-tidy:
       - cmake . -LA
       - python3 utilities/clang-tidy/analyze.py -p utilities/clang-tidy/analyze.yml -r $CI_PROJECT_DIR -c compile_commands.json -o clang-tidy-output
    artifacts:
+      when: always
       paths:
          - $CI_PROJECT_DIR/build/clang-tidy-output
    tags:
diff --git a/utilities/clang-tidy/analyze.py b/utilities/clang-tidy/analyze.py
index fa1d768f8..d3f44a687 100644
--- a/utilities/clang-tidy/analyze.py
+++ b/utilities/clang-tidy/analyze.py
@@ -53,18 +53,18 @@ WARNING_PATTERN = re.compile(r"\[[a-z-]+,-warnings-as-errors\]\n")
 TRAILING = len(",-warnings-as-errors]\n")
 
 
-def print_summary(output_file: pathlib.Path):
+def print_summary(output_file: pathlib.Path) -> tuple[bool | str]:
     clang_tidy_log = output_file.read_text()
     matches = WARNING_PATTERN.findall(clang_tidy_log)
     matches = [m[1:-TRAILING] for m in matches]
     counter = Counter(matches)
 
     if not counter:
-        return "Success! No more warnings."
+        return True, "Success! No more warnings."
 
     counts = sorted(list(counter.items()), key=lambda it: it[1], reverse=True)
     summary = "\n".join(f"{warning}: {count}" for warning, count in counts)
-    return summary
+    return False, summary
 
 
 def main():
@@ -116,6 +116,8 @@ def main():
     database_backup = database_fp.parent / f"{database_fp.name}.bak"
     shutil.copy(str(database_fp), str(database_backup))
 
+    success: bool = True
+
     try:
         with database_fp.open() as dbfile:
             orig_db = json.load(dbfile)
@@ -167,11 +169,12 @@ def main():
 
             print(f"  -- clang-tidy output written to {str(output)}")
 
-            summary = print_summary(output)
+            success, summary = print_summary(output)
             print("  -- Summary:")
             print(indent(summary, "      - "))
 
             print("\n\n", end="")
+            return success
 
         for module_spec in params.get("modules", []):
             include_paths: list[pathlib.Path] = []
@@ -187,7 +190,7 @@ def main():
                         include_paths.append(tests_dir / module_name)
             header_filter = rf".*/src/{module_name}/.*"
 
-            run_clang_tidy(
+            success = success and run_clang_tidy(
                 orig_db,
                 include_paths,
                 header_filter,
@@ -210,7 +213,7 @@ def main():
                     else:
                         include_paths = [apps_dir / app_name]
 
-            run_clang_tidy(
+            success = success and run_clang_tidy(
                 orig_db,
                 include_paths,
                 None,
@@ -222,6 +225,8 @@ def main():
         #   Restore the backup
         shutil.move(str(database_backup), str(database_fp))
 
+    exit(0 if success else 1)
+
 
 if __name__ == "__main__":
     main()
-- 
GitLab