Skip to content

fix(test): dump file and directory context on E2E assertion failures#77

Merged
rm3l merged 1 commit intoredhat-developer:mainfrom
rm3l:ci/fix_e2e_tests
Mar 11, 2026
Merged

fix(test): dump file and directory context on E2E assertion failures#77
rm3l merged 1 commit intoredhat-developer:mainfrom
rm3l:ci/fix_e2e_tests

Conversation

@rm3l
Copy link
Member

@rm3l rm3l commented Mar 11, 2026

Description

This makes it easier to troubleshoot the failures seen for example in https://github.com/redhat-developer/rhdh-must-gather/actions/runs/22925718339/job/66535452232#step:5:267

Which issue(s) does this PR fix or relate to

PR acceptance criteria

  • Tests
  • Documentation

How to test changes / Special notes to the reviewer

@rhdh-qodo-merge
Copy link

Review Summary by Qodo

Enhance E2E test debugging with file and directory context dumps

✨ Enhancement 🧪 Tests

Grey Divider

Walkthroughs

Description
• Add helper functions to dump file and directory context on E2E assertion failures
• Improve debugging by displaying file contents and directory listings in CI logs
• Handle edge cases like missing files, missing parents, and large files
• Harden existing check functions to prevent errors on nonexistent paths
Diagram
flowchart LR
  A["E2E Test Assertion Failure"] --> B["_dump_file_context or _dump_dir_context"]
  B --> C["Check if path exists"]
  C -->|Exists| D["Display content/listing in CI log"]
  C -->|Missing| E["Show parent directory contents"]
  D --> F["Truncate large files to first/last 50 lines"]
  E --> F
  F --> G["Enhanced CI log for troubleshooting"]
Loading

Grey Divider

File Changes

1. tests/e2e/lib/test-utils.sh ✨ Enhancement +74/-2

Add debugging context dumps for E2E test failures

• Added _dump_file_context helper function to display file contents with truncation for large
 files (>100 lines)
• Added _dump_dir_context helper function to display directory listings with parent directory
 fallback
• Integrated context dumping into existing check functions: check_file_exists, check_dir_exists,
 check_file_not_empty, check_file_valid_json, check_dir_not_empty, and check_file_contains
• Hardened check_dir_not_empty and check_file_contains with existence checks to prevent errors
 on nonexistent paths

tests/e2e/lib/test-utils.sh


Grey Divider

Qodo Logo

@rhdh-qodo-merge
Copy link

rhdh-qodo-merge bot commented Mar 11, 2026

Code Review by Qodo

🐞 Bugs (4) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Dump helpers trigger errexit 🐞 Bug ⛯ Reliability
Description
The new _dump_file_context/_dump_dir_context run wc/head/tail/ls without guarding failures; under
set -euo pipefail this can abort the validator early (especially when the path exists but isn’t a
readable regular file/dir), skipping remaining checks and masking the original failure.
Code

tests/e2e/lib/test-utils.sh[R28-90]

+_dump_file_context() {
+    local file="$1"
+    if [ ! -e "$file" ]; then
+        log_error "  ↳ File does not exist: $file"
+        local parent
+        parent="$(dirname "$file")"
+        if [ -d "$parent" ]; then
+            log_error "  ↳ Parent directory contents ($(basename "$parent")/):"
+            ls -la "$parent" | while IFS= read -r line; do
+                log_error "      $line"
+            done
+        else
+            log_error "  ↳ Parent directory also missing: $parent"
+        fi
+        return
+    fi
+    if [ ! -s "$file" ]; then
+        log_error "  ↳ File exists but is empty (0 bytes): $file"
+        return
+    fi
+    local total_lines
+    total_lines=$(wc -l < "$file")
+    local max_lines=100
+    log_error "  ↳ File content ($total_lines lines):"
+    if [ "$total_lines" -le "$max_lines" ]; then
+        while IFS= read -r line; do
+            log_error "      $line"
+        done < "$file"
+    else
+        log_error "      --- first 50 lines ---"
+        head -n 50 "$file" | while IFS= read -r line; do
+            log_error "      $line"
+        done
+        log_error "      --- ... truncated $(( total_lines - 100 )) lines ... ---"
+        log_error "      --- last 50 lines ---"
+        tail -n 50 "$file" | while IFS= read -r line; do
+            log_error "      $line"
+        done
+    fi
+}
+
+# Dump directory listing for debugging failed assertions.
+_dump_dir_context() {
+    local dir="$1"
+    if [ ! -e "$dir" ]; then
+        log_error "  ↳ Directory does not exist: $dir"
+        local parent
+        parent="$(dirname "$dir")"
+        if [ -d "$parent" ]; then
+            log_error "  ↳ Parent directory contents ($(basename "$parent")/):"
+            ls -la "$parent" | while IFS= read -r line; do
+                log_error "      $line"
+            done
+        else
+            log_error "  ↳ Parent directory also missing: $parent"
+        fi
+        return
+    fi
+    log_error "  ↳ Directory listing:"
+    ls -la "$dir" | while IFS= read -r line; do
+        log_error "      $line"
+    done
+}
Evidence
All E2E validators enable set -euo pipefail and source these helpers, so any non-zero exit from
unguarded commands inside the dump helpers can terminate the script. This is more likely than just a
race: check_file_exists checks -f, but _dump_file_context only checks -e/-s, so if the path
exists but is a directory/symlink/permission-denied, wc/head/tail and ls can fail and trigger
errexit/pipefail.

