public inbox for kdevops@lists.linux.dev
 help / color / mirror / Atom feed
From: Luis Chamberlain <mcgrof@kernel.org>
To: Chuck Lever <cel@kernel.org>, Daniel Gomez <da.gomez@kruces.com>,
	kdevops@lists.linux.dev
Cc: Luis Chamberlain <mcgrof@kernel.org>
Subject: [PATCH 5/5] crash_report.py: add a crash report
Date: Sat, 19 Apr 2025 22:48:21 -0700	[thread overview]
Message-ID: <20250420054822.533987-6-mcgrof@kernel.org> (raw)
In-Reply-To: <20250420054822.533987-1-mcgrof@kernel.org>

This can be used by CIs to augment the commit log.

Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
---
 scripts/workflows/generic/crash_report.py | 109 ++++++++++++++++++++++
 1 file changed, 109 insertions(+)
 create mode 100755 scripts/workflows/generic/crash_report.py

diff --git a/scripts/workflows/generic/crash_report.py b/scripts/workflows/generic/crash_report.py
new file mode 100755
index 000000000000..10b4f958042d
--- /dev/null
+++ b/scripts/workflows/generic/crash_report.py
@@ -0,0 +1,109 @@
+#!/usr/bin/env python3
+import os
+import re
+from pathlib import Path
+
+CRASH_DIR = Path("crashes")
+ANSI_ESCAPE_RE = re.compile(r"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])")
+
+
+def clean_lines(text):
+    lines = text.splitlines()
+    cleaned = []
+    for line in lines:
+        line = ANSI_ESCAPE_RE.sub("", line)
+        line = re.sub(r"[^\x20-\x7E\t]", "", line)
+        if line.strip():
+            cleaned.append(line)
+    return "\n".join(cleaned)
+
+
+def collect_host_logs(host_path):
+    entries = []
+    files = sorted(host_path.iterdir())
+    seen_base = set()
+
+    # First pass: collect decoded crash files
+    for file in files:
+        if not file.is_file():
+            continue
+        fname = file.name
+
+        # Look for decoded crash variants first
+        for suffix in [".crash", ".crash_and_corruption"]:
+            if fname.endswith(".decoded" + suffix):
+                # Store the original filename (without .decoded) in seen_base
+                base = fname.replace(".decoded" + suffix, suffix)
+                seen_base.add(base)
+                entries.append(
+                    {
+                        "type": "crash",
+                        "file": fname,
+                        "content": clean_lines(file.read_text(errors="replace")),
+                    }
+                )
+
+    # Second pass: collect remaining files (non-decoded crashes and other types)
+    for file in files:
+        if not file.is_file():
+            continue
+        fname = file.name
+
+        # Handle undecoded crash files only if we didn't already see their decoded version
+        for suffix in [".crash", ".crash_and_corruption"]:
+            if fname.endswith(suffix) and not fname.endswith(".decoded" + suffix):
+                if fname in seen_base:
+                    continue  # decoded version already handled
+
+                seen_base.add(fname)
+                entries.append(
+                    {
+                        "type": "crash",
+                        "file": fname,
+                        "content": clean_lines(file.read_text(errors="replace")),
+                    }
+                )
+
+        # Warnings or corruption always go in
+        if fname.endswith(".warning"):
+            entries.append(
+                {
+                    "type": "warning",
+                    "file": fname,
+                    "content": clean_lines(file.read_text(errors="replace")),
+                }
+            )
+        elif fname.endswith(".corruption"):
+            entries.append(
+                {
+                    "type": "corruption",
+                    "file": fname,
+                    "content": clean_lines(file.read_text(errors="replace")),
+                }
+            )
+
+    return entries
+
+
+def generate_commit_log():
+    print("# Kernel crash report summary\n")
+    for host_dir in sorted(CRASH_DIR.iterdir()):
+        if not host_dir.is_dir():
+            continue
+        logs = collect_host_logs(host_dir)
+        if not logs:
+            continue
+        print(f"## Host: {host_dir.name}\n")
+        for entry in logs:
+            tag = entry["type"].upper()
+            print(f"### [{tag}] {entry['file']}")
+            print("```")
+            print(entry["content"])
+            print("```\n")
+
+
+if __name__ == "__main__":
+    if not CRASH_DIR.exists():
+        print(f"No crashes, filesystem corruption isues, or kernel warnings were detected on this run.")
+        exit(0)
+    generate_commit_log()
-- 
2.47.2


  parent reply	other threads:[~2025-04-20  5:48 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-04-20  5:48 [PATCH 0/5] crash: provide a crash watchdog Luis Chamberlain
2025-04-20  5:48 ` [PATCH 1/5] systemd-remote: use ip address for systemd-remote journal Luis Chamberlain
2025-04-20  5:48 ` [PATCH 2/5] crash: add kernel crash watchdog library Luis Chamberlain
2025-04-20  5:48 ` [PATCH 3/5] fstests_watchdog.py: use the new " Luis Chamberlain
2025-04-20  5:48 ` [PATCH 4/5] crash_watchdog.py: add generic crash watchdog Luis Chamberlain
2025-04-20  5:48 ` Luis Chamberlain [this message]
2025-04-20 15:19 ` [PATCH 0/5] crash: provide a " Chuck Lever
2025-04-21 23:16   ` Luis Chamberlain
2025-04-22  2:38     ` Luis Chamberlain

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250420054822.533987-6-mcgrof@kernel.org \
    --to=mcgrof@kernel.org \
    --cc=cel@kernel.org \
    --cc=da.gomez@kruces.com \
    --cc=kdevops@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox