Skip to content

Conversation

@aantn
Copy link
Contributor

@aantn aantn commented Aug 11, 2025

Before this PR, the docs had to repeat YAML configurations for Holmes multiple times - once for cli, once for helm chart etc.

Now there is a reusable yaml fence to output markdown with several tabs, without repeating the config each time.

@aantn aantn requested a review from pavangudiwada August 11, 2025 06:53
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 11, 2025

Walkthrough

Adds a new MkDocs custom fences module and registers two YAML fence types, then replaces multiple per-method YAML examples in docs with unified fenced blocks (yaml-toolset-config or yaml-helm-values) across several documentation pages.

Changes

Cohort / File(s) Summary
Custom MkDocs fence formatters
docs/custom_fences.py
New module adding toolset_config_fence_format (3-tab: Holmes CLI, Holmes Helm Chart, Robusta Helm Chart) and helm_tabs_fence_format (2-tab: Holmes Helm Chart, Robusta Helm Chart); escapes HTML, indents Robusta YAML, inserts notes/Helm commands, and disables Jinja processing.
MkDocs configuration
mkdocs.yml
Registers custom fences under pymdownx.superfences.custom_fences: yaml-helm-valueshelm_tabs_fence_format and yaml-toolset-configtoolset_config_fence_format.
Unified toolset config docs
docs/data-sources/builtin-toolsets/coralogix-logs.md, docs/data-sources/builtin-toolsets/grafanaloki.md, docs/data-sources/builtin-toolsets/kafka.md, docs/data-sources/builtin-toolsets/opensearch-status.md, docs/data-sources/builtin-toolsets/prometheus.md, docs/data-sources/builtin-toolsets/rabbitmq.md
Replaced multiple Holmes CLI / Robusta Helm Chart YAML examples with single yaml-toolset-config fenced snippet per section; removed separate snippet includes and Helm command blocks while preserving configuration keys and explanatory text.
Remote MCP servers docs
docs/data-sources/remote-mcp-servers.md
Replaced Helm-chart-specific examples with top-level mcp_servers blocks using yaml-helm-values; removed Helm upgrade commands and adjusted a HolmesGPT opening sentence.

Sequence Diagram(s)

sequenceDiagram
    participant Doc as Markdown file
    participant MkDocs as MkDocs build
    participant SuperFences as pymdownx.superfences
    participant Formatter as custom fence formatter
    participant Output as Generated HTML

    Doc->>MkDocs: contains ```yaml-toolset-config / ```yaml-helm-values
    MkDocs->>SuperFences: parse fenced blocks
    SuperFences->>Formatter: call appropriate formatter
    Formatter->>Formatter: escape YAML, adjust indentation, build tabbed HTML
    Formatter-->>SuperFences: return HTML fragment
    SuperFences-->>MkDocs: embed fragment
    MkDocs-->>Output: finalize page with tabs
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • pavangudiwada
  • arikalon1
  • Sheeproid

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch improve-docs-reusable-fence

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

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

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@aantn aantn enabled auto-merge (squash) August 11, 2025 06:53
Copy link
Contributor

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

🧹 Nitpick comments (6)
docs/custom_fences.py (1)

24-27: Minor DRY: extract YAML indentation helper.

Both functions duplicate the “indent by two spaces” logic. Consider a small helper for maintainability. Optional.

+def _indent_yaml_two_spaces(yaml_text: str) -> str:
+    lines = yaml_text.split("\n")
+    return "\n".join(("  " + ln) if ln else "" for ln in lines)
@@
-    robusta_yaml_lines = yaml_content.split("\n")
-    robusta_yaml_indented = "\n".join(
-        "  " + line if line else "" for line in robusta_yaml_lines
-    )
+    robusta_yaml_indented = _indent_yaml_two_spaces(yaml_content)
@@
-    robusta_yaml_lines = yaml_content.split("\n")
-    robusta_yaml_indented = "\n".join(
-        "  " + line if line else "" for line in robusta_yaml_lines
-    )
+    robusta_yaml_indented = _indent_yaml_two_spaces(yaml_content)

