Skip to content

ROB-0000 add labels to robusta alerts using subject information#2065

Open
RoiGlinik wants to merge 3 commits intomasterfrom
ROB-0000-bettson-add-label-to-robusta-alerts
Open

ROB-0000 add labels to robusta alerts using subject information#2065
RoiGlinik wants to merge 3 commits intomasterfrom
ROB-0000-bettson-add-label-to-robusta-alerts

Conversation

@RoiGlinik
Copy link
Copy Markdown
Contributor

No description provided.

RoiGlinik added 2 commits May 3, 2026 17:05
Signed-off-by: Roi Glinik <groi.tech@gmail.com>
Signed-off-by: Roi Glinik <groi.tech@gmail.com>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 4, 2026

Docker image ready for 0b9174b (built in 38s)

⚠️ Warning: does not support ARM (ARM images are built on release only - not on every PR)

Use this tag to pull the image for testing.

📋 Copy commands

⚠️ Temporary images are deleted after 30 days. Copy to a permanent registry before using them:

gcloud auth configure-docker us-central1-docker.pkg.dev
docker pull us-central1-docker.pkg.dev/robusta-development/temporary-builds/robusta-runner:0b9174b
docker tag us-central1-docker.pkg.dev/robusta-development/temporary-builds/robusta-runner:0b9174b me-west1-docker.pkg.dev/robusta-development/development/robusta-runner-dev:0b9174b
docker push me-west1-docker.pkg.dev/robusta-development/development/robusta-runner-dev:0b9174b

Patch Helm values in one line:

helm upgrade --install robusta robusta/robusta \
  --reuse-values \
  --set runner.image=me-west1-docker.pkg.dev/robusta-development/development/robusta-runner-dev:0b9174b

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 4, 2026

Walkthrough

This PR adds support for label relabeling in findings via configurable regex rules. It introduces a FindingLabelRule model and extends FindingOverrides with optional finding_label_rules. The customise_finding action now evaluates these rules against finding subject fields, applies regex capture-group substitutions, and injects matched labels via a new inject_finding_labels() method on events.

Changes

Finding Label Relabeling Feature

Layer / File(s) Summary
Data Models
playbooks/robusta_playbooks/common_actions.py
Added FindingLabelRule model with source_fields, regex, target_label, replacement, and separator fields. Extended FindingOverrides with optional finding_label_rules list.
Core Implementation
playbooks/robusta_playbooks/common_actions.py, src/robusta/core/model/events.py
Enhanced customise_finding to template and pass aggregation_key to override attributes. Added conditional rule evaluation: builds source-value map from subject fields (namespace, name, kind, labels, annotations), applies re.fullmatch per rule, substitutes capture groups into replacement, and injects via new inject_finding_labels() method. Added ExecutionBaseEvent.inject_finding_labels(labels) to update finding labels across named sinks.
Tests & Documentation
tests/test_customise_finding_relabel.py
Comprehensive test suite with 18 tests covering namespace regex matching, capture-group replacements, multiple source fields, custom separators, rule ordering/overwrite semantics, edge cases (missing namespace, missing keys, non-matching rules), and no-op behavior when rules are absent.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning No pull request description was provided by the author, making it impossible to assess its relevance to the changeset. Add a pull request description explaining the purpose, implementation details, and benefits of the finding label rules feature.
Docstring Coverage ⚠️ Warning Docstring coverage is 4.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: adding labels to robusta alerts using subject information, which aligns with the PR's implementation of finding label rules.
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.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ROB-0000-bettson-add-label-to-robusta-alerts

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
Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.

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

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
tests/test_customise_finding_relabel.py (1)

179-208: ⚡ Quick win

Add a malformed-regex regression test.

Coverage is solid; one high-value gap is a rule with invalid regex to ensure customise_finding skips the bad rule without crashing.

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

