Skip to content

Weekly run of a fast benchmark - #1329

Merged
Sheeproid merged 10 commits into
masterfrom
weekly-benchmark
Jan 6, 2026
Merged

Sheeproid merged 10 commits into
masterfrom
weekly-benchmark

Conversation

@Sheeproid

@Sheeproid Sheeproid commented Jan 5, 2026 •

Copy link
Copy Markdown
Collaborator
Screenshot 2026-01-05 at 16 15 23

Summary by CodeRabbit

  • New Features

    • Selectable benchmark types (Fast / Full) via CLI and workflow input, mutual-exclusion handling, weekly scheduled runs, and artifacts for both benchmark types.
    • Automated creation/updating of timestamped PRs containing benchmark summaries and results.
  • Documentation

    • Added Fast and Full benchmark result pages, per-run history pages, a Benchmark History index, a latest-results redirect, and updated navigation labels.

✏️ Tip: You can customize this high-level summary in your review settings.

Signed-off-by: Tomer Keshet <tomer@robusta.dev>
Signed-off-by: Tomer Keshet <tomer@robusta.dev>
Signed-off-by: Tomer Keshet <tomer@robusta.dev>
Signed-off-by: Tomer Keshet <tomer@robusta.dev>
@linux-foundation-easycla

linux-foundation-easycla Bot commented Jan 5, 2026 •

Copy link
Copy Markdown

CLA Not Signed

@coderabbitai

coderabbitai Bot commented Jan 5, 2026 •

Copy link
Copy Markdown
Contributor

Walkthrough

Adds a two-tier benchmarking flow (fast/full) across CI, local runner, report generation, and docs: introduces a benchmark_type input/CLI option, builds/exports a runnable command, writes timestamped history results, uploads artifacts, and automates creating/updating a PR with benchmark outputs.

Changes