Also applies to: 76-79

docs/data-sources/remote-mcp-servers.md (2)

12-25: yaml-helm-values usage is appropriate here.

Good example of mcp_servers; the fence will render Robusta with holmes: nesting automatically. One nit: tiny grammar in the comment.

-    # human-readable description of the mcp server (this is not seen by the AI model - its just for users)
+    # human-readable description of the MCP server (this is not seen by the AI model — it's just for users)

172-172: Minor copy edit (optional).

Consider: “After deployment completes, you can use HolmesGPT and ask questions like …” Slightly crisper, but current wording is fine.

docs/data-sources/builtin-toolsets/grafanaloki.md (3)

39-50: Good switch to reusable yaml-toolset-config; add a security hint for api_key

The example is clear and correctly disables kubernetes/logs. Please add a short comment guiding users not to store secrets in plaintext configs.

 toolsets:
   grafana/loki:
     enabled: true
     config:
-      api_key: <your grafana API key>
+      # Avoid committing secrets to source control. Prefer env vars or secret management per your deployment.
+      api_key: <your grafana API key>
       url: https://xxxxxxx.grafana.net # Your Grafana cloud account URL
       grafana_datasource_uid: <the UID of the loki data source in Grafana>

One more check: In other toolsets (e.g., azuremonitorlogs), “enabled: true” is shown as an example and the toolset is disabled by default. Please confirm the default for grafana/loki and, if similarly disabled by default, consider adding a brief note near this snippet clarifying that “enabled: true” is illustrative and must be set by users. I can propose the wording if desired.


58-69: Direct connection example looks good; consider noting auth header usage

This configuration accurately omits grafana_datasource_uid and shows multitenancy via X-Scope-OrgID. Add a comment to hint how to pass auth when Loki is protected.

       url: http://loki.logging
       headers:
         X-Scope-OrgID: "<tenant id>" # Set the X-Scope-OrgID if loki multitenancy is enabled
+        # If your Loki requires authentication, add the appropriate header, e.g.:
+        # Authorization: "Bearer <token>"
 
   kubernetes/logs:
     enabled: false # HolmesGPT's default logging mechanism MUST be disabled

77-86: Advanced labels config is correct; small clarity improvement

The example correctly nests labels under config. Add a brief comment to make it explicit that shown values reflect the defaults and only need changing if your Loki uses different label names.

       url: ...
       labels:
+          # Defaults shown; change only if your Loki uses different label keys
           pod: "pod"
           namespace: "namespace"
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c27dc19 and 2eed9df.