In `@tests/test_customise_finding_relabel.py` around lines 179 - 208, Add a test
that verifies customise_finding/FindingOverrides tolerate an invalid regex by
creating a FindingSubject (use _run or _make_event) and a rule where "regex" is
malformed (e.g. unmatched bracket), then call customise_finding or _run with
that rule and assert the function does not raise and the finding's labels remain
unchanged (e.g. existing "team" label stays the same or target_label is not
added); reference customise_finding, FindingOverrides, _run, _make_event and
FindingSubject to locate where to add the test and ensure the bad rule is
skipped rather than crashing.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@playbooks/robusta_playbooks/common_actions.py`:
- Around line 110-111: The current logging in customise_finding logs full
labels_to_inject which can leak sensitive metadata; change the call in the
customise_finding block so you do not log full label values—either downgrade to
logging.debug or log only the label keys (e.g., list(labels_to_inject.keys()))
before calling event.inject_finding_labels(labels_to_inject); keep the injection
via event.inject_finding_labels unchanged but ensure only non-sensitive key
names or a debug-level message is emitted.
- Around line 102-103: customise_finding currently calls
re.fullmatch(rule.regex, source_value) which will raise re.error for malformed
user regexes; wrap the re.fullmatch call in a try/except catching re.error, log
the invalid pattern and exception (including rule.regex and any identifying rule
id) using the existing logger, then continue to the next rule so the bad pattern
is skipped instead of crashing customise_finding.

In `@src/robusta/core/model/events.py`:
- Around line 158-161: The issue is that Finding uses a shared mutable default
FindingSubject which causes inject_finding_labels to mutate a shared labels
dict; fix by changing the Finding constructor signature (class Finding) to use
subject: Optional[FindingSubject] = None instead of a default instance, and
inside the constructor create a fresh FindingSubject() when subject is None
(assign self.subject = subject or FindingSubject()); keep inject_finding_labels
as-is but this ensures each Finding has its own subject.labels so .update()
won't bleed labels across Findings.

---

Nitpick comments:
In `@tests/test_customise_finding_relabel.py`:
- Around line 179-208: Add a test that verifies
customise_finding/FindingOverrides tolerate an invalid regex by creating a
FindingSubject (use _run or _make_event) and a rule where "regex" is malformed
(e.g. unmatched bracket), then call customise_finding or _run with that rule and
assert the function does not raise and the finding's labels remain unchanged
(e.g. existing "team" label stays the same or target_label is not added);
reference customise_finding, FindingOverrides, _run, _make_event and
FindingSubject to locate where to add the test and ensure the bad rule is
skipped rather than crashing.
🪄 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: Pro

Run ID: e57f4745-7ead-4c6f-b04e-e9ac2d6aa0d8

📥 Commits

Reviewing files that changed from the base of the PR and between 447c385 and 46c2a3f.

📒 Files selected for processing (3)
  • playbooks/robusta_playbooks/common_actions.py
  • src/robusta/core/model/events.py
  • tests/test_customise_finding_relabel.py

Comment on lines +102 to +103
m = re.fullmatch(rule.regex, source_value)
if m:
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n playbooks/robusta_playbooks/common_actions.py | head -150 | tail -60

Repository: robusta-dev/robusta

Length of output: 3457


🏁 Script executed:

head -50 playbooks/robusta_playbooks/common_actions.py

Repository: robusta-dev/robusta

Length of output: 2026


🏁 Script executed:

sed -n '70,110p' playbooks/robusta_playbooks/common_actions.py

Repository: robusta-dev/robusta

Length of output: 2220


Guard malformed regex rules to avoid crashing customise_finding.

At line 102, re.fullmatch() will raise re.error on invalid user-provided regex patterns in finding_label_rules, causing the entire action to crash instead of skipping the bad rule. Wrap the call in a try-except block, log the invalid pattern, and continue to the next rule:

Proposed fix
-            m = re.fullmatch(rule.regex, source_value)
+            try:
+                m = re.fullmatch(rule.regex, source_value)
+            except re.error:
+                logging.warning("[customise_finding] invalid finding_label_rules regex: %r", rule.regex)
+                continue
📝 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
m = re.fullmatch(rule.regex, source_value)
if m:
try:
m = re.fullmatch(rule.regex, source_value)
except re.error:
logging.warning("[customise_finding] invalid finding_label_rules regex: %r", rule.regex)
continue
if m:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@playbooks/robusta_playbooks/common_actions.py` around lines 102 - 103,
customise_finding currently calls re.fullmatch(rule.regex, source_value) which
will raise re.error for malformed user regexes; wrap the re.fullmatch call in a
try/except catching re.error, log the invalid pattern and exception (including
rule.regex and any identifying rule id) using the existing logger, then continue
to the next rule so the bad pattern is skipped instead of crashing
customise_finding.

