Skip to content

feat: add flags to store WAF log lines for failed tests - #626

Merged
theseion merged 1 commit into
mainfrom
copilot/only-keep-logs-for-failing-tests
May 17, 2026
Merged

feat: add flags to store WAF log lines for failed tests#626
theseion merged 1 commit into
mainfrom
copilot/only-keep-logs-for-failing-tests

Conversation

Copilot AI commented Apr 19, 2026

Copy link
Copy Markdown
Contributor
  • adds new flags:
    • --store-failure-waf-logs
    • --failure-waf-logs-file
    • --failure-waf-logs-dir

These flags allow users to store the log lines from the WAF log in a
dedicated file to help with debugging, e.g., in CI/CD.

Summary by CodeRabbit

Release Notes

  • New Features

    • Added --store-failure-waf-logs flag to capture WAF logs separately for failed tests
    • Added --failure-waf-logs-file and --failure-waf-logs-dir flags to configure failure log output location
  • Bug Fixes

    • Improved error handling for log assertions and log reading operations to provide clearer failure feedback

Review Change Stack

Copilot AI linked an issue Apr 19, 2026 that may be closed by this pull request
Copilot AI changed the title [WIP] Add functionality to keep logs for failing tests feat: save failed test logs and truncate WAF log when using --show-failures-only Apr 19, 2026
Copilot AI requested a review from fzipi April 19, 2026 12:51
@fzipi

fzipi commented Apr 21, 2026

Copy link
Copy Markdown
Member

Copilot AI commented Apr 21, 2026

Copy link
Copy Markdown
Contributor Author

@copilot fix the windows tests: https://github.com/coreruleset/go-ftw/actions/runs/24629480025/job/72128596838?pr=626

Fixed in a76dae6. The TestFailedTestsLogFilePath test was using hardcoded Unix-style paths (/tmp/failed-tests.log), but on Windows filepath.Join produces backslash separators. Changed the test to build expected paths with filepath.Join so it works cross-platform.

@fzipi
fzipi force-pushed the copilot/only-keep-logs-for-failing-tests branch from a76dae6 to cf4861e Compare April 21, 2026 21:50
@fzipi
fzipi marked this pull request as ready for review May 3, 2026 13:28
@fzipi

fzipi commented May 3, 2026

Copy link
Copy Markdown
Member

@copilot maybe adding a new flag instead, called --log-failures-only instead of reusing the --show-failures-only to trigger this feature.

Copilot AI commented May 3, 2026

Copy link
Copy Markdown
Contributor Author

@copilot maybe adding a new flag instead, called --log-failures-only instead of reusing the --show-failures-only to trigger this feature.

Done in 28666e9. Added a new --log-failures-only flag that controls the WAF log management behavior (saving failed entries + truncating after each stage), keeping it fully independent from --show-failures-only.

Copilot AI changed the title feat: save failed test logs and truncate WAF log when using --show-failures-only feat: save failed test logs and truncate WAF log when using --log-failures-only May 3, 2026
Copilot finished work on behalf of fzipi May 3, 2026 13:37
@theseion

theseion commented May 9, 2026

Copy link
Copy Markdown
Collaborator

@copilot rebase

@fzipi

fzipi commented May 10, 2026

Copy link
Copy Markdown
Member

@copilot fix failing tests

@fzipi

fzipi commented May 10, 2026

Copy link
Copy Markdown
Member

@coderabbitai full_review

Copilot AI commented May 10, 2026

Copy link
Copy Markdown
Contributor Author

@copilot fix failing tests

Fixed in d445f16. The CI failure was caused by missing go.sum entries after the merge of main brought in golang.org/x/net v0.53.0, which introduced new transitive dependencies. Ran go mod tidy to add the missing entries.

@copilot rebase

The branch was already rebased/merged with main (commit 5dbc5f3). The go.sum has now been fixed as well (d445f16).

Copilot finished work on behalf of fzipi May 10, 2026 23:55
@fzipi

fzipi commented May 10, 2026