📒 Files selected for processing (9)
  • docs/custom_fences.py (1 hunks)
  • docs/data-sources/builtin-toolsets/coralogix-logs.md (1 hunks)
  • docs/data-sources/builtin-toolsets/grafanaloki.md (1 hunks)
  • docs/data-sources/builtin-toolsets/kafka.md (1 hunks)
  • docs/data-sources/builtin-toolsets/opensearch-status.md (1 hunks)
  • docs/data-sources/builtin-toolsets/prometheus.md (1 hunks)
  • docs/data-sources/builtin-toolsets/rabbitmq.md (1 hunks)
  • docs/data-sources/remote-mcp-servers.md (2 hunks)
  • mkdocs.yml (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

📄 CodeRabbit Inference Engine (CLAUDE.md)

**/*.py: ALWAYS place Python imports at the top of the file, not inside functions or methods
Use Ruff for formatting and linting (configured in pyproject.toml)
Type hints required (mypy configuration in pyproject.toml)
Pre-commit hooks enforce quality checks
Don't add convenience logs that give away the problem
Don't write logs that directly state the issue
Ensure historical timestamps are properly handled in logs (especially with Loki)

Files:

  • docs/custom_fences.py
🧠 Learnings (4)
📚 Learning: 2025-08-05T00:42:23.792Z
Learnt from: vishiy
PR: robusta-dev/holmesgpt#782
File: config.example.yaml:31-49
Timestamp: 2025-08-05T00:42:23.792Z
Learning: In robusta-dev/holmesgpt config.example.yaml, the azuremonitorlogs toolset configuration shows "enabled: true" as an example of how to enable the toolset, not as a default setting. The toolset is disabled by default and requires explicit enablement in user configurations.

Applied to files:

  • docs/data-sources/builtin-toolsets/coralogix-logs.md
  • docs/data-sources/builtin-toolsets/opensearch-status.md
  • docs/data-sources/builtin-toolsets/rabbitmq.md
  • docs/data-sources/builtin-toolsets/prometheus.md
  • docs/data-sources/builtin-toolsets/kafka.md
  • docs/data-sources/builtin-toolsets/grafanaloki.md
📚 Learning: 2025-08-10T06:02:54.308Z
Learnt from: CR
PR: robusta-dev/holmesgpt#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-10T06:02:54.308Z
Learning: Applies to holmes/plugins/toolsets/**/*.yaml : The only valid top-level fields for toolsets in YAML are: enabled, name, description, additional_instructions, prerequisites, tools, docs_url, icon_url, installation_instructions, config, url (for MCP toolsets only)

Applied to files:

  • docs/data-sources/builtin-toolsets/coralogix-logs.md
  • docs/data-sources/builtin-toolsets/opensearch-status.md
  • docs/data-sources/builtin-toolsets/rabbitmq.md
  • docs/data-sources/builtin-toolsets/prometheus.md
  • docs/data-sources/builtin-toolsets/kafka.md
📚 Learning: 2025-08-10T06:02:54.308Z
Learnt from: CR
PR: robusta-dev/holmesgpt#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-10T06:02:54.308Z
Learning: Applies to holmes/plugins/toolsets/**/*.yaml : When configuring toolsets in toolsets.yaml files, ALL toolset-specific configuration must go under a config field

Applied to files:

  • docs/data-sources/builtin-toolsets/coralogix-logs.md
  • docs/data-sources/builtin-toolsets/opensearch-status.md
  • docs/data-sources/builtin-toolsets/rabbitmq.md
  • docs/data-sources/builtin-toolsets/prometheus.md
  • docs/data-sources/builtin-toolsets/kafka.md
📚 Learning: 2025-08-10T06:02:54.308Z
Learnt from: CR
PR: robusta-dev/holmesgpt#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-10T06:02:54.308Z
Learning: Applies to holmes/plugins/toolsets/**/*.yaml : Toolsets must be located at holmes/plugins/toolsets/{name}.yaml or {name}/

Applied to files:

  • docs/data-sources/builtin-toolsets/coralogix-logs.md
  • docs/data-sources/builtin-toolsets/rabbitmq.md
  • docs/data-sources/builtin-toolsets/prometheus.md
  • docs/data-sources/builtin-toolsets/kafka.md
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: build (3.12)
  • GitHub Check: build (3.11)
  • GitHub Check: build (3.10)
  • GitHub Check: Pre-commit checks
  • GitHub Check: llm_evals
🔇 Additional comments (7)
mkdocs.yml (1)

109-114: ✅ Import path for custom fences verified

Importing docs.custom_fences succeeds in a Python REPL (module loaded from docs/custom_fences.py), so no changes are needed.

docs/data-sources/builtin-toolsets/rabbitmq.md (1)

12-22: Unified yaml-toolset-config fence looks correct.

Structure matches our toolset schema (enabled + config under toolsets.rabbitmq/core). Good consolidation.

docs/data-sources/builtin-toolsets/coralogix-logs.md (1)

19-30: Consolidated config LGTM.

  • Correct top-level toolsets mapping.
  • Explicitly disables kubernetes/logs to avoid overlap. Clear and consistent.
docs/data-sources/builtin-toolsets/kafka.md (1)

9-27: Kafka toolset block is consistent and valid.

Fields are under config.kafka_clusters as expected. Nice cleanup into a single reusable fence.

docs/data-sources/builtin-toolsets/opensearch-status.md (1)

9-27: OpenSearch status config fence reads well.

Schema follows toolsets → opensearch/status → enabled/config. Matches our docs conventions.

docs/data-sources/builtin-toolsets/prometheus.md (1)

12-22: Prometheus unified fence is correct.

prometheus/metrics under toolsets with config.prometheus_url. Optional headers commented is helpful.

docs/data-sources/remote-mcp-servers.md (1)

165-170: Second MCP example LGTM.

Clear, minimal example for Helm values; works well with the new fence.

Copy link
Contributor

@pavangudiwada pavangudiwada left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Contributor

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

♻️ Duplicate comments (3)
docs/custom_fences.py (3)

25-30: Strip before escaping to normalize whitespace across tabs

This ensures CLI/Helm tabs don’t preserve stray leading/trailing whitespace while Robusta uses stripped content.

-    # Escape HTML in the source to prevent XSS
-    escaped_source = html.escape(source)
-
-    # Strip any leading/trailing whitespace
-    yaml_content = source.strip()
+    # Strip any leading/trailing whitespace and escape for XSS
+    yaml_content = source.strip()
+    escaped_source = html.escape(yaml_content)
@@
-    # Escape HTML in the source to prevent XSS
-    escaped_source = html.escape(source)
-
-    # Strip any leading/trailing whitespace
-    yaml_content = source.strip()
+    # Strip any leading/trailing whitespace and escape for XSS
+    yaml_content = source.strip()
+    escaped_source = html.escape(yaml_content)

Also applies to: 83-88


9-11: Add typing imports and prefer uuid4 import for clarity and mypy/Ruff compliance

Per repo guidelines (mypy + Ruff), add explicit typing imports and import uuid4 directly. This also pairs with the signature typing changes below.

-import html
-import uuid
+import html
+from typing import Any, Mapping
+from uuid import uuid4

13-17: Type-hint fence formatters and underscore unused params to satisfy mypy/Ruff

Provide explicit types and underscore unused parameters to silence Ruff’s unused-arg warnings while preserving pymdownx.superfences’ expected callable signature.

-def toolset_config_fence_format(source, language, css_class, options, md, **kwargs):
+def toolset_config_fence_format(
+    source: str,
+    _language: str,
+    _css_class: str,
+    _options: Mapping[str, Any],
+    _md: Any,
+    **_kwargs: Any,
+) -> str:
@@
-def helm_tabs_fence_format(source, language, css_class, options, md, **kwargs):
+def helm_tabs_fence_format(
+    source: str,
+    _language: str,
+    _css_class: str,
+    _options: Mapping[str, Any],
+    _md: Any,
+    **_kwargs: Any,
+) -> str:

Also applies to: 72-76

🧹 Nitpick comments (3)
docs/custom_fences.py (3)

18-24: Good call on unique radio groups; nit: prefer uuid4().hex over str(...).replace("-", "_")

uuid4().hex avoids string replacement and yields an ID safe for attribute usage.

-    tab_group_id = str(uuid.uuid4()).replace("-", "_")
+    tab_group_id = uuid4().hex
@@
-    tab_group_id = str(uuid.uuid4()).replace("-", "_")
+    tab_group_id = uuid4().hex

Also applies to: 77-82


31-35: Optional: DRY the YAML indentation logic with a tiny helper

Both functions duplicate the same “indent by 2 spaces” logic. A small helper improves readability and consistency.

-    robusta_yaml_lines = yaml_content.split("\n")
-    robusta_yaml_indented = "\n".join(
-        "  " + line if line else "" for line in robusta_yaml_lines
-    )
+    robusta_yaml_indented = indent_yaml(yaml_content, spaces=2)
@@
-    robusta_yaml_lines = yaml_content.split("\n")
-    robusta_yaml_indented = "\n".join(
-        "  " + line if line else "" for line in robusta_yaml_lines
-    )
+    robusta_yaml_indented = indent_yaml(yaml_content, spaces=2)

Add this helper near the imports:

def indent_yaml(content: str, spaces: int = 2) -> str:
    prefix = " " * spaces
    # Keep empty lines empty to avoid trailing spaces in code blocks
    return "\n".join((prefix + line) if line else "" for line in content.splitlines())

Also applies to: 89-93


112-115: Consider making enableHolmesGPT optional in the yaml-helm-values fence

The yaml-helm-values fence is also used in non-Holmes contexts:

  • docs/data-sources/remote-mcp-servers.md:12–15
  • docs/data-sources/remote-mcp-servers.md:165–168

Both of these examples simply show MCP server configuration, so automatically injecting

enableHolmesGPT: true

can be misleading.

I recommend refactoring custom_fences.py to either:

  • Add a flag (e.g. <!-- holmes=true -->) so the fence only prepends enableHolmesGPT when explicitly requested, or
  • Introduce a separate yaml-holmes-values fence for HolmesGPT-specific snippets.

Please adjust the implementation or confirm that always including enableHolmesGPT: true is indeed the intended behavior.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 2eed9df and 841cfdd.

📒 Files selected for processing (2)
  • docs/custom_fences.py (1 hunks)
  • mkdocs.yml (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • mkdocs.yml
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

📄 CodeRabbit Inference Engine (CLAUDE.md)

**/*.py: ALWAYS place Python imports at the top of the file, not inside functions or methods
Type hints are required (project is type-checked with mypy)
Use Ruff for formatting and linting (configured in pyproject.toml)

Files:

  • docs/custom_fences.py
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Pre-commit checks
  • GitHub Check: llm_evals
  • GitHub Check: Pre-commit checks
🔇 Additional comments (1)
docs/custom_fences.py (1)

4-7: MkDocs fence registration confirmed

The mkdocs.yml already registers both custom fences under pymdownx.superfences with the correct paths:

  • yaml-helm-valuesdocs.custom_fences.helm_tabs_fence_format
  • yaml-toolset-configdocs.custom_fences.toolset_config_fence_format

No further changes needed.

@github-actions
Copy link
Contributor

Results of HolmesGPT evals

  • ask_holmes: 21/39 test cases were successful, 1 regressions, 2 skipped, 15 mock failures
Test suite Test case Status
ask 01_how_many_pods
ask 02_what_is_wrong_with_pod
ask 03_what_is_the_command_to_port_forward 🔧
ask 04_related_k8s_events ↪️
ask 05_image_version 🔧
ask 09_crashpod
ask 10_image_pull_backoff 🔧
ask 11_init_containers
ask 14_pending_resources
ask 15_failed_readiness_probe 🔧
ask 17_oom_kill
ask 18_crash_looping_v2
ask 19_detect_missing_app_details 🔧
ask 20_long_log_file_search 🔧
ask 24_misconfigured_pvc 🔧
ask 28_permissions_error
ask 29_events_from_alert_manager ↪️
ask 39_failed_toolset 🔧
ask 41_setup_argo
ask 42_dns_issues_steps_new_tools 🔧
ask 43_current_datetime_from_prompt
ask 45_fetch_deployment_logs_simple
ask 51_logs_summarize_errors 🔧
ask 53_logs_find_term
ask 54_not_truncated_when_getting_pods 🔧
ask 59_label_based_counting
ask 60_count_less_than 🔧
ask 61_exact_match_counting
ask 63_fetch_error_logs_no_errors
ask 79_configmap_mount_issue 🔧
ask 83_secret_not_found 🔧
ask 86_configmap_like_but_secret 🔧
ask 93_calling_datadog
ask 93_calling_datadog
ask 93_calling_datadog
ask 97_logs_clarification_needed
ask 110_k8s_events_image_pull 🔧
ask 24a_misconfigured_pvc_basic 🔧
ask 13a_pending_node_selector_basic 🔧

Legend

  • ✅ the test was successful
  • ↪️ the test was skipped
  • ⚠️ the test failed but is known to be flaky or known to fail
  • 🔧 the test failed due to mock data issues (not a code regression)
  • ❌ the test failed and should be fixed before merging the PR

@aantn aantn merged commit 6fc0227 into master Aug 19, 2025
10 of 11 checks passed
@aantn aantn deleted the improve-docs-reusable-fence branch August 19, 2025 06:42
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