Cohort / File(s) Summary
GitHub Actions Workflow
​.github/workflows/eval-benchmarks.yaml
Adds benchmark_type input and weekly schedule; replaces test-detection with a build-command step that emits command and benchmark_type; executes the built command; uploads fast/full artifacts and eval_results.json; commits history and creates/updates a timestamped PR.
Local runner & report generator
run_benchmarks_local.py, tests/generate_eval_report.py
Introduces --benchmark-type and BENCHMARK_TYPES; enforces mutual exclusivity with markers; derives markers from benchmark_type (default fast); selects output filenames and benchmark-aware titles/info boxes; writes history files and a latest-results redirect.
Documentation & generated results
docs/development/evaluations/index.md, docs/development/evaluations/.nav.yml, docs/development/evaluations/fast-benchmark-results.md, .../full-benchmark-results.md, .../history/*.md, docs/development/evaluations/latest-results.md
Adds “Benchmark Types” section and nav label change; adds fast & full result pages and a timestamped history entry; replaces latest-results with a redirect to history.
Toolsets / plugins
holmes/plugins/toolsets/__init__.py, holmes/plugins/toolsets/elasticsearch/..., holmes/plugins/toolsets/grafana/common.py
Consolidates and exposes additional toolset imports; applies formatting/structural changes across Elasticsearch tool classes (no API changes); removes unused imports in Grafana common.
Tests / CI helpers
conftest.py, tests/generate_eval_report.py
Adds benchmark-type-aware report generation; conftest.py formatting-only change (no behavior change).
Generated artifacts (history & results)
docs/development/evaluations/*.md, docs/development/evaluations/history/*.md
New/updated markdown result pages with benchmark metadata, raw/detailed result tables, and history/redirect behavior.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    actor Trigger as Trigger\n(schedule / workflow_dispatch)
    participant Builder as Build Benchmark Command
    participant Runner as Execute Benchmark Command
    participant Storage as Artifact Store / Repo
    participant PRSvc as PR Automation (git / gh)

    Trigger->>Builder: inputs (benchmark_type / markers / models / iterations)
    Builder->>Builder: construct `command` and set `benchmark_type`
    Builder-->>Runner: export `command`, `benchmark_type`
    Runner->>Runner: run constructed benchmark command (script)
    Runner->>Storage: upload artifacts (fast/full results, eval_results.json)
    Storage->>PRSvc: write timestamped history files
    PRSvc->>PRSvc: commit branch, push, create/update PR (title/body include benchmark_type + command)
    PRSvc-->>Trigger: PR opened/updated
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • aantn
  • arikalon1

Pre-merge checks

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 36.36% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: the PR implements a weekly automated fast benchmark run with comprehensive workflow, documentation, and result tracking updates.

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.

@github-actions

github-actions Bot commented Jan 5, 2026 •

Copy link
Copy Markdown
Contributor

✅ Docker image ready for 56c4497 (built in 1m 1s)

⚠️ 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/holmes:56c4497
docker tag us-central1-docker.pkg.dev/robusta-development/temporary-builds/holmes:56c4497 me-west1-docker.pkg.dev/robusta-development/development/holmes-dev:56c4497
docker push me-west1-docker.pkg.dev/robusta-development/development/holmes-dev:56c4497

Patch Helm values in one line (choose the chart you use):

HolmesGPT chart:

helm upgrade --install holmesgpt ./helm/holmes \
  --set registry=me-west1-docker.pkg.dev/robusta-development/development \
  --set image=holmes-dev:56c4497

Robusta wrapper chart:

helm upgrade --install robusta robusta/robusta \
  --reuse-values \
  --set holmes.registry=me-west1-docker.pkg.dev/robusta-development/development \
  --set holmes.image=holmes-dev:56c4497

@github-actions

github-actions Bot commented Jan 5, 2026 •

Copy link
Copy Markdown
Contributor

📂 Previous Runs

📜 Run @ a974979 (#20740934476)

✅ Results of HolmesGPT evals

Automatically triggered by commit a974979 on branch weekly-benchmark

View workflow logs

Results of HolmesGPT evals

  • ask_holmes: 9/9 test cases were successful, 0 regressions
Status Test case Time Turns Tools Cost
✅ 09_crashpod 31.0s ±0% 5 12 $0.1569
✅ 101_loki_historical_logs_pod_deleted 47.3s ↓14% 6 13 $0.1939
✅ 111_pod_names_contain_service 42.5s ±0% 8 16 $0.1908
✅ 12_job_crashing 38.9s ↓23% 7 13 $0.1748
✅ 162_get_runbooks 45.1s ±0% 7 17 $0.2181
✅ 176_network_policy_blocking_traffic_no_runbooks 38.7s ±0% 6 14 $0.1761
✅ 24_misconfigured_pvc 43.6s ↑15% 8 19 $0.1924
✅ 43_current_datetime_from_prompt 3.5s ±0% 1 — $0.0618
✅ 61_exact_match_counting 10.9s ±0% 3 3 $0.0858
Total 33.5s avg 5.7 avg 13.4 avg $1.4505

Time/Cost columns show % change vs historical average (↑slower/costlier, ↓faster/cheaper). Changes under 10% shown as ±0%.

Historical Comparison Details

Filter: excluding branch 'weekly-benchmark'

Status: Success - 10 test/model combinations loaded

Experiments compared (30):

Comparison indicators:

  • ±0% — diff under 10% (within noise threshold)
  • ↑N%/↓N% — diff 10-25%
  • ↑N%/↓N% — diff over 25% (significant)
📜 Run @ d0348c3 (#20721255719)

✅ Results of HolmesGPT evals

Automatically triggered by commit d0348c3 on branch weekly-benchmark

View workflow logs

Results of HolmesGPT evals

  • ask_holmes: 8/9 test cases were successful, 1 regressions
Status Test case Time Turns Tools Cost
✅ 09_crashpod 37.8s ±0% 7 14 $0.1272
✅ 101_loki_historical_logs_pod_deleted 61.4s ±0% 10 19 $0.1960
✅ 111_pod_names_contain_service 42.3s ±0% 8 18 $0.1404
✅ 12_job_crashing 46.7s ±0% 8 19 $0.1696
❌ 162_get_runbooks 40.0s ↓22% 6 17 $0.1466
✅ 176_network_policy_blocking_traffic_no_runbooks 40.9s ±0% 6 15 $0.1359
✅ 24_misconfigured_pvc 32.6s ↓15% 6 15 $0.1023
✅ 43_current_datetime_from_prompt 3.2s ±0% 1 — $0.0085
✅ 61_exact_match_counting 10.7s ±0% 3 3 $0.0326
Total 35.1s avg 6.1 avg 15.0 avg $1.0591

Time/Cost columns show % change vs historical average (↑slower/costlier, ↓faster/cheaper). Changes under 10% shown as ±0%.

Historical Comparison Details

Filter: excluding branch 'weekly-benchmark'

Status: Success - 11 test/model combinations loaded

Experiments compared (30):

Comparison indicators:

  • ±0% — diff under 10% (within noise threshold)
  • ↑N%/↓N% — diff 10-25%
  • ↑N%/↓N% — diff over 25% (significant)

⚠️ 1 Failure Detected

📜 Run @ 8bb10ab (#20720486463)

✅ Results of HolmesGPT evals

Automatically triggered by commit 8bb10ab on branch weekly-benchmark

View workflow logs

Results of HolmesGPT evals

  • ask_holmes: 9/9 test cases were successful, 0 regressions
Status Test case Time Turns Tools Cost
✅ 09_crashpod 30.8s ↓15% 5 12 $0.1561
✅ 101_loki_historical_logs_pod_deleted 45.2s ↓32% 7 15 $0.1955
✅ 111_pod_names_contain_service 34.4s ↓18% 6 14 $0.1600
✅ 12_job_crashing 48.8s ±0% 9 20 $0.2374
✅ 162_get_runbooks 48.5s ±0% 7 19 $0.2347
✅ 176_network_policy_blocking_traffic_no_runbooks 36.9s ↓13% 6 14 $0.1741
✅ 24_misconfigured_pvc 33.0s ↓16% 6 15 $0.1623
✅ 43_current_datetime_from_prompt 3.4s ±0% 1 — $0.0618
✅ 61_exact_match_counting 10.8s ±0% 3 3 $0.0859
Total 32.4s avg 5.6 avg 14.0 avg $1.4678

Time/Cost columns show % change vs historical average (↑slower/costlier, ↓faster/cheaper). Changes under 10% shown as ±0%.

Historical Comparison Details

Filter: excluding branch 'weekly-benchmark'

Status: Success - 11 test/model combinations loaded

Experiments compared (30):

Comparison indicators:

  • ±0% — diff under 10% (within noise threshold)
  • ↑N%/↓N% — diff 10-25%
  • ↑N%/↓N% — diff over 25% (significant)
📜 Run @ 6f26b3d (#20718971370)

✅ Results of HolmesGPT evals

Automatically triggered by commit 6f26b3d on branch weekly-benchmark

View workflow logs

Results of HolmesGPT evals

  • ask_holmes: 9/9 test cases were successful, 0 regressions
Status Test case Time Turns Tools Cost
✅ 09_crashpod 35.2s ±0% 6 13 $0.1112
✅ 101_loki_historical_logs_pod_deleted 68.5s ±0% 11 24 $0.2090
✅ 111_pod_names_contain_service 49.7s ↑20% 9 20 $0.1623
✅ 12_job_crashing 52.6s ±0% 9 18 $0.1640
✅ 162_get_runbooks 55.9s ±0% 8 17 $0.1884
✅ 176_network_policy_blocking_traffic_no_runbooks 42.0s ±0% 7 14 $0.1199
✅ 24_misconfigured_pvc 37.6s ±0% 7 16 $0.1232
✅ 43_current_datetime_from_prompt 3.4s ±0% 1 — $0.0085
✅ 61_exact_match_counting 11.4s ±0% 3 3 $0.0326
Total 39.6s avg 6.8 avg 15.6 avg $1.1191

Time/Cost columns show % change vs historical average (↑slower/costlier, ↓faster/cheaper). Changes under 10% shown as ±0%.

Historical Comparison Details

Filter: excluding branch 'weekly-benchmark'

Status: Success - 11 test/model combinations loaded

Experiments compared (30):

Comparison indicators:

  • ±0% — diff under 10% (within noise threshold)
  • ↑N%/↓N% — diff 10-25%
  • ↑N%/↓N% — diff over 25% (significant)
📜 Run @ 3175f13 (#20718124662)

✅ Results of HolmesGPT evals

Automatically triggered by commit 3175f13 on branch weekly-benchmark

View workflow logs

Results of HolmesGPT evals

  • ask_holmes: 9/9 test cases were successful, 0 regressions
Status Test case Time Turns Tools Cost
✅ 09_crashpod 35.2s ±0% 5 12 $0.1576
✅ 101_loki_historical_logs_pod_deleted 53.8s ↓20% 8 15 $0.2013
✅ 111_pod_names_contain_service 48.0s ↑16% 7 15 $0.1784
✅ 12_job_crashing 70.3s ↑39% 10 24 $0.2665
✅ 162_get_runbooks 60.0s ↑14% 8 15 $0.2294
✅ 176_network_policy_blocking_traffic_no_runbooks 45.4s ±0% 6 15 $0.1890
✅ 24_misconfigured_pvc 43.3s ±0% 7 19 $0.1847
✅ 43_current_datetime_from_prompt 4.1s ↑18% 1 — $0.0618
✅ 61_exact_match_counting 13.1s ↑11% 3 3 $0.0859
Total 41.5s avg 6.1 avg 14.8 avg $1.5546

Time/Cost columns show % change vs historical average (↑slower/costlier, ↓faster/cheaper). Changes under 10% shown as ±0%.

Historical Comparison Details

Filter: excluding branch 'weekly-benchmark'

Status: Success - 10 test/model combinations loaded

Experiments compared (30):

Comparison indicators:

  • ±0% — diff under 10% (within noise threshold)
  • ↑N%/↓N% — diff 10-25%
  • ↑N%/↓N% — diff over 25% (significant)

✅ Results of HolmesGPT evals

Automatically triggered by commit 766775b on branch weekly-benchmark

View workflow logs

Results of HolmesGPT evals

  • ask_holmes: 9/9 test cases were successful, 0 regressions
Status Test case Time Turns Tools Cost
✅ 09_crashpod 32.9s ±0% 6 13 $0.1639
✅ 101_loki_historical_logs_pod_deleted 55.8s ±0% 10 16 $0.2273
✅ 111_pod_names_contain_service 42.9s ±0% 8 19 $0.2007
✅ 12_job_crashing 54.9s ±0% 10 23 $0.2627
✅ 162_get_runbooks 42.5s ↓12% 7 14 $0.2044
✅ 176_network_policy_blocking_traffic_no_runbooks 38.9s ±0% 6 15 $0.1858
✅ 24_misconfigured_pvc 36.9s ±0% 7 17 $0.1797
✅ 43_current_datetime_from_prompt 3.0s ↓12% 1 — $0.0618
✅ 61_exact_match_counting 10.6s ±0% 3 3 $0.0870
Total 35.4s avg 6.4 avg 15.0 avg $1.5731

Time/Cost columns show % change vs historical average (↑slower/costlier, ↓faster/cheaper). Changes under 10% shown as ±0%.

Historical Comparison Details

Filter: excluding branch 'weekly-benchmark'

Status: Success - 10 test/model combinations loaded

Experiments compared (30):

Comparison indicators:

  • ±0% — diff under 10% (within noise threshold)
  • ↑N%/↓N% — diff 10-25%
  • ↑N%/↓N% — diff over 25% (significant)
📖 Legend
Icon Meaning
✅ The test was successful
➖ The test was skipped
⚠️ The test failed but is known to be flaky or known to fail
🚧 The test had a setup failure (not a code regression)
🔧 The test failed due to mock data issues (not a code regression)
🚫 The test was throttled by API rate limits/overload
❌ The test failed and should be fixed before merging the PR
🔄 Re-run evals manually

⚠️ Warning: /eval comments always run using the workflow from master, not from this PR branch. If you modified the GitHub Action (e.g., added secrets or env vars), those changes won't take effect.

To test workflow changes, use the GitHub CLI or Actions UI instead:

gh workflow run eval-regression.yaml --repo HolmesGPT/holmesgpt --ref weekly-benchmark -f markers=regression -f filter=

Option 1: Comment on this PR with /eval:

/eval
markers: regression

Or with more options (one per line):

/eval
model: gpt-4o
markers: regression
filter: 09_crashpod
iterations: 5

Run evals on a different branch (e.g., master) for comparison:

/eval
branch: master
markers: regression
Option Description
model Model(s) to test (default: same as automatic runs)
markers Pytest markers (no default - runs all tests!)
filter Pytest -k filter (use /list to see valid eval names)
iterations Number of runs, max 10
branch Run evals on a different branch (for cross-branch comparison)

Quick re-run: Use /rerun to re-run the most recent /eval on this PR with the same parameters.

Option 2: Trigger via GitHub Actions UI → "Run workflow"

🏷️ Valid markers

benchmark, chain-of-causation, compaction, context_window, coralogix, counting, database, datadog, datetime, easy, elasticsearch, embeds, grafana-dashboard, hard, kafka, kubernetes, leaked-information, logs, loki, medium, metrics, network, newrelic, no-cicd, numerical, one-test, port-forward, prometheus, question-answer, regression, runbooks, slackbot, storage, toolset-limitation, traces, transparency


Commands: /eval · /rerun · /list

CLI: gh workflow run eval-regression.yaml --repo HolmesGPT/holmesgpt --ref weekly-benchmark -f markers=regression -f filter=

@Sheeproid
Sheeproid requested a review from aantn January 5, 2026 14:15

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Fix all issues with AI Agents 🤖
In @tests/generate_eval_report.py:
- Line 1347: Remove the in-function "import re" and instead add "import re" to
the module-level imports at the top of the file (alongside the other imports),
then delete the original import statement where it currently appears so there
are no duplicate imports.
🧹 Nitpick comments (3)
docs/development/evaluations/latest-results.md (1)

9-9: Improve link text for better accessibility and UX.

The link text "click here" is not descriptive. Prefer a meaningful description of the link destination, such as "latest benchmark results" or "benchmark results history."

🔎 Suggested fix
-If you are not redirected automatically, [click here](../history/results_20260104_174301/).
+If you are not redirected automatically, [view the latest benchmark results](../history/results_20260104_174301/).
tests/generate_eval_report.py (1)

1349-1358: Unused variables from tuple unpacking.

The variables hour, minute, and second are extracted but never used. Use underscores to indicate they are intentionally ignored.

Proposed fix
-        year, month, day, hour, minute, second = history_match.groups()
+        year, month, day, _hour, _minute, _second = history_match.groups()
.github/workflows/eval-benchmarks.yaml (1)

118-161: PR title says "Weekly" even for manual runs.

Line 146 hardcodes "Weekly Benchmark Results" but this workflow can also be triggered manually via workflow_dispatch. Consider making the title dynamic.

Suggested fix
-          PR_TITLE="Weekly Benchmark Results $(date +%Y-%m-%d)"
+          if [ "${{ github.event_name }}" == "schedule" ]; then
+            PR_TITLE="Weekly Benchmark Results $(date +%Y-%m-%d)"
+          else
+            PR_TITLE="Benchmark Results $(date +%Y-%m-%d)"
+          fi

Also note: same-day runs will push to the same branch (automated/benchmark-YYYYMMDD) with --force, which will overwrite previous results. This is acceptable for automation but worth documenting.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 661ab7c and 3175f13.

📒 Files selected for processing (10)
  • .github/workflows/eval-benchmarks.yaml
  • docs/development/evaluations/.nav.yml
  • docs/development/evaluations/fast-benchmark-results.md
  • docs/development/evaluations/full-benchmark-results.md
  • docs/development/evaluations/history/index.md
  • docs/development/evaluations/history/results_20260104_174301.md
  • docs/development/evaluations/index.md
  • docs/development/evaluations/latest-results.md
  • run_benchmarks_local.py
  • tests/generate_eval_report.py
🧰 Additional context used
📓 Path-based instructions (3)
docs/**/*.md

