Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion .github/workflows/build-and-push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ jobs:
registry_username: ${{ secrets.QUAY_IMAGE_SCLORG_BUILDER_USERNAME }}
registry_token: ${{ secrets.QUAY_IMAGE_SCLORG_BUILDER_TOKEN }}
dockerfile: Dockerfile.daily-tests
tag: "0.8.7"
tag: "0.8.8"
image_name: "upstream-daily-tests"
quay_application_token: ${{ secrets.QUAY_IMAGE_SCLORG_UPDATE_DESC }}
2 changes: 1 addition & 1 deletion Dockerfile.daily-tests
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ FROM quay.io/fedora/fedora:42

ENV SHARED_DIR="/var/ci-scripts" \
VERSION="42" \
RELEASE_UPSTREAM="0.8.7" \
RELEASE_UPSTREAM="0.8.8" \
UPSTREAM_TMT_REPO="https://github.com/sclorg/sclorg-testing-farm" \
UPSTREAM_TMT_DIR="sclorg-testing-farm" \
HOME="/home/nightly" \
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ shellcheck:
./run-shellcheck.sh `git ls-files *.sh`

build_images:
podman build -t quay.io/sclorg/upstream-daily-tests:0.8.7 -f Dockerfile.daily-tests .
podman build -t quay.io/sclorg/upstream-daily-tests:0.8.8 -f Dockerfile.daily-tests .
93 changes: 74 additions & 19 deletions daily_tests/daily_nightly_tests_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ def __init__(self):
self.available_test_case = TEST_CASES

def parse_args(self):
"""
Parse command line arguments.
"""
parser = argparse.ArgumentParser(
description="NightlyTestsReport program report all failures"
"over all OS and Tests (tests, test-pytest, test-openshift-pytest)."
Expand All @@ -150,11 +153,17 @@ def parse_args(self):
return parser.parse_args()

def return_plan_name(self, item) -> str:
"""
Return the plan name for a given item.
"""
return "".join(
[x[1] for x in self.available_test_case if item.startswith(x[0])]
)

def load_mails_from_environment(self):
"""
Load email addresses from environment variables.
"""
print(os.environ)
if "DB_MAILS" in os.environ:
SCLORG_MAILS["mariadb-container"] = os.environ["DB_MAILS"].split(",")
Expand Down Expand Up @@ -186,6 +195,12 @@ def load_mails_from_environment(self):
print(f"Send email: '{self.send_email}'")

def send_file_to_pastebin(self, log_path, log_name: Path):
"""
Send file to pastebin using send_to_paste_bin.sh script.
It is used for sending logs from TMT command in case of TMT failures.

:param log_path: Path to log file to send
:param log_name: Path to file where pastebin link will be stored"""
if not os.path.exists(log_path):
return
cmd = f'{SEND_PASTE_BIN} "{log_path}" "{str(log_name)}"'
Expand All @@ -200,6 +215,11 @@ def send_file_to_pastebin(self, log_path, log_name: Path):
time.sleep(1)

def get_pastebin_url(self, log_name: str) -> str:
"""
Get pastebin URL from file where send_to_paste_bin.sh
script stored it after sending logs to pastebin.
:param log_name: Path to file where pastebin link is stored
:return: URL as string or empty string if URL is not found in file"""
with open(log_name, "r") as f:
lines = f.read()

Expand All @@ -210,36 +230,51 @@ def get_pastebin_url(self, log_name: str) -> str:
return ""

def store_tmt_logs_to_dict(
self, path_dir: Path, test_case, is_running=False, not_exists=False
self,
path_dir: Path,
test_case,
is_running=False,
not_exists=False,
is_failed=False,
):
"""
Store TMT logs in a dictionary for reporting purposes.
:param path_dir: Path to the directory containing TMT logs
:param test_case: Name of the test case
:param is_running: Flag indicating if the test is still running
:param not_exists: Flag indicating if the data directory does not exist
:param is_failed: Flag indicating if the test has failed
"""
log_path = self.reports_dir / test_case / "tmt-verbose-log"
log_name = path_dir / "tmt-verbose-log.txt"
self.send_file_to_pastebin(log_path=log_path, log_name=log_name)

if not (is_running or is_failed or not_exists):
return
if not_exists:
msg = (
f"Data dir for test case {test_case} does not exist."
f"Look at log in attachment called '{test_case}-log.txt'."
)
else:
if is_running:
msg = (
f"tmt tests for case {test_case} is still running."
f"Look at log in attachment called '{test_case}-log.txt'."
)
else:
msg = (
f"tmt command has failed for test case {test_case}."
f"Look at log in attachment called '{test_case}-log.txt'."
)
if is_running:
msg = (
f"tmt tests for case {test_case} is still running."
f"Look at log in attachment called '{test_case}-log.txt'."
)
if is_failed:
msg = (
f"tmt command has failed for test case {test_case}."
f"Look at log in attachment called '{test_case}-log.txt'."
)
self.data_dict["tmt"]["msg"].append(msg)
if is_running:
dictionary_key = "tmt_running"
else:
if is_failed:
dictionary_key = "tmt_failed"
self.data_dict["tmt"][dictionary_key].append(test_case)
log_path = self.reports_dir / test_case / "tmt-verbose-log"
log_name = path_dir / "tmt-verbose-log.txt"
self.send_file_to_pastebin(log_path=log_path, log_name=log_name)
if log_name.exists():
with open(log_name) as f:
print(f.readlines())
self.data_dict["tmt"][dictionary_key].append(test_case)
self.data_dict["tmt"]["logs"].append((test_case, log_path, log_name))

def collect_data(self):
Expand Down Expand Up @@ -277,7 +312,7 @@ def collect_data(self):
# /var/tmp/daily_scl_tests/<test_case>/log.txt file
if (path_dir / "tmt_failed").exists():
print(f"tmt command has failed for test case {test_case}.")
self.store_tmt_logs_to_dict(path_dir, test_case)
self.store_tmt_logs_to_dict(path_dir, test_case, is_failed=True)
failed_tests = True
continue
data_dir = path_dir / "results"
Expand All @@ -293,7 +328,7 @@ def collect_data(self):
print(success_logs)
for suc in success_logs:
self.store_tmt_logs_to_dict(
path_dir=path_dir, test_case=test_case
path_dir=path_dir, test_case=test_case, is_failed=False
)
Comment on lines 329 to 332
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Avoid repeated pastebin uploads in success loop.

Lines [329]-[332] call store_tmt_logs_to_dict once per success log, but the call doesn’t use suc and re-sends the same TMT log repeatedly.

♻️ Suggested fix
-                    for suc in success_logs:
-                        self.store_tmt_logs_to_dict(
-                            path_dir=path_dir, test_case=test_case, is_failed=False
-                        )
+                    self.store_tmt_logs_to_dict(
+                        path_dir=path_dir,
+                        test_case=test_case,
+                    )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
for suc in success_logs:
self.store_tmt_logs_to_dict(
path_dir=path_dir, test_case=test_case
path_dir=path_dir, test_case=test_case, is_failed=False
)
self.store_tmt_logs_to_dict(
path_dir=path_dir,
test_case=test_case,
)
🧰 Tools
🪛 Ruff (0.15.2)

[warning] 329-329: Loop control variable suc not used within loop body

Rename unused suc to _suc

(B007)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@daily_tests/daily_nightly_tests_report.py` around lines 329 - 332, The loop
iterates over success_logs but never uses the loop variable suc, causing
store_tmt_logs_to_dict to be called repeatedly with the same arguments; either
move the call to store_tmt_logs_to_dict(path_dir=path_dir, test_case=test_case,
is_failed=False) out of the for suc in success_logs loop so it runs once, or if
you intended per-success-log behavior, change store_tmt_logs_to_dict to accept
the individual success entry (e.g., suc) and pass it in (update call sites and
the function signature inside store_tmt_logs_to_dict accordingly); locate and
modify the loop containing success_logs and the store_tmt_logs_to_dict
invocation to implement one of these fixes.

self.data_dict["SUCCESS_DATA"].extend(
[(test_case, str(f), str(f.name)) for f in success_logs]
Expand All @@ -313,6 +348,11 @@ def collect_data(self):
pprint.pprint(self.data_dict)

def generate_email_body(self):
"""
Generate email body based on collected data.
It contains information about failed containers
and logs from TMT command in case of TMT failures.
"""
if self.args.upstream_tests:
body_failure = "<b>NodeJS upstream tests failures:</b><br>"
body_success = (
Expand Down Expand Up @@ -346,6 +386,9 @@ def generate_email_body(self):
print(f"Body to email: {self.body}")

def generate_failed_containers(self):
"""
Generate email body for failed containers.
"""
print("GENERATE FAILED CONTAINERS")
for test_case, plan, msg in self.available_test_case:
if test_case not in self.data_dict:
Expand All @@ -365,6 +408,9 @@ def generate_failed_containers(self):
)

def generate_success_containers(self):
"""
Generate email body for successful containers.
"""
print("GENERATE SUCCESS CONTAINERS")
for test_case, cont_path, log_name in self.data_dict["SUCCESS_DATA"]:
if os.path.exists(log_name):
Expand All @@ -374,6 +420,9 @@ def generate_success_containers(self):
)

def generate_tmt_logs_containers(self):
"""
Generate email body for TMT logs.
"""
for test_case, cont_path, log_name in self.data_dict["tmt"]["logs"]:
print(f"generate_tmt_logs_containers: {test_case}, {cont_path}, {log_name}")
if os.path.exists(log_name):
Expand All @@ -390,6 +439,9 @@ def generate_tmt_logs_containers(self):
self.body += "<br>"

def generate_emails(self):
"""
Generate email list based on collected data and predefined email lists for each container.
"""
print("generate_emails: ", self.data_dict)
for test_case, plan, _ in self.available_test_case:
if test_case not in self.data_dict:
Expand All @@ -405,6 +457,9 @@ def generate_emails(self):
print(f"generate_emails: Additional emails: {DEFAULT_MAILS}")

def send_emails(self):
"""
Send emails with the test results.
"""
if not self.send_email:
print("Sending email is not allowed")
return
Expand Down
Loading