tests/e2e/validate-common.sh[15-22]
tests/e2e/validate-helm.sh[16-21]
tests/e2e/lib/test-utils.sh[28-66]
tests/e2e/lib/test-utils.sh[70-90]
tests/e2e/lib/test-utils.sh[99-109]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The new debug dump helpers can cause the E2E validation scripts to exit prematurely under `set -euo pipefail` when `wc/head/tail/ls` fail (e.g., unreadable path, path is a directory, permission denied).

### Issue Context
These helpers run during assertion failures; they must be *best-effort* and must not change control flow of the validation scripts.

### Fix Focus Areas
- tests/e2e/lib/test-utils.sh[26-90]

### Notes for implementation
- In `_dump_file_context`, add guards like `if [ ! -f &quot;$file&quot; ] || [ ! -r &quot;$file&quot; ]; then ...; return; fi`.
- Wrap/guard commands so they cannot trip errexit/pipefail, e.g.:
 - `total_lines=$(wc -l &lt;&quot;$file&quot; 2&gt;/dev/null || echo &quot;?&quot;)`
 - `ls -la &quot;$dir&quot; 2&gt;&amp;1 | while ...; done || true`
 - `head ... 2&gt;/dev/null | while ...; done || true`
 - `tail ... 2&gt;/dev/null | while ...; done || true`

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Missing-file counted twice 🐞 Bug ✓ Correctness
Description
Several helpers call check_file_exists/check_dir_exists (which increments ERRORS) but then continue
and also increment ERRORS + dump again, so a missing file/dir can produce duplicate error counts and
repeated context output.
Code

tests/e2e/lib/test-utils.sh[R162-170]

    local content="$2"
    local description="$3"
    check_file_exists "$file" "$description"
-    if grep -q "$content" "$file"; then
+    if [ -f "$file" ] && grep -q "$content" "$file"; then
        log_info "✓ Found $content in $file"
    else
        log_error "✗ $description does not contain '$content': $file"
+        _dump_file_context "$file"
        ((ERRORS++))
Evidence
check_file_exists increments ERRORS and dumps context on missing paths but does not stop the caller;
check_file_contains (and similarly check_file_not_empty/check_file_valid_json/check_dir_not_empty)
continues and increments ERRORS and dumps again in its own failure branch. With the new context
dumping, this duplication is more costly/noisy and the error count becomes misleading.

tests/e2e/lib/test-utils.sh[99-109]
tests/e2e/lib/test-utils.sh[160-171]
tests/e2e/lib/test-utils.sh[123-145]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
Helpers like `check_file_not_empty`, `check_file_valid_json`, `check_dir_not_empty`, and `check_file_contains` call `check_*_exists` and then continue, which can cause a single missing file/dir to be reported twice (and now dumped twice).

### Issue Context
E2E scripts rely on `ERRORS` as a summary counter and print debug context only to help troubleshooting. Duplicates inflate counts and can spam CI logs.

### Fix Focus Areas
- tests/e2e/lib/test-utils.sh[99-171]

### Notes for implementation
- After `check_file_exists`, add an explicit guard in callers:
 - `check_file_exists &quot;$file&quot; &quot;$description&quot;; [ -f &quot;$file&quot; ] || return`
- Similarly for dirs:
 - `check_dir_exists &quot;$dir&quot; &quot;$description&quot;; [ -d &quot;$dir&quot; ] || return`
- Keep return codes from these helpers as `0` to avoid tripping `set -e` in callers.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. echo -e corrupts dumps 🐞 Bug ✧ Quality
Description
Dump helpers log arbitrary file/listing content via log_error which uses echo -e, so backslash
escapes in content will be interpreted, and despite the comment saying “to stderr” the output
currently goes to stdout, reducing fidelity of debugging output.
Code