📄 CodeRabbit inference engine (CLAUDE.md)

Add blank line between header/bold text and a list in MkDocs documentation files, otherwise lists won't render properly

Files:

  • docs/development/evaluations/fast-benchmark-results.md
  • docs/development/evaluations/full-benchmark-results.md
  • docs/development/evaluations/history/index.md
  • docs/development/evaluations/history/results_20260104_174301.md
  • docs/development/evaluations/latest-results.md
  • docs/development/evaluations/index.md
**/*.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 with configuration in pyproject.toml
Type hints required (mypy configuration in pyproject.toml)
Pre-commit hooks enforce quality checks on Python files

Files:

  • tests/generate_eval_report.py
  • run_benchmarks_local.py
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

tests/**/*.py: Tests should match source structure under tests/
Live execution is now enabled by default to ensure tests match real-world behavior

Files:

  • tests/generate_eval_report.py
🧠 Learnings (2)
📚 Learning: 2026-01-05T11:14:20.208Z
Learnt from: CR
Repo: HolmesGPT/holmesgpt PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-05T11:14:20.208Z
Learning: Applies to tests/llm/**/*.yaml : Use real-world scenarios in eval tests (ML pipelines with checkpoint issues, database connection pools) not simulated scenarios

Applied to files:

  • docs/development/evaluations/fast-benchmark-results.md
  • docs/development/evaluations/full-benchmark-results.md
  • docs/development/evaluations/history/results_20260104_174301.md
  • docs/development/evaluations/index.md
