Skip to content

Fix full error log file upload and inline rendering for non-changepoi…#122

Merged
vishnuchalla merged 1 commit into
redhat-performance:mainfrom
mmnabeel317:fix/restore-error-log-file-upload
Jul 6, 2026
Merged

Fix full error log file upload and inline rendering for non-changepoi…#122
vishnuchalla merged 1 commit into
redhat-performance:mainfrom
mmnabeel317:fix/restore-error-log-file-upload

Conversation

@mmnabeel317

@mmnabeel317 mmnabeel317 commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Restores the full_errors.txt file attachment for non-changepoint failures (logjuicer, logmine, cluster-operator error paths) which was broken since 0b73e6c
  • Sanitizes uploaded file content so Slack renders it as an inline expandable snippet instead of a binary download card

Root Cause

The needs_file condition in _send_error_logs_preview() used and to gate on errors_for_file != errors_preview. For all non-changepoint failure paths, full_errors_for_file is None, so errors_for_file falls back to errors_preview — making them identical and needs_file always False. No file was ever uploaded for these failures, even when the preview truncated the content.

Found by: Testing BugZooka against real Prow failures on a test Slack channel. A ROSA cluster install failure and a telco virt-6nodes orion-report failure both showed truncated previews with no full log attached. Tracing the code and git history (git show 0b73e6c) revealed the regression — the original condition was needs_file = len(errors_for_file) > preview_limit which worked correctly, but was changed to an and gate that silently broke non-changepoint uploads.