Comment on lines +110 to +111
logging.info(f"[customise_finding] injecting labels into finding: {labels_to_inject}")
event.inject_finding_labels(labels_to_inject)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Avoid logging injected label values at INFO level.

At Line 110, logging full labels_to_inject may leak sensitive metadata into centralized logs. Prefer logging only keys (or downgrade to debug).

🛠️ Proposed fix
-            logging.info(f"[customise_finding] injecting labels into finding: {labels_to_inject}")
+            logging.debug(
+                "[customise_finding] injecting %d labels into finding (keys=%s)",
+                len(labels_to_inject),
+                sorted(labels_to_inject.keys()),
+            )
📝 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
logging.info(f"[customise_finding] injecting labels into finding: {labels_to_inject}")
event.inject_finding_labels(labels_to_inject)
logging.debug(
"[customise_finding] injecting %d labels into finding (keys=%s)",
len(labels_to_inject),
sorted(labels_to_inject.keys()),
)
event.inject_finding_labels(labels_to_inject)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@playbooks/robusta_playbooks/common_actions.py` around lines 110 - 111, The
current logging in customise_finding logs full labels_to_inject which can leak
sensitive metadata; change the call in the customise_finding block so you do not
log full label values—either downgrade to logging.debug or log only the label
keys (e.g., list(labels_to_inject.keys())) before calling
event.inject_finding_labels(labels_to_inject); keep the injection via
event.inject_finding_labels unchanged but ensure only non-sensitive key names or
a debug-level message is emitted.

Comment on lines +158 to +161
def inject_finding_labels(self, labels: Dict[str, str]):
for sink in self.named_sinks:
for finding in self.sink_findings[sink]:
finding.subject.labels.update(labels)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Verify mutable default subject exists
rg -nP 'subject:\s*FindingSubject\s*=\s*FindingSubject\(\)' src/robusta/core/reporting/base.py

# Verify default findings are created without explicit subject
rg -nP 'def create_default_finding|return Finding\(title="Robusta notification"' src/robusta/core/model/events.py

Repository: robusta-dev/robusta

Length of output: 264


🏁 Script executed:

# Read the inject_finding_labels method context
sed -n '155,165p' src/robusta/core/model/events.py

Repository: robusta-dev/robusta

Length of output: 505


🏁 Script executed:

# Check FindingSubject class definition and labels attribute
rg -A 20 'class FindingSubject' src/robusta/core/reporting/base.py | head -40

Repository: robusta-dev/robusta

Length of output: 728


🏁 Script executed:

# Verify the Finding class __init__ with the mutable default argument
sed -n '250,270p' src/robusta/core/reporting/base.py

Repository: robusta-dev/robusta

Length of output: 862


Prevent cross-event label bleed from shared default subjects.

At line 161, inject_finding_labels mutates finding.subject.labels in place. The Finding class uses a mutable default argument for the subject parameter at line 261 of src/robusta/core/reporting/base.py. This causes all Finding instances created without an explicit subject to share the same FindingSubject instance, including its labels dict. The .update() call then mutates this shared dict, leaking labels across unrelated findings and events.

The codebase already acknowledges this as bug-prone (see TODO comment at line 258-259). Fix by changing the default parameter to Optional[FindingSubject] = None and instantiating a new FindingSubject() in the method body when subject is None.

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

In `@src/robusta/core/model/events.py` around lines 158 - 161, The issue is that
Finding uses a shared mutable default FindingSubject which causes
inject_finding_labels to mutate a shared labels dict; fix by changing the
Finding constructor signature (class Finding) to use subject:
Optional[FindingSubject] = None instead of a default instance, and inside the
constructor create a fresh FindingSubject() when subject is None (assign
self.subject = subject or FindingSubject()); keep inject_finding_labels as-is
but this ensures each Finding has its own subject.labels so .update() won't
bleed labels across Findings.

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