📚 Learning: 2026-01-05T11:14:20.209Z
Learnt from: CR
Repo: HolmesGPT/holmesgpt PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-05T11:14:20.209Z
Learning: Add required environment variables to .github/workflows/eval-regression.yaml 'Run tests' step when adding evals for new cloud service integrations

Applied to files:

  • .github/workflows/eval-benchmarks.yaml
🪛 markdownlint-cli2 (0.18.1)
docs/development/evaluations/latest-results.md

9-9: Link text should be descriptive

(MD059, descriptive-link-text)

🪛 Ruff (0.14.10)
tests/generate_eval_report.py

1356-1356: Unpacked variable hour is never used

Prefix it with an underscore or any other dummy variable pattern

(RUF059)


1356-1356: Unpacked variable minute is never used

Prefix it with an underscore or any other dummy variable pattern

(RUF059)


1356-1356: Unpacked variable second is never used

Prefix it with an underscore or any other dummy variable pattern

(RUF059)

run_benchmarks_local.py

243-243: subprocess call: check for execution of untrusted input

(S603)


254-254: subprocess call: check for execution of untrusted input

(S603)

⏰ 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). (4)
  • GitHub Check: build
  • GitHub Check: build (3.10)
  • GitHub Check: build (3.11)
  • GitHub Check: build (3.12)
🔇 Additional comments (23)
docs/development/evaluations/.nav.yml (1)

4-4: LGTM! Simplified navigation label aligns with new branding.

The change from "Historical Results" to "History" is more concise and aligns with the new "Benchmark History" page title.

docs/development/evaluations/index.md (2)

9-18: LGTM! Clear benchmark types documentation.

The new "Benchmark Types" section effectively distinguishes fast and full benchmarks with a well-formatted table and clear descriptions. The ⚡ emoji provides good visual distinction.


20-27: LGTM! Test categories section properly formatted.

The updated test categories list is well-structured and follows MkDocs formatting guidelines with proper blank line spacing.

run_benchmarks_local.py (8)

17-21: LGTM! Clear benchmark type definitions.

The BENCHMARK_TYPES constant provides a clean mapping between benchmark types and their corresponding pytest markers. This centralizes the configuration and makes it easy to maintain.


36-36: LGTM! Proper type hints and parameter handling.

The new benchmark_type parameter is correctly typed as Optional[str] with an appropriate default value of None, and properly stored as an instance variable.

Also applies to: 45-45


56-57: LGTM! Clear benchmark type display.

The conditional display of the benchmark type helps users understand which benchmark configuration is running.


209-240: LGTM! Well-structured benchmark-type-aware report generation.

The logic correctly determines output files based on benchmark type and builds appropriate commands. The fallback to full-benchmark-results.md for custom markers is sensible.


285-286: LGTM! Consistent benchmark type handling in summary.

The summary display correctly shows the benchmark type and determines the appropriate result file, maintaining consistency with the report generation logic.

Also applies to: 305-313


381-393: LGTM! Well-defined CLI arguments with validation.

The new --benchmark-type argument uses proper validation with choices, and both mutually exclusive arguments clearly document their relationship in help text.


438-469: LGTM! Robust validation and default behavior.

The mutual exclusivity validation is correctly implemented, and the logic properly handles three scenarios: custom markers, explicit benchmark type, and default to fast-benchmark. The default behavior (fast-benchmark) aligns with the PR objectives.


257-274: Path construction is correct for MkDocs.

MkDocs serves markdown files with the .md extension removed and a trailing slash. The code correctly generates relative paths like ../history/results_20260104_174301/ for redirect targets, which aligns with MkDocs' URL structure as confirmed in the mkdocs.yml navigation entries.

docs/development/evaluations/history/index.md (1)

1-10: LGTM! Clear benchmark history documentation.

The updated history page provides clear distinction between fast and full benchmarks with consistent use of the ⚡ emoji and proper MkDocs formatting.

docs/development/evaluations/full-benchmark-results.md (2)

1-16: LGTM! Well-structured full benchmark results header.

The header clearly identifies this as a full benchmark with appropriate metadata and a well-formatted info box distinguishing it from fast benchmarks.


17-71: LGTM! Well-formatted benchmark results tables.

The results tables and detailed sections are properly formatted with appropriate links to Braintrust for deeper analysis. The auto-generation footer clearly indicates this file is maintained by CI.

docs/development/evaluations/fast-benchmark-results.md (1)

1-71: LGTM!

The document is properly formatted with appropriate blank lines between sections and tables. The admonition block and table structures follow MkDocs conventions correctly.

docs/development/evaluations/history/results_20260104_174301.md (1)

1-121: LGTM!

The generated results document is well-structured with proper blank lines between headers, sections, and tables. All MkDocs formatting conventions are followed correctly.

tests/generate_eval_report.py (4)

232-237: LGTM!

The new --benchmark-type CLI argument is well-defined with appropriate choices and a sensible default of None.


1333-1343: LGTM!

The benchmark type label and icon logic is clean and handles all three cases (fast, full, and unspecified) appropriately.


1359-1364: LGTM!

The title generation correctly incorporates the benchmark icon for both history files and main result files.


1443-1461: LGTM!

The info boxes use proper MkDocs admonition syntax and clearly document the markers, schedule, and purpose for each benchmark type.

.github/workflows/eval-benchmarks.yaml (3)

7-30: LGTM!

The new benchmark_type input with choices and the weekly schedule trigger are well-configured. Good use of mutual exclusivity documentation in the descriptions.