Rendering fix found by: After restoring the file upload, certain jobs rendered the file as a binary download card instead of an inline snippet. Testing with multiple real Prow jobs identified three categories of non-text content in build logs that trigger Slack's binary detection:

  • ANSI escape codes (\x1b[1m, \x1b[31m) from Prow colored output
  • Control characters from broken/corrupted log streams
  • Emojis (🔍, 👋) logged by tools like kube-burner

Changes

File Change
bugzooka/integrations/slack_fetcher.py andor in needs_file condition; sanitize file upload content (strip ANSI, control chars, emojis)

Behavior

Scenario Before After
Long non-CP error (logjuicer/logmine/build log) No file upload File uploaded (inline snippet)
Cluster operator errors (long) No file upload File uploaded (inline snippet)
CP with report summary (different content) File uploaded Unchanged
CP without report summary (short, fits preview) No upload Unchanged
Short non-CP error (fits in preview) No upload Unchanged

Test plan

  • All 96 existing tests pass
  • Tested on Slack: changepoint failure (aws-5.0 payload-control-plane-6nodes) — inline snippet with viz links
  • Tested on Slack: non-CP failure (metal-5.0 daily-virt-6nodes, missing clusteroperators.json) — file now uploaded, inline
  • Tested on Slack: non-CP failure (rosa-4.22 build-farm-114nodes, ANSI codes in build log) — file now uploaded, inline
  • Tested on Slack: non-CP failure (metal-5.0 virt-density-nomount, emojis in kube-burner log) — file now uploaded, inline
  • Verified content sanitization preserves all log text, timestamps, error messages, JSON, URLs — only invisible formatting and decorative characters removed

/cc @vishnuchalla

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Enterprise

Run ID: b42979bf-1c75-4668-8498-d7c98738e3f8

📥 Commits

Reviewing files that changed from the base of the PR and between 6bbca27 and cdef80c.

📒 Files selected for processing (1)
  • bugzooka/integrations/slack_fetcher.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • bugzooka/integrations/slack_fetcher.py

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes
    • Improved error log sharing so the full log is uploaded more reliably when the preview differs from the full content or exceeds the preview limit.
    • Removed terminal escape/formatting codes from uploaded error logs to make shared logs cleaner and easier to read.

Walkthrough

The PR updates SlackMessageFetcher so full error logs are uploaded when preview text differs or exceeds the limit, and strips ANSI escape sequences from log content before uploading.

Changes

Slack Error Log Handling

Layer / File(s) Summary
Preview and upload logic
bugzooka/integrations/slack_fetcher.py
needs_file now uses an OR-based condition for full-log uploads, and _upload_full_error_log uploads sanitized content with ANSI escape codes removed.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the main change: restoring full error log uploads and adjusting Slack rendering.
Description check ✅ Passed The description clearly relates to the Slack log upload and sanitization changes in this pull request.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
bugzooka/integrations/slack_fetcher.py (1)

302-305: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Preview text isn't sanitized the same way.

ANSI codes are stripped from the uploaded file content but not from errors_log_preview used in the chat message (Line 248). If preview content can also contain ANSI escapes, the inline message will still render raw control codes while the uploaded file is clean.

♻️ Suggested consistency fix
+ANSI_ESCAPE_RE = re.compile(r'\x1b\[[0-9;]*[a-zA-Z]')
+
 ...
-        errors_log_preview = errors_preview[:preview_limit]
+        errors_log_preview = ANSI_ESCAPE_RE.sub('', errors_preview[:preview_limit])
 ...
-        clean_content = re.sub(r'\x1b\[[0-9;]*[a-zA-Z]', '', content)
+        clean_content = ANSI_ESCAPE_RE.sub('', content)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@bugzooka/integrations/slack_fetcher.py` around lines 302 - 305, The preview
text used in the Slack message is not sanitized consistently with the uploaded
file content. Update the SlackFetcher flow in the same area that cleans content
before files_upload_v2 so that errors_log_preview is passed through the same
ANSI-stripping logic before it is inserted into the chat message, keeping the
preview and attachment rendering consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@bugzooka/integrations/slack_fetcher.py`:
- Line 243: The needs_file check in SlackFetcher is too broad because
errors_for_file != errors_preview can force file uploads even when the
changepoint is still short; tighten the condition around needs_file so only logs
exceeding preview_limit or otherwise requiring truncation upload a file. Add a
changepoint test covering the short-but-different case in
slack_fetcher/SlackFetcher to verify that a short changepoint does not
unexpectedly attach a file.

---

Nitpick comments:
In `@bugzooka/integrations/slack_fetcher.py`:
- Around line 302-305: The preview text used in the Slack message is not
sanitized consistently with the uploaded file content. Update the SlackFetcher
flow in the same area that cleans content before files_upload_v2 so that
errors_log_preview is passed through the same ANSI-stripping logic before it is
inserted into the chat message, keeping the preview and attachment rendering
consistent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Enterprise

Run ID: e3f71a19-96b2-4995-b55e-d178d28aa1d0

📥 Commits

Reviewing files that changed from the base of the PR and between 1e50f20 and 6bbca27.

📒 Files selected for processing (1)
  • bugzooka/integrations/slack_fetcher.py

needs_file = errors_for_file != errors_preview and (
is_changepoint or len(errors_for_file) > preview_limit
)
needs_file = errors_for_file != errors_preview or len(errors_for_file) > preview_limit

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Look for tests covering changepoint short-report file-upload behavior
rg -n "changepoint" -g '*test*' -C5 bugzooka

Repository: redhat-performance/BugZooka

Length of output: 165


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== relevant file outline ==\n'
ast-grep outline bugzooka/integrations/slack_fetcher.py --view expanded || true

printf '\n== surrounding lines around the condition ==\n'
nl -ba bugzooka/integrations/slack_fetcher.py | sed -n '210,330p'

printf '\n== test references to slack_fetcher / file upload behavior ==\n'
rg -n "slack_fetcher|needs_file|errors_preview|errors_for_file|preview_limit|upload a file|changepoint" bugzooka -g '*test*' -C 3 || true

Repository: redhat-performance/BugZooka

Length of output: 1183


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== file size ==\n'
wc -l bugzooka/integrations/slack_fetcher.py

printf '\n== function/method map for slack_fetcher ==\n'
ast-grep outline bugzooka/integrations/slack_fetcher.py --view expanded | sed -n '1,260p'

printf '\n== exact code around the branch ==\n'
nl -ba bugzooka/integrations/slack_fetcher.py | sed -n '230,310p'

printf '\n== search for changepoint-related tests or docs ==\n'
rg -n "changepoint|preview_limit|errors_for_file|errors_preview|needs_file" . -g '*test*' -g '*.md' -g '*.py' -C 2 || true

Repository: redhat-performance/BugZooka

Length of output: 1250


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== search for slack_fetcher usage and related tests ==\n'
rg -n "slack_fetcher|SlackFetcher|needs_file|errors_preview|errors_for_file|preview_limit" bugzooka -C 2 || true

printf '\n== locate tests under repository ==\n'
find . -path '*/.git' -prune -o -name '*test*.py' -o -name 'test_*.py' -o -name '*_test.py' -print

Repository: redhat-performance/BugZooka

Length of output: 7394


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
p = Path('bugzooka/integrations/slack_fetcher.py')
print('exists', p.exists(), 'lines', sum(1 for _ in p.open()))
with p.open() as f:
    for i, line in enumerate(f, 1):
        if 220 <= i <= 310:
            print(f"{i:4d}: {line.rstrip()}")
PY

printf '\n== nearby tests referencing SlackFetcher or file uploads ==\n'
rg -n "SlackFetcher|needs_file|errors_for_file|errors_preview|preview_limit|upload.*file|file.*upload" . -g '*test*' -g '*.py' -C 2 || true

Repository: redhat-performance/BugZooka

Length of output: 20085


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== slack_fetcher call site ==\n'
python3 - <<'PY'
from pathlib import Path
p = Path('bugzooka/integrations/slack_fetcher.py')
for i, line in enumerate(p.open(), 1):
    if 630 <= i <= 665:
        print(f"{i:4d}: {line.rstrip()}")
PY

printf '\n== prow_analyzer changepoint branch ==\n'
python3 - <<'PY'
from pathlib import Path
p = Path('bugzooka/analysis/prow_analyzer.py')
for i, line in enumerate(p.open(), 1):
    if 330 <= i <= 356:
        print(f"{i:4d}: {line.rstrip()}")
PY

printf '\n== tests around error upload behavior ==\n'
python3 - <<'PY'
from pathlib import Path
p = Path('tests/test_slack_fetcher.py')
for i, line in enumerate(p.open(), 1):
    if 110 <= i <= 260:
        print(f"{i:4d}: {line.rstrip()}")
PY

Repository: redhat-performance/BugZooka

Length of output: 10658


Short changepoint reports may now upload a file unexpectedly. At bugzooka/integrations/slack_fetcher.py:243, errors_for_file != errors_preview makes needs_file true whenever the full changepoint log differs from the preview, even if both are still under preview_limit. Add a changepoint test for the short-but-different case.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@bugzooka/integrations/slack_fetcher.py` at line 243, The needs_file check in
SlackFetcher is too broad because errors_for_file != errors_preview can force
file uploads even when the changepoint is still short; tighten the condition
around needs_file so only logs exceeding preview_limit or otherwise requiring
truncation upload a file. Add a changepoint test covering the
short-but-different case in slack_fetcher/SlackFetcher to verify that a short
changepoint does not unexpectedly attach a file.

…nt failures

Signed-off-by: Nabeel Mohd <mmnabeel317@gmail.com>
@mmnabeel317 mmnabeel317 force-pushed the fix/restore-error-log-file-upload branch from 6bbca27 to cdef80c Compare July 2, 2026 09:50

@vishnuchalla vishnuchalla left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

lgtm

@vishnuchalla vishnuchalla merged commit 25a27bd into redhat-performance:main Jul 6, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants