Skip to content

feat(known-error): support multiple regex patterns per known error#325

Merged
rubberduck203 merged 4 commits into
mainfrom
feat/known-error-multi-pattern
Jun 4, 2026
Merged

feat(known-error): support multiple regex patterns per known error#325
rubberduck203 merged 4 commits into
mainfrom
feat/known-error-multi-pattern

Conversation

@rubberduck203
Copy link
Copy Markdown
Contributor

@rubberduck203 rubberduck203 commented Jun 3, 2026

Summary

  • spec.pattern now accepts either a single string (existing behavior, unchanged) or a list of strings
  • A log line matching any one of the patterns triggers the known error
  • An empty list is rejected at both the schema layer and at parse time
  • Internally, patterns are compiled into a RegexSet for single-pass matching

Details

Uses a #[serde(untagged)] enum (KnownErrorPattern) to accept both forms under the same pattern key — the same idiom already used by SkipSpec in this codebase. Single-string configs round-trip unchanged; no migration needed.

# still works
spec:
  pattern: "No space left on device"

# now also works
spec:
  pattern:
    - "No space left on device"
    - "Out of memory"

Implementation notes

  • Schema: the Many variant carries minItems: 1 via a schema_with helper, so schema-aware tooling (IDE validators, YAML linters) catches pattern: [] at authoring time. A runtime guard in TryFrom remains as defense-in-depth since validate_resource only warns on schema mismatches.
  • Internal model: the old parallel patterns: Vec<String> / regexes: Vec<Regex> fields are replaced by a single regexes: RegexSet. RegexSet matches all patterns in one DFA pass and exposes the original strings via .patterns(), eliminating the dual-storage issue.
  • Also includes a pre-existing clippy lint fix (useless_vec → array literal in a test) that would otherwise fail CI under -D warnings.

Test plan

  • cargo test — all existing tests pass (backward compatibility)
  • New unit tests: parses_list_of_patterns, empty_pattern_list_is_rejected, try_from_multi_pattern_spec
  • schema_rejects_empty_pattern_list — confirms pattern: [] is caught at the schema layer
  • cargo test create_and_validate_schemas — regenerated schemas validated against both single-string and multi-pattern example fixtures
  • cargo clippy --all-targets --all-features -- -D warnings — clean

🤖 Generated with Claude Code

@rubberduck203 rubberduck203 force-pushed the feat/known-error-multi-pattern branch from 3051afe to 3131221 Compare June 3, 2026 19:33
rubberduck203 and others added 4 commits June 3, 2026 15:43
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
`spec.pattern` now accepts either a single string (as before) or a list
of strings. A log line matching any one of the patterns triggers the
known error. Existing single-string configs are unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds `minItems: 1` to the list variant of `KnownErrorPattern` via a
`schema_with` helper, so schema-aware tooling (IDE validators, CI schema
checks) rejects `pattern: []` at authoring time rather than at runtime.

The `schema_with` approach is used instead of `#[schemars(length(min=1))]`
to keep the published schema clean — the `length` attribute unconditionally
emits both `minItems` and a stray `minLength` on array schemas.

The runtime empty-list guard in `TryFrom` is kept as defense-in-depth since
`validate_resource` only warns on schema mismatches rather than hard-failing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replaces the parallel `patterns: Vec<String>` and `regexes: Vec<Regex>`
fields with a single `regex_set: RegexSet`. This resolves two findings
from code review in one change:

- Eliminates redundant dual storage: `RegexSet::patterns()` returns the
  original strings in input order, removing the need to store them
  separately. A `KnownError::patterns()` accessor wraps this for callers.
- Improves hot-path efficiency: the match site in `analyze/mod.rs` now
  calls `regex_set.is_match(&line)`, which runs a single DFA pass over
  all patterns rather than iterating a `Vec<Regex>` with `.any()`.

The explicit empty-list guard in `TryFrom` is kept because `RegexSet::new`
succeeds on an empty iterator (returning a set that never matches), so the
guard is still needed to surface the configuration error clearly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@rubberduck203 rubberduck203 force-pushed the feat/known-error-multi-pattern branch from 3131221 to b1223fe Compare June 3, 2026 19:44
@rubberduck203 rubberduck203 marked this pull request as ready for review June 3, 2026 19:57
Copy link
Copy Markdown
Member

@ivy ivy left a comment

Choose a reason for hiding this comment

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

Nice job on the backwards compatibility!

@rubberduck203 rubberduck203 merged commit bb72704 into main Jun 4, 2026
11 checks passed
@rubberduck203 rubberduck203 deleted the feat/known-error-multi-pattern branch June 4, 2026 18:51
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