57-92: Potential quoting issue with custom markers.

Line 71 embeds escaped quotes into the command string, which may not expand correctly when executed on line 105. Consider using single quotes or avoiding embedded quotes.

Additionally, when both benchmark_type (default) and empty test_markers are provided in workflow_dispatch, the condition on line 70 will be false (empty string), falling through to line 72 which adds the benchmark_type. This behavior appears intentional but should be verified.

Suggested safer approach for custom markers
-            if [ -n "$CUSTOM_MARKERS" ]; then
-              CMD="$CMD --markers \"$CUSTOM_MARKERS\""
+            if [ -n "$CUSTOM_MARKERS" ]; then
+              CMD="$CMD --markers '$CUSTOM_MARKERS'"

Or avoid quotes entirely if markers don't contain spaces:

-            if [ -n "$CUSTOM_MARKERS" ]; then
-              CMD="$CMD --markers \"$CUSTOM_MARKERS\""
+            if [ -n "$CUSTOM_MARKERS" ]; then
+              CMD="$CMD --markers $CUSTOM_MARKERS"

104-105: No changes needed.

The script is executable (mode 100755) with a proper shebang (#!/usr/bin/env python3), so direct command substitution works as intended. Since all inputs are controlled through the GitHub Actions workflow interface and arguments are properly escaped, the command execution is safe.

Comment thread tests/generate_eval_report.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 (1)
tests/generate_eval_report.py (1)

1347-1347: Move import re to the top of the file.

As previously noted, Python imports should be placed at the top of the file per coding guidelines.

🧹 Nitpick comments (4)
holmes/plugins/toolsets/__init__.py (1)

98-98: LGTM! Toolsets instantiated correctly.

All three toolsets are properly instantiated with their default constructors.

Optional organizational suggestion: Consider grouping the OpenSearchQueryAssistToolset (line 98) together with the Elasticsearch toolsets (lines 107-108), since OpenSearch is an Elasticsearch fork. This would improve discoverability and maintainability.

🔎 Optional refactor to group related toolsets
     DatadogGeneralToolset(),
     DatadogMetricsToolset(),
     DatadogTracesToolset(),
-    OpenSearchQueryAssistToolset(),
     CoralogixToolset(),
     RabbitMQToolset(),
     GitToolset(),
     BashExecutorToolset(),
     MongoDBAtlasToolset(),
     RunbookToolset(dal=dal, additional_search_paths=additional_search_paths),
     AzureSQLToolset(),
     ServiceNowTablesToolset(),
     ElasticsearchDataToolset(),
     ElasticsearchClusterToolset(),
+    OpenSearchQueryAssistToolset(),
 ]

Also applies to: 107-108

holmes/plugins/toolsets/elasticsearch/elasticsearch.py (1)

74-108: Consider using try-except-else pattern for clearer intent.

The success return at lines 80-83 could be moved to an else block following the try-except pattern. This makes the happy path more explicit and is more idiomatic Python.

🔎 Proposed refactor using else block
     def _perform_health_check(self) -> Tuple[bool, str]:
         """Perform a health check by querying cluster health."""
         try:
             response = self._make_request("GET", "_cluster/health", timeout=10)
+        except requests.exceptions.HTTPError as e:
+            if e.response.status_code == 401:
+                return (
+                    False,
+                    "Elasticsearch authentication failed. Check your API key or credentials.",
+                )
+            elif e.response.status_code == 403:
+                return (
+                    False,
+                    "Elasticsearch access denied. Ensure your credentials have cluster access.",
+                )
+            else:
+                return (
+                    False,
+                    f"Elasticsearch API error: {e.response.status_code} - {e.response.text}",
+                )
+        except requests.exceptions.ConnectionError:
+            return (
+                False,
+                f"Failed to connect to Elasticsearch at {self.elasticsearch_config.url}",
+            )
+        except requests.exceptions.Timeout:
+            return False, "Elasticsearch health check timed out"
+        except Exception as e:
+            return False, f"Elasticsearch health check failed: {str(e)}"
+        else:
             cluster_name = response.get("cluster_name", "unknown")
             status = response.get("status", "unknown")
             return (
                 True,
                 f"Connected to Elasticsearch cluster '{cluster_name}' (status: {status})",
             )
-        except requests.exceptions.HTTPError as e:
-            if e.response.status_code == 401:
-                return (
-                    False,
-                    "Elasticsearch authentication failed. Check your API key or credentials.",
-                )
-            elif e.response.status_code == 403:
-                return (
-                    False,
-                    "Elasticsearch access denied. Ensure your credentials have cluster access.",
-                )
-            else:
-                return (
-                    False,
-                    f"Elasticsearch API error: {e.response.status_code} - {e.response.text}",
-                )
-        except requests.exceptions.ConnectionError:
-            return (
-                False,
-                f"Failed to connect to Elasticsearch at {self.elasticsearch_config.url}",
-            )
-        except requests.exceptions.Timeout:
-            return False, "Elasticsearch health check timed out"
-        except Exception as e:
-            return False, f"Elasticsearch health check failed: {str(e)}"
tests/generate_eval_report.py (1)

1354-1358: Prefix unused variables with underscore.

The hour, minute, and second variables are unpacked but never used. Prefix them with underscores to indicate they are intentionally ignored.

Proposed fix
     if history_match:
         # History file - use date as title, add ⚡ for fast benchmarks
-        year, month, day, hour, minute, second = history_match.groups()
+        year, month, day, _hour, _minute, _second = history_match.groups()
         date_obj = datetime(int(year), int(month), int(day))
.github/workflows/eval-benchmarks.yaml (1)

152-161: Existing PR body/title is not updated.

When an existing PR is found, the workflow only logs a message but doesn't update the PR body with the new benchmark type and command information. Consider updating the PR with the latest run details.

Proposed fix
          # Check if PR already exists
          EXISTING_PR=$(gh pr list --head "$BRANCH_NAME" --json number --jq '.[0].number')
          if [ -n "$EXISTING_PR" ]; then
            echo "Updating existing PR #$EXISTING_PR"
+           gh pr edit "$EXISTING_PR" \
+             --title "$PR_TITLE" \
+             --body "$PR_BODY"
          else
            gh pr create \
              --title "$PR_TITLE" \
              --body "$PR_BODY" \
              --base master \
              --head "$BRANCH_NAME"
          fi
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3175f13 and 8bb10ab.

📒 Files selected for processing (6)
  • .github/workflows/eval-benchmarks.yaml
  • conftest.py
  • holmes/plugins/toolsets/__init__.py
  • holmes/plugins/toolsets/elasticsearch/elasticsearch.py
  • holmes/plugins/toolsets/grafana/common.py
  • tests/generate_eval_report.py
💤 Files with no reviewable changes (1)
  • holmes/plugins/toolsets/grafana/common.py