tests/e2e/lib/test-utils.sh[R26-60]

+# Dump file content to stderr for debugging failed assertions.
+# Truncates to first and last 50 lines if the file is large.
+_dump_file_context() {
+    local file="$1"
+    if [ ! -e "$file" ]; then
+        log_error "  ↳ File does not exist: $file"
+        local parent
+        parent="$(dirname "$file")"
+        if [ -d "$parent" ]; then
+            log_error "  ↳ Parent directory contents ($(basename "$parent")/):"
+            ls -la "$parent" | while IFS= read -r line; do
+                log_error "      $line"
+            done
+        else
+            log_error "  ↳ Parent directory also missing: $parent"
+        fi
+        return
+    fi
+    if [ ! -s "$file" ]; then
+        log_error "  ↳ File exists but is empty (0 bytes): $file"
+        return
+    fi
+    local total_lines
+    total_lines=$(wc -l < "$file")
+    local max_lines=100
+    log_error "  ↳ File content ($total_lines lines):"
+    if [ "$total_lines" -le "$max_lines" ]; then
+        while IFS= read -r line; do
+            log_error "      $line"
+        done < "$file"
+    else
+        log_error "      --- first 50 lines ---"
+        head -n 50 "$file" | while IFS= read -r line; do
+            log_error "      $line"
+        done
Evidence
The dump helpers are explicitly intended to print raw file/directory context, but they route content
through log_error implemented with echo -e (escape interpretation) and no stderr redirection. This
can make the dumped content inaccurate (e.g., \t, \n, \033 sequences are expanded) and
contradicts the new comment about stderr output.

tests/e2e/lib/test-utils.sh[22-27]
tests/e2e/lib/test-utils.sh[53-60]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The dump helpers pass raw file and `ls` output through `log_error`, which currently uses `echo -e` (interprets backslash escapes) and writes to stdout. This can corrupt the displayed content and conflicts with the intent to dump to stderr.

### Issue Context
Dump output is used for troubleshooting; it should preserve content faithfully and appear in the expected stream.

### Fix Focus Areas
- tests/e2e/lib/test-utils.sh[14-27]
- tests/e2e/lib/test-utils.sh[26-90]

### Notes for implementation
- Prefer:
 - `log_error() { printf &#x27;%b[ERROR]%b %s\n&#x27; &quot;$RED&quot; &quot;$NC&quot; &quot;$1&quot; &gt;&amp;2; }`
 - and similar for info/warn (stdout or stderr by convention).
- Avoid `echo -e` when printing arbitrary file contents.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Advisory comments

4. Potential sensitive log leak 🐞 Bug ⛨ Security
Description
On failures, the new helpers dump entire file contents (up to 100 lines) into CI logs; if collected
output includes sensitive data (or sanitization misses domain-specific secrets), this increases the
risk of leaking credentials/tokens in CI output.
Code

tests/e2e/lib/test-utils.sh[R51-65]

+    log_error "  ↳ File content ($total_lines lines):"
+    if [ "$total_lines" -le "$max_lines" ]; then
+        while IFS= read -r line; do
+            log_error "      $line"
+        done < "$file"
+    else
+        log_error "      --- first 50 lines ---"
+        head -n 50 "$file" | while IFS= read -r line; do
+            log_error "      $line"
+        done
+        log_error "      --- ... truncated $(( total_lines - 100 )) lines ... ---"
+        log_error "      --- last 50 lines ---"
+        tail -n 50 "$file" | while IFS= read -r line; do
+            log_error "      $line"
+        done
Evidence
The dump helpers print file contents directly into logs, and project docs acknowledge sanitization
is best-effort and requires manual review for domain-specific sensitive information. If E2E runs
ever enable secret collection or encounter unsanitized sensitive values in logs/manifests, this
debug output could expose them in CI logs.

tests/e2e/lib/test-utils.sh[51-66]
docs/secret-collection-and-sanitization.md[28-53]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The dump helpers print file contents into CI logs on failures. If any sensitive values make it into collected output (or sanitization is incomplete for domain-specific patterns), CI logs may expose them.

### Issue Context
Docs note sanitization is not a guarantee for domain-specific sensitive info; E2E failure logs may be broadly visible.

### Fix Focus Areas
- tests/e2e/lib/test-utils.sh[26-90]
- docs/secret-collection-and-sanitization.md[21-53]

### Notes for implementation
- Add an env var gate to enable dumps only when explicitly requested.
- Optionally add lightweight redaction for common patterns or skip dumps for files likely to contain secrets.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@rm3l rm3l changed the title ci: dump file and directory context on E2E assertion failures fix(test): dump file and directory context on E2E assertion failures Mar 11, 2026
Comment on lines +28 to +90
_dump_file_context() {
local file="$1"
if [ ! -e "$file" ]; then
log_error " ↳ File does not exist: $file"
local parent
parent="$(dirname "$file")"
if [ -d "$parent" ]; then
log_error " ↳ Parent directory contents ($(basename "$parent")/):"
ls -la "$parent" | while IFS= read -r line; do
log_error " $line"
done
else
log_error " ↳ Parent directory also missing: $parent"
fi
return
fi
if [ ! -s "$file" ]; then
log_error " ↳ File exists but is empty (0 bytes): $file"
return
fi
local total_lines
total_lines=$(wc -l < "$file")
local max_lines=100
log_error " ↳ File content ($total_lines lines):"
if [ "$total_lines" -le "$max_lines" ]; then
while IFS= read -r line; do
log_error " $line"
done < "$file"
else
log_error " --- first 50 lines ---"
head -n 50 "$file" | while IFS= read -r line; do
log_error " $line"
done
log_error " --- ... truncated $(( total_lines - 100 )) lines ... ---"
log_error " --- last 50 lines ---"
tail -n 50 "$file" | while IFS= read -r line; do
log_error " $line"
done
fi
}

# Dump directory listing for debugging failed assertions.
_dump_dir_context() {
local dir="$1"
if [ ! -e "$dir" ]; then
log_error " ↳ Directory does not exist: $dir"
local parent
parent="$(dirname "$dir")"
if [ -d "$parent" ]; then
log_error " ↳ Parent directory contents ($(basename "$parent")/):"
ls -la "$parent" | while IFS= read -r line; do
log_error " $line"
done
else
log_error " ↳ Parent directory also missing: $parent"
fi
return
fi
log_error " ↳ Directory listing:"
ls -la "$dir" | while IFS= read -r line; do
log_error " $line"
done
}

Choose a reason for hiding this comment

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

Action required

1. Dump helpers trigger errexit 🐞 Bug ⛯ Reliability

The new _dump_file_context/_dump_dir_context run wc/head/tail/ls without guarding failures; under
set -euo pipefail this can abort the validator early (especially when the path exists but isn’t a
readable regular file/dir), skipping remaining checks and masking the original failure.
Agent Prompt
### Issue description
The new debug dump helpers can cause the E2E validation scripts to exit prematurely under `set -euo pipefail` when `wc/head/tail/ls` fail (e.g., unreadable path, path is a directory, permission denied).

### Issue Context
These helpers run during assertion failures; they must be *best-effort* and must not change control flow of the validation scripts.

### Fix Focus Areas
- tests/e2e/lib/test-utils.sh[26-90]

### Notes for implementation
- In `_dump_file_context`, add guards like `if [ ! -f "$file" ] || [ ! -r "$file" ]; then ...; return; fi`.
- Wrap/guard commands so they cannot trip errexit/pipefail, e.g.:
  - `total_lines=$(wc -l <"$file" 2>/dev/null || echo "?")`
  - `ls -la "$dir" 2>&1 | while ...; done || true`
  - `head ... 2>/dev/null | while ...; done || true`
  - `tail ... 2>/dev/null | while ...; done || true`

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

When an E2E validation check fails (e.g. file missing, file empty,
file not containing expected content, invalid JSON, directory missing
or empty), the error message alone is not enough to diagnose CI
failures — especially in nightly runs where the environment is
ephemeral.

Add _dump_file_context and _dump_dir_context helpers that are called
on every assertion failure. They print the actual file content (or
directory listing) inline in the CI log, and handle edge cases like
missing files, missing parent directories, and large files (truncated
to first/last 50 lines). This eliminates the need to download the
must-gather artifact just to understand why a check failed.

Also harden check_dir_not_empty and check_file_contains to guard
against errors when the path doesn't exist (the prior code would
error on ls/grep of a nonexistent path after check_dir_exists/
check_file_exists already reported the failure).

Assisted-by: Cursor
Made-with: Cursor
@rm3l rm3l force-pushed the ci/fix_e2e_tests branch from 8a66c6d to cd57057 Compare March 11, 2026 12:16
@rm3l rm3l merged commit 34e5490 into redhat-developer:main Mar 11, 2026
5 checks passed
@rm3l rm3l deleted the ci/fix_e2e_tests branch March 11, 2026 12:39
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.

1 participant