Copy link
Copy Markdown
Member

@coderabbitai full_review

@coderabbitai

coderabbitai Bot commented May 10, 2026

Copy link
Copy Markdown

@fzipi Sure! I'll redo the full review of PR #626 now.

✅ Actions performed

Full review triggered.

@coderabbitai

coderabbitai Bot commented May 10, 2026

Copy link
Copy Markdown

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 4fec4e59-8057-445b-82dc-6f8885377bf8

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR adds a failure WAF logs feature with comprehensive error handling refactoring. It updates WAF log API methods to return errors instead of fatal-ing, refactors log assertion logic to propagate those errors, and implements conditional persistence of marked logs from failed test stages to a separate file via new CLI flags.

Changes

Failure WAF Logs Implementation

Layer / File(s) Summary
WAF Log API Error Handling Refactoring
waflog/read.go, waflog/read_test.go, waflog/waflog_test.go
WAF log methods (TriggeredRules, ContainsAllIds, ContainsAnyId, MatchesRegex, GetMarkedLines) return error tuples instead of fatal-ing; marked lines are now reversed internally to restore original order; test coverage updated to handle new error returns.
Log Assertion Error Propagation
runner/check_logs.go, runner/check_logs_test.go
FTWCheck.AssertLogs() returns (bool, error) with helpers assertLogContains and assertNoLogContains updated to capture and propagate errors from WAF log operations; log assertion failures distinguished from missing patterns by explicit error returns.
Check Base Signature and Fixture Updates
runner/check_base.go, runner/check_base_test.go, runner/check_error_test.go, runner/check_response_test.go
GetTriggeredRules() signature updated to return ([]uint, error); test fixtures consolidated to use inline logLines strings for consistency with error-aware log processing.
Configuration and Runtime Types
config/runner_config.go, runner/types.go
New fields StoreFailureLogs (bool) and FailureWafLogsFilePath (string) added to both RunnerConfig and TestRunContext to carry failure log configuration through execution.
CLI Flag Wiring and Validation
cmd/run/run.go, cmd/run/run_test.go
Registers --store-failure-waf-logs, --failure-waf-logs-file, --failure-waf-logs-dir flags; buildRunnerConfig validates paths, defaults directory to log file directory when not provided, and includes test coverage for default and explicit flag configurations with directory existence checks.
Failure Log Persistence and Runtime Integration
runner/run.go, runner/run_test.go, runner/testdata/TestStoreFailureWafLogs.yaml, runner/testdata/TestStoreFailureWafLogs_Disabled.yaml
Implements conditional persistence of marked WAF log lines for failed stages during non-cloud execution; appendFailureWafLogs() appends marked lines to the configured failure log file; log assertion errors captured in checkResult; integration tests validate that failure logs are created only when enabled and contain expected marked content.

Sequence Diagram(s)

sequenceDiagram
  participant FTWLogLines
  participant AssertLogs as FTWCheck.AssertLogs
  participant assertLogContains
  participant Runner
  
  Runner->>AssertLogs: call with error handling
  AssertLogs->>assertLogContains: check log expectations
  assertLogContains->>FTWLogLines: TriggeredRules()
  alt Error from log operations
    FTWLogLines-->>assertLogContains: (nil, error)
    assertLogContains-->>AssertLogs: (false, error)
    AssertLogs-->>Runner: (false, error)
  else Success
    FTWLogLines-->>assertLogContains: (ruleIds, nil)
    assertLogContains-->>AssertLogs: (bool, nil)
    AssertLogs-->>Runner: (bool, nil)
  end