✅ Files skipped from review due to trivial changes (1)
  • conftest.py
🧰 Additional context used
📓 Path-based instructions (4)
**/*.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 with configuration in pyproject.toml
Type hints required (mypy configuration in pyproject.toml)
Pre-commit hooks enforce quality checks on Python files

Files:

  • holmes/plugins/toolsets/elasticsearch/elasticsearch.py
  • holmes/plugins/toolsets/__init__.py
  • tests/generate_eval_report.py
holmes/plugins/toolsets/**/*.{py,yaml}

📄 CodeRabbit inference engine (CLAUDE.md)

holmes/plugins/toolsets/**/*.{py,yaml}: All toolsets MUST return detailed error messages from underlying APIs to enable LLM self-correction, including exact query/command executed, time ranges/parameters/filters used, and full API error response (status code and message)
For 'no data' responses in toolsets, specify what was searched and where
Never return unbounded data from APIs - always include filter parameters on tools that query collections

Files:

  • holmes/plugins/toolsets/elasticsearch/elasticsearch.py
  • holmes/plugins/toolsets/__init__.py
holmes/plugins/toolsets/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

holmes/plugins/toolsets/**/*.py: Use requests library for HTTP calls in Python toolsets, not specialized client libraries like opensearchpy
Implement simple Pydantic config class with validation for Python toolsets
Include health check in prerequisites_callable() method for Python toolsets
Each tool in Python toolsets should be a thin wrapper around a single API endpoint
Use JsonFilterMixin for client-side filtering when server-side filtering is not possible, adding max_depth and jq parameters
Maintain backwards compatibility in toolset config using Pydantic's extra='allow' when renaming config fields
Only define current field names in toolset config schema with extra='allow' to avoid polluting model_dump() output with deprecated fields
Use @model_validator(mode='after') in toolset config to map old field names to new names and log deprecation warnings
Bash toolset validates commands for safety

Files:

  • holmes/plugins/toolsets/elasticsearch/elasticsearch.py
  • holmes/plugins/toolsets/__init__.py
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

tests/**/*.py: Tests should match source structure under tests/
Live execution is now enabled by default to ensure tests match real-world behavior

Files:

  • tests/generate_eval_report.py
🧠 Learnings (14)
📚 Learning: 2026-01-05T11:14:20.209Z
Learnt from: CR
Repo: HolmesGPT/holmesgpt PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-05T11:14:20.209Z
Learning: Add required environment variables to .github/workflows/eval-regression.yaml 'Run tests' step when adding evals for new cloud service integrations

Applied to files:

  • .github/workflows/eval-benchmarks.yaml
📚 Learning: 2026-01-05T11:14:20.208Z
Learnt from: CR
Repo: HolmesGPT/holmesgpt PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-05T11:14:20.208Z
Learning: Applies to holmes/plugins/toolsets/**/*.py : Use requests library for HTTP calls in Python toolsets, not specialized client libraries like opensearchpy

Applied to files:

  • holmes/plugins/toolsets/elasticsearch/elasticsearch.py
  • holmes/plugins/toolsets/__init__.py
📚 Learning: 2026-01-05T11:14:20.208Z
Learnt from: CR
Repo: HolmesGPT/holmesgpt PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-05T11:14:20.208Z
Learning: Applies to holmes/plugins/toolsets/**/*.py : Implement simple Pydantic config class with validation for Python toolsets

Applied to files:

  • holmes/plugins/toolsets/elasticsearch/elasticsearch.py
  • holmes/plugins/toolsets/__init__.py
📚 Learning: 2026-01-05T11:14:20.208Z
Learnt from: CR
Repo: HolmesGPT/holmesgpt PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-05T11:14:20.208Z
Learning: Applies to holmes/plugins/toolsets/**/*.py : Each tool in Python toolsets should be a thin wrapper around a single API endpoint

Applied to files:

  • holmes/plugins/toolsets/elasticsearch/elasticsearch.py
  • holmes/plugins/toolsets/__init__.py
📚 Learning: 2026-01-05T11:14:20.208Z
Learnt from: CR
Repo: HolmesGPT/holmesgpt PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-05T11:14:20.208Z
Learning: Applies to holmes/plugins/toolsets/**/*.py : Only define current field names in toolset config schema with extra='allow' to avoid polluting model_dump() output with deprecated fields

Applied to files:

  • holmes/plugins/toolsets/__init__.py
📚 Learning: 2026-01-05T11:14:20.208Z
Learnt from: CR
Repo: HolmesGPT/holmesgpt PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-05T11:14:20.208Z
Learning: Applies to holmes/plugins/toolsets/**/*.py : Maintain backwards compatibility in toolset config using Pydantic's extra='allow' when renaming config fields

Applied to files:

  • holmes/plugins/toolsets/__init__.py
📚 Learning: 2026-01-05T11:14:20.208Z
Learnt from: CR
Repo: HolmesGPT/holmesgpt PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-05T11:14:20.208Z
Learning: Applies to holmes/plugins/toolsets/**/*.py : Include health check in prerequisites_callable() method for Python toolsets

Applied to files:

  • holmes/plugins/toolsets/__init__.py
📚 Learning: 2026-01-05T11:14:20.208Z
Learnt from: CR
Repo: HolmesGPT/holmesgpt PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-05T11:14:20.208Z
Learning: Applies to holmes/plugins/toolsets/**/*.yaml : Toolsets should be YAML files in holmes/plugins/toolsets/{name}.yaml or {name}/ directory structure

Applied to files:

  • holmes/plugins/toolsets/__init__.py
📚 Learning: 2026-01-05T11:14:20.208Z
Learnt from: CR
Repo: HolmesGPT/holmesgpt PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-05T11:14:20.208Z
Learning: Applies to holmes/plugins/toolsets/**/*.{py,yaml} : Never return unbounded data from APIs - always include filter parameters on tools that query collections

Applied to files:

  • holmes/plugins/toolsets/__init__.py
📚 Learning: 2026-01-05T11:14:20.208Z
Learnt from: CR
Repo: HolmesGPT/holmesgpt PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-05T11:14:20.208Z
Learning: Applies to holmes/plugins/toolsets/**/*.{py,yaml} : For 'no data' responses in toolsets, specify what was searched and where

Applied to files:

  • holmes/plugins/toolsets/__init__.py
📚 Learning: 2026-01-05T11:14:20.208Z
Learnt from: CR
Repo: HolmesGPT/holmesgpt PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-05T11:14:20.208Z
Learning: Applies to holmes/plugins/toolsets/**/*.{py,yaml} : All toolsets MUST return detailed error messages from underlying APIs to enable LLM self-correction, including exact query/command executed, time ranges/parameters/filters used, and full API error response (status code and message)

Applied to files:

  • holmes/plugins/toolsets/__init__.py
📚 Learning: 2026-01-05T11:14:20.208Z
Learnt from: CR
Repo: HolmesGPT/holmesgpt PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-05T11:14:20.208Z
Learning: Applies to holmes/plugins/toolsets/**/kubernetes*.py : RBAC permissions are respected for Kubernetes access

Applied to files:

  • holmes/plugins/toolsets/__init__.py
📚 Learning: 2026-01-05T11:14:20.208Z
Learnt from: CR
Repo: HolmesGPT/holmesgpt PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-05T11:14:20.208Z
Learning: Applies to holmes/plugins/toolsets/**/*.py : Bash toolset validates commands for safety

Applied to files:

  • holmes/plugins/toolsets/__init__.py
📚 Learning: 2026-01-05T11:14:20.208Z
Learnt from: CR
Repo: HolmesGPT/holmesgpt PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-05T11:14:20.208Z
Learning: Applies to **/*.py : Always place Python imports at the top of the file, not inside functions or methods

Applied to files:

  • tests/generate_eval_report.py
🧬 Code graph analysis (2)
holmes/plugins/toolsets/elasticsearch/elasticsearch.py (3)
holmes/plugins/toolsets/utils.py (1)
  • toolset_name_for_one_liner (232-236)
holmes/plugins/toolsets/json_filter_mixin.py (2)
  • JsonFilterMixin (51-134)
  • extend_parameters (68-73)
holmes/core/tools.py (1)
  • ToolParameter (141-147)
holmes/plugins/toolsets/__init__.py (2)
holmes/plugins/toolsets/elasticsearch/elasticsearch.py (2)
  • ElasticsearchClusterToolset (810-830)
  • ElasticsearchDataToolset (789-807)
holmes/plugins/toolsets/elasticsearch/opensearch_query_assist.py (1)
  • OpenSearchQueryAssistToolset (55-78)
🪛 Ruff (0.14.10)
holmes/plugins/toolsets/elasticsearch/elasticsearch.py

80-83: Consider moving this statement to an else block

(TRY300)

tests/generate_eval_report.py

1356-1356: Unpacked variable hour is never used

Prefix it with an underscore or any other dummy variable pattern

(RUF059)


1356-1356: Unpacked variable minute is never used

Prefix it with an underscore or any other dummy variable pattern

(RUF059)


1356-1356: Unpacked variable second is never used

Prefix it with an underscore or any other dummy variable pattern

(RUF059)

⏰ 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: run-benchmarks
  • GitHub Check: llm_evals
  • GitHub Check: build (3.12)
  • GitHub Check: build (3.10)
  • GitHub Check: build (3.11)
🔇 Additional comments (12)
holmes/plugins/toolsets/__init__.py (1)

31-37: LGTM! Clean import consolidation.

The imports are properly placed at the top of the file and follow alphabetical ordering. Consolidating these imports (removing duplication as noted in the summary) improves maintainability.

holmes/plugins/toolsets/elasticsearch/elasticsearch.py (2)

502-531: Excellent integration of JsonFilterMixin for the mappings tool.

The ElasticsearchMappings class now properly integrates JsonFilterMixin, enabling users to filter large mapping results using max_depth and jq parameters. The implementation correctly:

  • Inherits from JsonFilterMixin
  • Extends parameters using JsonFilterMixin.extend_parameters
  • Applies filtering via self.filter_result

This follows the coding guidelines for using JsonFilterMixin for client-side filtering when needed.


682-777: Excellent integration of JsonFilterMixin for the list indices tool.

The ElasticsearchListIndices class now properly integrates JsonFilterMixin, providing both server-side filtering (via Elasticsearch's own parameters) and client-side filtering (via max_depth and jq). The implementation is comprehensive and follows best practices.

tests/generate_eval_report.py (4)

12-20: LGTM!

Import path update looks correct.


232-237: LGTM!

The new --benchmark-type argument is well-defined with clear choices and appropriate default.


1333-1343: LGTM!

The benchmark type handling logic is clear. Using getattr is slightly defensive since benchmark_type is defined in parse_args() with a default, but it doesn't cause any issues.


1443-1461: LGTM!

The benchmark info boxes use MkDocs admonition syntax correctly and provide helpful context about each benchmark type.

.github/workflows/eval-benchmarks.yaml (5)

7-30: LGTM!

The workflow inputs are well-structured with clear descriptions. The weekly schedule at 2 AM UTC on Sundays is appropriate for automated benchmarking.


94-106: LGTM!

The evaluation step correctly sets up environment variables and runs the constructed command. Using github.run_id for the experiment ID ensures unique tracking.


107-116: LGTM!

The artifact upload captures all relevant result files and uses if: always() to ensure results are preserved even if tests fail.


127-129: Same-day runs will overwrite each other.

The branch name uses only the date (%Y%m%d), so multiple workflow runs on the same day will force-push to the same branch, potentially losing intermediate results. This is likely acceptable for weekly scheduled runs but could be surprising for manual dispatch.

If preserving results from multiple same-day runs is important, consider adding a run number or timestamp:

BRANCH_NAME="automated/benchmark-$(date +%Y%m%d-%H%M%S)"

70-74: The current quoting strategy is correct and requires no changes.

The escaped quotes \"$CUSTOM_MARKERS\" on line 71 are necessary and work correctly. When this command is output to $GITHUB_OUTPUT and later executed via ${{ steps.build-command.outputs.command }}, the quotes are preserved and allow pytest markers with spaces (e.g., regression or benchmark, easy and kubernetes) to be passed as a single argument.

Testing confirms:

  • With quotes: ./run_benchmarks_local.py --markers "regression or benchmark" → Correctly parsed by argparse
  • Without quotes: ./run_benchmarks_local.py --markers regression or benchmark → Fails with "unrecognized arguments" error

The proposed fixes in the review would introduce problems rather than solve them. The documentation in running-evals.md also shows the expected usage with quotes: ./run_benchmarks_local.py --markers "easy and kubernetes".

Signed-off-by: Tomer Keshet <tomer@robusta.dev>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Fix all issues with AI Agents 🤖
In @.github/workflows/eval-benchmarks.yaml:
- Around line 118-162: When an existing PR is found the script only echoes
"Updating existing PR" and does not refresh its metadata; after detecting
EXISTING_PR populate PR_TITLE and PR_BODY as already computed and call the
GitHub CLI to update the PR (use gh pr edit with --title and --body and the PR
number stored in EXISTING_PR) so the title/body reflect the latest
BENCHMARK_TYPE and command outputs; ensure you reference EXISTING_PR when
calling gh pr edit and preserve the --base/--head behavior used when creating a
new PR.
🧹 Nitpick comments (1)
run_benchmarks_local.py (1)

262-279: Consider simplifying the redirect path construction.

The current path construction works but is unnecessarily complex:

history_relative = f"../history/{history_output.name.replace('.md', '/')}".rstrip("/") + "/"
🔎 Simpler alternative
-            history_relative = (
-                f"../history/{history_output.name.replace('.md', '/')}".rstrip("/")
-                + "/"
-            )
+            history_relative = f"../history/{history_output.stem}/"

Using .stem (filename without extension) is clearer and achieves the same result.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8bb10ab and d0348c3.

📒 Files selected for processing (2)
  • .github/workflows/eval-benchmarks.yaml
  • run_benchmarks_local.py
🧰 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 with configuration in pyproject.toml
Type hints required (mypy configuration in pyproject.toml)
Pre-commit hooks enforce quality checks on Python files

Files:

  • run_benchmarks_local.py
🧠 Learnings (1)
📚 Learning: 2026-01-05T11:14:20.209Z
Learnt from: CR
Repo: HolmesGPT/holmesgpt PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-05T11:14:20.209Z
Learning: Add required environment variables to .github/workflows/eval-regression.yaml 'Run tests' step when adding evals for new cloud service integrations

Applied to files:

  • .github/workflows/eval-benchmarks.yaml
🪛 Ruff (0.14.10)
run_benchmarks_local.py

248-248: subprocess call: check for execution of untrusted input

(S603)


259-259: subprocess call: check for execution of untrusted input

(S603)

⏰ 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: run-benchmarks
  • GitHub Check: build (3.11)
  • GitHub Check: llm_evals
  • GitHub Check: build (3.10)
  • GitHub Check: build (3.12)
🔇 Additional comments (13)
run_benchmarks_local.py (8)

17-21: LGTM! Clean benchmark type definitions.

The constant provides a clear mapping between benchmark types and their pytest markers, improving maintainability.


36-36: LGTM! Proper parameter addition.

The benchmark_type parameter is correctly typed, positioned, and stored.

Also applies to: 45-45


56-57: LGTM! Clear status display.

The conditional output provides useful feedback about which benchmark type is running.


209-249: LGTM! Well-structured report generation.

The method correctly:

  • Selects output files based on benchmark type
  • Validates the report script exists before running
  • Sets up PYTHONPATH for module imports
  • Passes benchmark type to the report generator

The Ruff S603 warnings on subprocess calls are false positives—the script path is validated and arguments come from internal state.


290-313: LGTM! Consistent benchmark type handling.

The summary correctly displays the benchmark type and selects the appropriate result file, mirroring the logic in generate_report.


386-399: LGTM! Well-designed CLI argument.

The --benchmark-type argument:

  • Uses choices for validation
  • Defaults to None, allowing main() to apply conditional defaults
  • Clearly documents mutual exclusivity with --markers

443-461: LGTM! Robust mutual exclusivity validation.

The logic correctly:

  • Validates that --benchmark-type and --markers aren't both provided
  • Defaults to fast-benchmark when neither is specified
  • Derives markers from BENCHMARK_TYPES when using benchmark types

466-475: LGTM! Proper parameter passing.

The BenchmarkRunner instantiation correctly passes both markers and benchmark_type based on the validated logic.

.github/workflows/eval-benchmarks.yaml (5)

7-26: LGTM! Well-structured workflow inputs.

The inputs provide clear options:

  • benchmark_type uses choice validation with appropriate defaults
  • Descriptions clearly document mutual exclusivity
  • Empty string defaults enable proper conditional logic downstream

28-30: LGTM! Appropriate weekly schedule.

Sunday at 2 AM UTC is a sensible time for automated weekly benchmark runs.


57-92: Verify command quoting with custom markers.

The command building logic is well-structured, but line 71 uses escaped quotes:

CMD="$CMD --markers \"$CUSTOM_MARKERS\""

When CUSTOM_MARKERS contains spaces (e.g., "easy or medium"), the escaped quotes should preserve the argument correctly when executed on line 105. However, this quoting pattern can be fragile.

Since workflow inputs are trusted and the script validates them, this is likely acceptable. You may want to test a manual workflow run with custom markers containing spaces to confirm the quoting works as expected.

If issues arise, consider building the command without embedded quotes and letting the script handle the parsing, or use array-based command building.


104-105: LGTM! Simplified execution.

Directly running the built command reduces complexity and improves traceability of what was executed.


107-116: LGTM! Comprehensive artifact upload.

Uploading both fast and full benchmark result files ensures artifacts are captured regardless of which benchmark type ran.

Comment thread .github/workflows/eval-benchmarks.yaml
Signed-off-by: Tomer Keshet <tomer@robusta.dev>
@netlify

netlify Bot commented Jan 6, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for holmes-docs ready!

Name Link
🔨 Latest commit 766775b
🔍 Latest deploy log https://app.netlify.com/projects/holmes-docs/deploys/695cb4a9e881280007af22c2
😎 Deploy Preview https://deploy-preview-1329--holmes-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@Sheeproid
Sheeproid enabled auto-merge (squash) January 6, 2026 07:07
@Sheeproid
Sheeproid disabled auto-merge January 6, 2026 07:11

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d0348c3 and 766775b.

📒 Files selected for processing (1)
  • .github/workflows/eval-benchmarks.yaml
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2026-01-05T11:14:20.209Z
Learnt from: CR
Repo: HolmesGPT/holmesgpt PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-05T11:14:20.209Z
Learning: Add required environment variables to .github/workflows/eval-regression.yaml 'Run tests' step when adding evals for new cloud service integrations

Applied to files:

  • .github/workflows/eval-benchmarks.yaml
🔇 Additional comments (3)
.github/workflows/eval-benchmarks.yaml (3)

154-158: Great fix for updating existing PR metadata!

The previous review comment correctly identified that existing PRs weren't being updated. Lines 156-158 now properly call gh pr edit to refresh the title and body when a PR already exists for the day's benchmark branch.


70-74: Script correctly enforces mutual exclusivity.

The run_benchmarks_local.py script validates mutual exclusivity at lines 443–447 by checking if both --markers and --benchmark-type are provided and exiting with an error if so. The workflow's if/elif structure (lines 70–74) provides an additional layer by prioritizing CUSTOM_MARKERS when both environment variables are set, but the script's explicit validation confirms conflicting inputs are rejected. The comment on line 69 is accurate.


113-116: No action required. The actions/upload-artifact@v4 action handles missing files gracefully by default. When some paths in the list don't exist, it uploads the files that do exist and warns about the missing ones without failing the step (default if-no-files-found: warn behavior). Since only one of fast-benchmark-results.md or full-benchmark-results.md will exist depending on the benchmark type, the workflow will succeed and upload the available files as expected.

Comment thread .github/workflows/eval-benchmarks.yaml
@Sheeproid
Sheeproid merged commit 54feab6 into master Jan 6, 2026
15 of 17 checks passed
@Sheeproid
Sheeproid deleted the weekly-benchmark branch January 6, 2026 07:25
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