Loading
sequenceDiagram
  participant CLI
  participant buildRunner as buildRunnerConfig
  participant Validator as Path Validator
  participant Config as RunnerConfig
  
  CLI->>buildRunner: --store-failure-waf-logs flags
  buildRunner->>Validator: validate logs directory
  alt Directory provided and exists
    Validator-->>Config: use provided directory
  else Directory not provided
    Validator-->>Config: default to log file directory
  else Directory does not exist
    Validator-->>buildRunner: error
  end
  buildRunner->>Config: set StoreFailureLogs and FailureWafLogsFilePath
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 Logs now flow with grace, no fatal calls in sight,
Errors bubble up like carrots in the night,
Failed tests tucked away in their own file to keep,
While marked lines reverse and the system runs deep!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
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.
Title check ✅ Passed The title 'feat: add flags to store WAF log lines for failed tests' directly matches the main objective: adding CLI flags to manage WAF log storage for failed tests.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch copilot/only-keep-logs-for-failing-tests

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 and usage tips.

@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

🤖 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 `@waflog/waflog.go`:
- Around line 84-87: Update the in-line comment above the os.OpenFile call that
currently references the wrong CLI flag; change the text mentioning
"--show-failures-only" to the correct flag name "--log-failures-only" so the
comment near ll.logFile, ll.logFilePath and the os.OpenFile call accurately
documents the behavior when the log file is truncated after each test.
🪄 Autofix (Beta)

✅ Autofix completed


ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 65035d17-6cc9-4002-99be-079e437da444

📥 Commits

Reviewing files that changed from the base of the PR and between 599c89b and d445f16.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (8)
  • cmd/run/run.go
  • config/runner_config.go
  • runner/run.go
  • runner/run_test.go
  • runner/testdata/TestLogFailuresOnly.yaml
  • runner/types.go
  • waflog/waflog.go
  • waflog/waflog_test.go

Comment thread waflog/waflog.go Outdated
@coderabbitai

coderabbitai Bot commented May 11, 2026

Copy link
Copy Markdown

Note

Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.

Fixes Applied Successfully

Fixed 1 file(s) based on 1 unresolved review comment.

Files modified:

  • waflog/waflog.go

Commit: 7852736c8031f310798c38ecb2dafbfa688044fc

The changes have been pushed to the copilot/only-keep-logs-for-failing-tests branch.

Time taken: 2m 0s

@theseion

Copy link
Copy Markdown
Collaborator

Note: I'm rewriting this PR to use two separate flags.

@theseion
theseion force-pushed the copilot/only-keep-logs-for-failing-tests branch from 7852736 to 872b13e Compare May 16, 2026 19:14
@theseion

Copy link
Copy Markdown
Collaborator

@coderabbitai full_review

@coderabbitai

coderabbitai Bot commented May 16, 2026

Copy link
Copy Markdown

@theseion Sure! I'll redo the full review of PR #626 now, taking into account the rewrite using two separate flags.

✅ Actions performed

Full review triggered.

✅ Actions performed

Full review triggered.

@theseion theseion changed the title feat: save failed test logs and truncate WAF log when using --log-failures-only feat: add flags to store WAF log lines for failed tests May 16, 2026

@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: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
waflog/read.go (1)

175-183: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Propagate I/O failures from log scanning instead of silently returning partial results.

GetMarkedLines() now has an error return, but basicGetMarkedLines() still swallows Stat() / scanner errors. This can turn operational failures into false-negative assertions.

Suggested fix
-func (ll *FTWLogLines) basicGetMarkedLines() [][]byte {
+func (ll *FTWLogLines) basicGetMarkedLines() ([][]byte, error) {
  fileInfo, err := ll.logFile.Stat()
  if err != nil {
-   log.Error().Caller().Msg("cannot read file's size")
-   return ll.markedLines
+   return nil, fmt.Errorf("cannot read log file size: %w", err)
  }

  ...
  for {
    line, _, err := scanner.LineBytes()
    if err != nil {
      if err != io.EOF {
-       log.Trace().Err(err)
+       return nil, fmt.Errorf("failed while scanning log lines: %w", err)
      }
      break
    }
    ...
  }

  slices.Reverse(ll.markedLines)
- return ll.markedLines
+ return ll.markedLines, nil
}
- return ll.basicGetMarkedLines(), nil
+ lines, err := ll.basicGetMarkedLines()
+ if err != nil {
+   return nil, err
+ }
+ ll.markedLines = lines
+ ll.markedLinesInitialized = true
+ return ll.markedLines, nil

Also applies to: 195-201

🤖 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 `@waflog/read.go` around lines 175 - 183, basicGetMarkedLines currently
swallows I/O errors (e.g., from ll.logFile.Stat and scanner errors) even though
GetMarkedLines now returns an error; modify basicGetMarkedLines
(FTWLogLines.basicGetMarkedLines) to return ([][]byte, error) and return any
Stat()/scanner errors instead of logging and returning partial ll.markedLines,
then update GetMarkedLines to call the new signature and propagate the error up;
apply the same change to the similar block referenced at lines 195-201 so all
scanning/Stat failures are returned rather than silently ignored.
cmd/run/run.go (1)

220-277: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Enforce --failure-waf-logs-file as a file name (not a path).

This flag is documented as a file name, but path fragments are currently accepted. That can unintentionally bypass the selected failure-log directory.

Suggested patch
 	storeFailureWafLogsFileName, err := cmd.Flags().GetString(failureWafLogsFileNameFlag)
 	if err != nil {
 		return nil, err
 	}
+	if filepath.Base(storeFailureWafLogsFileName) != storeFailureWafLogsFileName {
+		return nil, fmt.Errorf("argument to %s must be a file name, got: '%s'", failureWafLogsFileNameFlag, storeFailureWafLogsFileName)
+	}
🤖 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 `@cmd/run/run.go` around lines 220 - 277, The flag value in
storeFailureWafLogsFileName must be enforced as a file name (no path fragments):
detect when the provided value contains path separators or differs from
filepath.Base and return an error, or alternatively sanitize by using
filepath.Base and reject empty names; update the logic where
storeFailureWafLogsFileName is read (the block that sets
runnerConfig.FailureWafLogsFilePath and checks failureWafLogsDirPath) to
validate that storeFailureWafLogsFileName is non-empty and contains no directory
components (compare to filepath.Base or check for os.PathSeparator/'/'),
returning a clear error mentioning the --failure-waf-logs-file flag if
validation fails before joining it with failureWafLogsDirPath to set
runnerConfig.FailureWafLogsFilePath.
🤖 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 `@cmd/run/run_test.go`:
- Around line 491-497: The test TestFailureWafLogsDirFlag_DirectoryDoesNotExist
is asserting on platform-specific error text via s.ErrorContains(err, "no such
file or directory"); change this to a platform-agnostic existence check by
asserting the error indicates a missing file/directory (e.g., use
os.IsNotExist(err) or errors.Is(err, fs.ErrNotExist)) after calling
buildRunnerConfig, replacing the s.ErrorContains call so the test passes on
Windows and Unix.

In `@cmd/run/run.go`:
- Around line 271-273: The error message formatting for the non-directory check
is malformed: update the fmt.Errorf call that uses failureWafLogsDirFlag and
failureWafLogsDirPath so the quoted path is properly closed and the format
string is correct (e.g., ensure the '%s' placeholder is terminated and the
trailing single quote is present). Locate the return statement that currently
reads fmt.Errorf("argument to %s is not a directory: '%s",
failureWafLogsDirFlag, failureWafLogsDirPath) and fix the format string to
include the missing closing quote and matching verbs.

In `@runner/run.go`:
- Around line 215-221: The current block checks notRunningInCloudMode(ftwCheck)
&& runContext.StoreFailureWafLogs and appends failed-stage WAF log lines via
appendFailureWafLogs when testResult == Failed, but never truncates the WAF log
after stage completion so non-failing-stage entries persist; update the logic to
truncate/clear the WAF log after each stage when StoreFailureWafLogs mode is
active — either add a call to the existing truncation helper (e.g.
truncateWafLog or clearWafLog) immediately after the stage finishes (both on
success and after handling failure) or modify appendFailureWafLogs to append the
failure lines and then truncate the live WAF log; ensure you reference
notRunningInCloudMode(ftwCheck), runContext.StoreFailureWafLogs,
testResult/Failed and appendFailureWafLogs when making the change.

In `@waflog/read.go`:
- Around line 38-47: The initialization flag triggeredRulesInitialized is being
set before the read/validation completes in FTWLogLines.TriggeredRules (and in
the analogous block flagged elsewhere), which can cache a failed/empty result;
change the code to only set ll.triggeredRulesInitialized = true after
GetMarkedLines() returns successfully and after you populate/validate
ll.triggeredRules, so that on error the flag remains false and subsequent calls
retry; apply the same change to the other method that currently sets its
initialization flag before completing its read/validation.

---

Outside diff comments:
In `@cmd/run/run.go`:
- Around line 220-277: The flag value in storeFailureWafLogsFileName must be
enforced as a file name (no path fragments): detect when the provided value
contains path separators or differs from filepath.Base and return an error, or
alternatively sanitize by using filepath.Base and reject empty names; update the
logic where storeFailureWafLogsFileName is read (the block that sets
runnerConfig.FailureWafLogsFilePath and checks failureWafLogsDirPath) to
validate that storeFailureWafLogsFileName is non-empty and contains no directory
components (compare to filepath.Base or check for os.PathSeparator/'/'),
returning a clear error mentioning the --failure-waf-logs-file flag if
validation fails before joining it with failureWafLogsDirPath to set
runnerConfig.FailureWafLogsFilePath.

In `@waflog/read.go`:
- Around line 175-183: basicGetMarkedLines currently swallows I/O errors (e.g.,
from ll.logFile.Stat and scanner errors) even though GetMarkedLines now returns
an error; modify basicGetMarkedLines (FTWLogLines.basicGetMarkedLines) to return
([][]byte, error) and return any Stat()/scanner errors instead of logging and
returning partial ll.markedLines, then update GetMarkedLines to call the new
signature and propagate the error up; apply the same change to the similar block
referenced at lines 195-201 so all scanning/Stat failures are returned rather
than silently ignored.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5b67b621-c1a9-4311-a6aa-eacd90a404a1

📥 Commits

Reviewing files that changed from the base of the PR and between eb6d056 and 872b13e.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (17)
  • cmd/run/run.go
  • cmd/run/run_test.go
  • config/runner_config.go
  • runner/check_base.go
  • runner/check_base_test.go
  • runner/check_error_test.go
  • runner/check_logs.go
  • runner/check_logs_test.go
  • runner/check_response_test.go
  • runner/run.go
  • runner/run_test.go
  • runner/testdata/TestStoreFailureWafLogs.yaml
  • runner/testdata/TestStoreFailureWafLogs_Disabled.yaml
  • runner/types.go
  • waflog/read.go
  • waflog/read_test.go
  • waflog/waflog_test.go

Comment thread cmd/run/run_test.go
Comment thread cmd/run/run.go
Comment thread runner/run.go
Comment thread waflog/read.go
@theseion
theseion force-pushed the copilot/only-keep-logs-for-failing-tests branch from 872b13e to 32f3ebf Compare May 17, 2026 06:03
@theseion

Copy link
Copy Markdown
Collaborator

@fzipi ready for review

@fzipi fzipi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just a nitpick, feel free to merge.

Comment thread cmd/run/run.go Outdated
- adds new flags:
  - `--store-failure-waf-logs`
  - `--failure-waf-logs-file`
  - `--failure-waf-logs-dir`

These flags allow users to store the log lines from the WAF log in a
dedicated file to help with debugging, e.g., in CI/CD.
@theseion
theseion force-pushed the copilot/only-keep-logs-for-failing-tests branch from 32f3ebf to f052368 Compare May 17, 2026 15:27
@theseion
theseion merged commit 1a12ddb into main May 17, 2026
5 checks passed
@theseion
theseion deleted the copilot/only-keep-logs-for-failing-tests branch May 17, 2026 15:29
@theseion theseion added the enhancement New feature or request label May 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Only keep logs for failing tests

3 participants