Skip to content

Enable parallel test execution with pytest-xdist - #1621

Merged
aantn merged 4 commits into
masterfrom
claude/parallel-pytest-tests-eZNz6
Feb 22, 2026
Merged

aantn merged 4 commits into
masterfrom
claude/parallel-pytest-tests-eZNz6

Conversation

@aantn

@aantn aantn commented Feb 22, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

This change enables parallel test execution in the pytest configuration to improve test suite performance by leveraging multiple CPU cores.

Key Changes

  • Enabled pytest-xdist parallel execution: Added -n auto flag to automatically detect and use all available CPU cores for running tests
  • Configured load-based test distribution: Added --dist loadgroup to distribute tests by load while respecting xdist_group marks, ensuring related tests run together
  • Fixed durations comment: Corrected the comment for --durations=10 from "Show 5 slowest tests" to "Show 10 slowest tests" to match the actual configuration
  • Removed file logging: Disabled log_file configuration and related settings to prevent log file corruption that would occur when multiple parallel workers write to the same file simultaneously
  • Added explanatory note: Included a comment explaining why file logging is disabled and recommending alternatives (log_cli or --capture=no) for debugging

Implementation Details

The removal of file logging is intentional and necessary for parallel test execution. When pytest-xdist spawns multiple worker processes, they would all attempt to write to the same log file, causing corruption. Users can still access test output through console logging (log_cli) or by running tests with --capture=no for debugging purposes.

https://claude.ai/code/session_016bAG1p7sRsKkYvgoBr8fcz

Summary by CodeRabbit

  • Chores

    • Removed shared file-based logging to avoid conflicts with parallel test workers; retained per-worker CLI logging.
    • Split CI paths so binary builds run as a separate job and the primary job focuses on tests; reorganized dependency installation.
  • Tests

    • Enabled parallel test execution with improved distribution to speed CI.
    • Collects and surfaces summarized test results; pipeline gating now fails if tests or binary builds fail.

Add `-n auto` and `--dist loadgroup` to the default pytest addopts so
all test runs (local and CI) automatically use parallel workers.
Remove the shared `log_file` setting which would corrupt under
concurrent writes from multiple xdist workers.

pytest-xdist was already a dev dependency but was only used for LLM
eval tests via explicit `-n 6` flags.  This change makes parallelism
the default for every pytest invocation.

https://claude.ai/code/session_016bAG1p7sRsKkYvgoBr8fcz
Signed-off-by: Claude <noreply@anthropic.com>
@github-actions

github-actions Bot commented Feb 22, 2026 •

Copy link
Copy Markdown
Contributor

✅ Docker images ready for 53505fe0 (built in 5m 37s)

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

Use these tags to pull the images 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:53505fe0
docker tag us-central1-docker.pkg.dev/robusta-development/temporary-builds/holmes:53505fe0 me-west1-docker.pkg.dev/robusta-development/development/holmes-dev:53505fe0
docker push me-west1-docker.pkg.dev/robusta-development/development/holmes-dev:53505fe0
docker pull us-central1-docker.pkg.dev/robusta-development/temporary-builds/holmes-operator:53505fe0
docker tag us-central1-docker.pkg.dev/robusta-development/temporary-builds/holmes-operator:53505fe0 me-west1-docker.pkg.dev/robusta-development/development/holmes-operator-dev:53505fe0
docker push me-west1-docker.pkg.dev/robusta-development/development/holmes-operator-dev:53505fe0

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:53505fe0 \
  --set operator.registry=me-west1-docker.pkg.dev/robusta-development/development \
  --set operator.image=holmes-operator-dev:53505fe0

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:53505fe0 \
  --set holmes.operator.registry=me-west1-docker.pkg.dev/robusta-development/development \
  --set holmes.operator.image=holmes-operator-dev:53505fe0

@github-actions

github-actions Bot commented Feb 22, 2026 •

Copy link
Copy Markdown
Contributor

📂 Previous Runs

📜 Run @ 46d8ec7 (#22280553116)

✅ Results of HolmesGPT evals

Automatically triggered by commit 46d8ec7 on branch claude/parallel-pytest-tests-eZNz6

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.8s 5 11 $0.2425
✅ 101_loki_historical_logs_pod_deleted 44.7s 7 11 $0.2783
✅ 111_pod_names_contain_service 35.4s 5 12 $0.2403
✅ 112_find_pvcs_by_uuid 30.6s 6 7 $0.2419
✅ 12_job_crashing 37.4s 6 12 $0.2603
✅ 176_network_policy_blocking_traffic_no_runbooks 46.3s 6 16 $0.2841
✅ 24_misconfigured_pvc 37.4s 6 15 $0.2594
✅ 43_current_datetime_from_prompt 4.8s 1 — $0.1113
✅ 61_exact_match_counting 16.1s 4 4 $0.1672
Total 31.6s avg 5.1 avg 11.0 avg $2.0854
📜 Run @ c4b3e7c (#22280452201)

✅ Results of HolmesGPT evals

Automatically triggered by commit c4b3e7c on branch claude/parallel-pytest-tests-eZNz6

View workflow logs

⚠️ No eval report was generated.

📜 Run @ 861a8a8 (#22280393131)

✅ Results of HolmesGPT evals

Automatically triggered by commit 861a8a8 on branch claude/parallel-pytest-tests-eZNz6

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.2s 6 10 $0.2361
✅ 101_loki_historical_logs_pod_deleted 51.2s 7 12 $0.2892
✅ 111_pod_names_contain_service 32.2s 5 11 $0.2298
✅ 112_find_pvcs_by_uuid 34.1s 6 6 $0.2380
✅ 12_job_crashing 31.6s 5 11 $0.2375
✅ 176_network_policy_blocking_traffic_no_runbooks 42.3s 7 16 $0.3008
✅ 24_misconfigured_pvc 32.9s 5 13 $0.2414
✅ 43_current_datetime_from_prompt 5.0s 1 — $0.0119
✅ 61_exact_match_counting 16.4s 4 4 $0.1669
Total 30.9s avg 5.1 avg 10.4 avg $1.9516

✅ Results of HolmesGPT evals

Automatically triggered by commit e4089ec on branch claude/parallel-pytest-tests-eZNz6

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 27.9s 4 11 $0.2289
✅ 101_loki_historical_logs_pod_deleted 31.2s 4 7 $0.2161
✅ 111_pod_names_contain_service 32.1s 5 12 $0.2398
✅ 112_find_pvcs_by_uuid 22.3s 4 5 $0.2007
✅ 12_job_crashing 22.9s 4 7 $0.2041
✅ 176_network_policy_blocking_traffic_no_runbooks 49.4s 7 18 $0.3112
✅ 24_misconfigured_pvc 32.1s 5 14 $0.2426
✅ 43_current_datetime_from_prompt 4.7s 1 — $0.1117
✅ 61_exact_match_counting 12.6s 3 2 $0.1506
Total 26.1s avg 4.1 avg 9.5 avg $1.9056
📖 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 claude/parallel-pytest-tests-eZNz6 -f markers=regression -f filter=

Option 1: Comment on this PR with /eval:

/eval
tags: regression

Or with more options (one per line):

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

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

/eval
branch: master
tags: regression
Option Description
model Model(s) to test (default: same as automatic runs)
tags Pytest tags / 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"

Option 3: Add PR labels to include extra evals in automatic regression runs:

Label Effect
evals-tag-<name> Run tests with tag <name> alongside regression
evals-id-<name> Run a specific eval by test ID

Examples: evals-tag-easy, evals-id-09_crashpod

🏷️ Valid tags

benchmark, chain-of-causation, compaction, confluence, context_window, coralogix, counting, database, datadog, datetime, easy, elasticsearch, embeds, fast, frontend, grafana-dashboard, hard, integration, 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 claude/parallel-pytest-tests-eZNz6 -f markers=regression -f filter=

@coderabbitai

coderabbitai Bot commented Feb 22, 2026 •

Copy link
Copy Markdown
Contributor

Walkthrough

Enabled pytest-xdist parallelism and removed shared file logging in pyproject.toml; split GitHub Actions into separate test and build-binary jobs, and updated the gate to depend on both test and binary outcomes.

Changes

Cohort / File(s) Summary
Pytest configuration
pyproject.toml
Added pytest-xdist flags (-n "auto", --dist "loadgroup"), clarified slow test display, removed file-based logging keys (log_file, log_file_level, log_file_format, log_file_date_format) while retaining log_cli and an explanatory note about per-worker logs.
CI workflows
.github/workflows/build-and-test.yaml
Renamed and split jobs: introduced test and build-binary jobs, extracted dependency installation into its own step, added a dedicated binary build path (PyInstaller), updated test result collection/upload, and changed build-and-test-gate to depend on both test and build-binary outcomes.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant PR as "PR / push"
    participant Check as "check-changes"
    participant Test as "test job"
    participant BuildBin as "build-binary job"
    participant Gate as "build-and-test-gate"
    PR->>Check: run check-changes
    Check->>Test: trigger test job (if changes)
    Check->>BuildBin: trigger binary build (if changes)
    Test->>Gate: upload test results & status
    BuildBin->>Gate: upload binary build status
    Gate->>PR: final combined status (pass/fail)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • moshemorad
  • Sheeproid
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Enable parallel test execution with pytest-xdist' directly and accurately summarizes the main objective of the changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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


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.

@netlify

netlify Bot commented Feb 22, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for holmes-docs ready!

Name Link
🔨 Latest commit e4089ec
🔍 Latest deploy log https://app.netlify.com/projects/holmes-docs/deploys/699b2a780167d1000862ff48
😎 Deploy Preview https://deploy-preview-1621--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.

@github-actions

github-actions Bot commented Feb 22, 2026 •

Copy link
Copy Markdown
Contributor

🔬 CLI Performance Benchmark

🟡 Startup Time (no LLM)

Measures holmes version execution time (imports + initialization)

Metric PR Master Change
Cold Start 10.74s 9.92s +8.3%
Warm Mean 4.75s 4.46s +6.7%
Warm Min 4.72s 4.41s
Warm Max 4.82s 4.55s

🟡 Full CLI with LLM

Measures holmes ask execution time (OpenRouter + Haiku 4.5)

Metric PR Master Change
Cold Start 25.00s 38.76s -35.5%
Warm Mean 7.62s 7.11s +7.1%
Warm Min 6.86s 6.38s
Warm Max 8.32s 7.99s

PR: 53505fe0 | Master: 11a3c194 | Iterations: 5

- Split the single `build` job into `test` (3x Python matrix) and
  `build-binary` (single Python 3.11) that run in parallel
- Add `actions/cache` for Poetry installation and pip/Poetry dependency
  caches, keyed on Python version + poetry.lock hash
- PyInstaller binary now builds once instead of 3x (was redundantly
  building on every Python version in the matrix)
- Tests no longer block on PyInstaller completion and vice versa
- Gate job updated to require both `test` and `build-binary` jobs

https://claude.ai/code/session_016bAG1p7sRsKkYvgoBr8fcz
Signed-off-by: Claude <noreply@anthropic.com>

@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

🧹 Nitpick comments (1)
pyproject.toml (1)

174-175: Consider capping worker count with --maxprocesses for CI resource control

-n auto will spawn one worker per available CPU. On CI runners with 32+ cores this can result in significant memory pressure, especially if each worker loads a full application import graph. Adding --maxprocesses=<N> provides an upper bound without disabling parallelism.

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

In `@pyproject.toml` around lines 174 - 175, The pytest invocation uses "-n",
"auto" (with "--dist", "loadgroup"), which can spawn too many workers on large
CI machines; add a "--maxprocesses=<N>" flag alongside these options to cap the
number of xdist workers (choose a sensible default like 8 or make it
configurable via an environment variable) so parallelism is preserved but CI
memory/CPU usage is bounded.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pyproject.toml`:
- Around line 184-185: The comment about debugging is misleading because when
pytest-xdist is enabled via addopts (e.g., "-n auto"), the "-s/--capture=no"
option does not work for parallel workers; update the note around
log_file/log_cli in pyproject.toml to remove the recommendation to use
"--capture=no" and instead state that only log_cli = true (already present) will
produce per-worker output under pytest-xdist, and mention that a shared log_file
is intentionally disabled for the same reason.

---

Nitpick comments:
In `@pyproject.toml`:
- Around line 174-175: The pytest invocation uses "-n", "auto" (with "--dist",
"loadgroup"), which can spawn too many workers on large CI machines; add a
"--maxprocesses=<N>" flag alongside these options to cap the number of xdist
workers (choose a sensible default like 8 or make it configurable via an
environment variable) so parallelism is preserved but CI memory/CPU usage is
bounded.

Comment thread pyproject.toml Outdated
Python 3.12 removed the distutils module (PEP 632). Poetry 1.4.0's
installer depends on it, so pip install setuptools before running the
Poetry installer to provide the distutils compatibility shim.

https://claude.ai/code/session_016bAG1p7sRsKkYvgoBr8fcz
Signed-off-by: Claude <noreply@anthropic.com>
--capture=no does not work with xdist parallel workers. The comment
now correctly points to log_cli which is already configured and safe
under xdist.

https://claude.ai/code/session_016bAG1p7sRsKkYvgoBr8fcz
Signed-off-by: Claude <noreply@anthropic.com>

@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

Caution

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

⚠️ Outside diff range comments (1)
.github/workflows/build-and-test.yaml (1)

126-148: ⚠️ Potential issue | 🟡 Minor

Handle missing test-results.json in both the upload and summary steps.

If pytest crashes during collection (e.g., import error) the JSON file is never written. Two problems follow:

  1. actions/upload-artifact@v4 defaults to if-no-files-found: error, causing the upload step itself to fail and obscuring the real failure in CI output.
  2. The inline Python script raises FileNotFoundError, adding a second spurious failure for the same reason.
🐛 Proposed fix
       - name: Upload test results
         if: always()
         uses: actions/upload-artifact@v4
         with:
           name: test-results-py${{ matrix.python-version }}
           path: test-results.json
+          if-no-files-found: warn

       - name: Show test summary
         if: always()
         run: |
           python3 -c "
           import json, sys, os
+          if not os.path.exists('test-results.json'):
+              print('test-results.json not found — pytest may have crashed during collection')
+              sys.exit(0)
           with open('test-results.json') as f:
               data = json.load(f)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/build-and-test.yaml around lines 126 - 148, Update the
"Upload test results" step (actions/upload-artifact@v4) to avoid failing when
test-results.json is missing by adding if-no-files-found: ignore, and update the
"Show test summary" run step to check for the existence of 'test-results.json'
before opening it (exit gracefully or print "no test results" if missing) so the
inline Python won't raise FileNotFoundError; reference the step names "Upload
test results" and "Show test summary" and the artifact/file name
'test-results.json' when making the changes.
🧹 Nitpick comments (4)
.github/workflows/build-and-test.yaml (4)

78-80: Consider adding fail-fast: false to the matrix strategy.

With the default fail-fast: true, a failure on any single Python version (e.g., 3.10) immediately cancels the 3.11 and 3.12 jobs, hiding whether those versions are also broken.

♻️ Suggested change
     strategy:
+      fail-fast: false
       matrix:
         python-version: ["3.10", "3.11", "3.12"]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/build-and-test.yaml around lines 78 - 80, Add fail-fast:
false to the existing matrix strategy so failing one Python-version job doesn't
cancel the others; update the strategy block that contains matrix and
python-version (the strategy: matrix: python-version entries) to include
fail-fast: false directly under strategy.

92-101: Cache paths don't include the installed Python packages — poetry install runs in full on every cache hit.

With poetry config virtualenvs.create false, packages are installed into the actions/setup-python-managed environment at /opt/hostedtoolcache/Python/<ver>/<arch>/lib/pythonX.Y/site-packages/, which is not among the cached paths. The cache only helps by:

  • Skipping Poetry re-download (~/.local)
  • Avoiding wheel/sdist re-downloads (~/.cache/pip, ~/.cache/pypoetry)

For actual dependency installation caching, switch to virtualenvs.create true (Poetry's default) and cache the virtualenv path:

♻️ Suggested change
-      - name: Cache Poetry installation and dependencies
-        uses: actions/cache@v4
-        with:
-          path: |
-            ~/.local
-            ~/.cache/pip
-            ~/.cache/pypoetry
-          key: poetry-${{ matrix.python-version }}-${{ hashFiles('poetry.lock') }}
-          restore-keys: |
-            poetry-${{ matrix.python-version }}-
+      - name: Cache Poetry installation
+        uses: actions/cache@v4
+        with:
+          path: ~/.local
+          key: poetry-bin-${{ runner.os }}
+
+      - name: Cache Poetry virtualenv
+        uses: actions/cache@v4
+        with:
+          path: ~/.cache/pypoetry/virtualenvs
+          key: poetry-venv-${{ matrix.python-version }}-${{ hashFiles('poetry.lock') }}
+          restore-keys: |
+            poetry-venv-${{ matrix.python-version }}-

And remove poetry config virtualenvs.create false (or set it to true explicitly).

The same applies to the build-binary job's cache block (lines 163–172).

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

In @.github/workflows/build-and-test.yaml around lines 92 - 101, The workflow's
Poetry cache step ("Cache Poetry installation and dependencies") doesn't include
the virtualenv where Poetry installs packages when `poetry config
virtualenvs.create false`, so dependencies are reinstalled on every run;
revert/remove `poetry config virtualenvs.create false` (or set it to `true`) and
change the cache to include the created virtualenv directory (the Poetry
virtualenv path under the runner, e.g. the virtualenv created by Poetry for the
matrix Python version) so that installed packages are cached; apply the same
change to the equivalent cache block in the `build-binary` job.

199-203: Inconsistent --hidden-import= vs --hiddenimport flag forms.

Lines 199–201 use --hidden-import= while lines 202–203 switch to --hiddenimport. Both are accepted by PyInstaller, but the inconsistency is confusing.

♻️ Suggested change
             --hidden-import=tiktoken_ext.openai_public \
             --hidden-import=tiktoken_ext \
             --hidden-import=backports \
-            --hiddenimport litellm.llms.tokenizers \
-            --hiddenimport litellm.litellm_core_utils.tokenizers \
+            --hidden-import=litellm.llms.tokenizers \
+            --hidden-import=litellm.litellm_core_utils.tokenizers \
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/build-and-test.yaml around lines 199 - 203, The workflow
uses two different PyInstaller flag forms (--hidden-import= and --hiddenimport)
which is confusing; standardize them to a single form (prefer --hidden-import=)
by replacing occurrences of the shorter form (e.g., the flags shown as
"--hiddenimport litellm.llms.tokenizers" and "--hiddenimport
litellm.litellm_core_utils.tokenizers") with the canonical
"--hidden-import=litellm.llms.tokenizers" and
"--hidden-import=litellm.litellm_core_utils.tokenizers" so all hidden-import
flags are consistent.

184-184: Pin the pyinstaller version for reproducible binary builds.

pip install --upgrade ... pyinstaller always pulls the latest release. A new PyInstaller major version can change spec-file semantics or --add-data glob support, silently breaking the build. The comment on line 182 already flags that this step must stay in sync with another workflow, making a version drift even harder to debug.

♻️ Suggested change
-          python -m pip install --upgrade pip setuptools pyinstaller
+          python -m pip install --upgrade pip setuptools pyinstaller==6.13.0
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/build-and-test.yaml at line 184, The workflow step that
runs the install command "python -m pip install --upgrade pip setuptools
pyinstaller" should pin the pyinstaller package to a specific tested version to
ensure reproducible binary builds; update that command (or introduce a variable
used by it) so pyinstaller is installed as a fixed version (e.g.,
pyinstaller==<chosen-version> or from a pinned constraint file) rather than
pulling the latest release, and ensure the chosen version is documented or
stored so it stays in sync with the related workflow referenced in the
surrounding comments.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/build-and-test.yaml:
- Around line 103-108: The workflow installs Poetry pinned to 1.4.0 which lacks
official Python 3.12 support; update the installer invocation in the "Install
Poetry" step (the curl | python3 - --version ... line) to a Poetry release that
supports Python 3.12 (e.g., change --version 1.4.0 to --version 1.7.0 or a newer
stable like 2.3.2) and make the identical change in the build-binary job where
the same pin is used so both occurrences are consistent; keep the subsequent
poetry config virtualenvs.create false line unchanged.

---

Outside diff comments:
In @.github/workflows/build-and-test.yaml:
- Around line 126-148: Update the "Upload test results" step
(actions/upload-artifact@v4) to avoid failing when test-results.json is missing
by adding if-no-files-found: ignore, and update the "Show test summary" run step
to check for the existence of 'test-results.json' before opening it (exit
gracefully or print "no test results" if missing) so the inline Python won't
raise FileNotFoundError; reference the step names "Upload test results" and
"Show test summary" and the artifact/file name 'test-results.json' when making
the changes.

---

Nitpick comments:
In @.github/workflows/build-and-test.yaml:
- Around line 78-80: Add fail-fast: false to the existing matrix strategy so
failing one Python-version job doesn't cancel the others; update the strategy
block that contains matrix and python-version (the strategy: matrix:
python-version entries) to include fail-fast: false directly under strategy.
- Around line 92-101: The workflow's Poetry cache step ("Cache Poetry
installation and dependencies") doesn't include the virtualenv where Poetry
installs packages when `poetry config virtualenvs.create false`, so dependencies
are reinstalled on every run; revert/remove `poetry config virtualenvs.create
false` (or set it to `true`) and change the cache to include the created
virtualenv directory (the Poetry virtualenv path under the runner, e.g. the
virtualenv created by Poetry for the matrix Python version) so that installed
packages are cached; apply the same change to the equivalent cache block in the
`build-binary` job.
- Around line 199-203: The workflow uses two different PyInstaller flag forms
(--hidden-import= and --hiddenimport) which is confusing; standardize them to a
single form (prefer --hidden-import=) by replacing occurrences of the shorter
form (e.g., the flags shown as "--hiddenimport litellm.llms.tokenizers" and
"--hiddenimport litellm.litellm_core_utils.tokenizers") with the canonical
"--hidden-import=litellm.llms.tokenizers" and
"--hidden-import=litellm.litellm_core_utils.tokenizers" so all hidden-import
flags are consistent.
- Line 184: The workflow step that runs the install command "python -m pip
install --upgrade pip setuptools pyinstaller" should pin the pyinstaller package
to a specific tested version to ensure reproducible binary builds; update that
command (or introduce a variable used by it) so pyinstaller is installed as a
fixed version (e.g., pyinstaller==<chosen-version> or from a pinned constraint
file) rather than pulling the latest release, and ensure the chosen version is
documented or stored so it stays in sync with the related workflow referenced in
the surrounding comments.

Comment thread .github/workflows/build-and-test.yaml

@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.

🧹 Nitpick comments (2)
.github/workflows/build-and-test.yaml (2)

92-101: Cache key collision between test (Python 3.11 matrix leg) and build-binary jobs.

Both jobs use the same key poetry-3.11-${{ hashFiles('poetry.lock') }} but install different dependency sets (--with dev vs. without). When they run concurrently, whichever saves the cache last will persist a potentially incomplete entry for the other job. Correctness is preserved because poetry install is idempotent, but cache hits may restore the wrong set and require follow-up installs.

Consider namespacing the keys to differentiate the two purposes:

♻️ Proposed fix
# test job (lines 92-101)
-          key: poetry-${{ matrix.python-version }}-${{ hashFiles('poetry.lock') }}
-          restore-keys: |
-            poetry-${{ matrix.python-version }}-
+          key: poetry-test-${{ matrix.python-version }}-${{ hashFiles('poetry.lock') }}
+          restore-keys: |
+            poetry-test-${{ matrix.python-version }}-

# build-binary job (lines 165-174)
-          key: poetry-3.11-${{ hashFiles('poetry.lock') }}
-          restore-keys: |
-            poetry-3.11-
+          key: poetry-binary-3.11-${{ hashFiles('poetry.lock') }}
+          restore-keys: |
+            poetry-binary-3.11-
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/build-and-test.yaml around lines 92 - 101, The cache key
for the "Cache Poetry installation and dependencies" step collides across
different jobs because it only uses matrix.python-version and poetry.lock;
update the key to namespace by job purpose so test vs build-binary produce
different caches (for example add ${{ github.job }} or a custom job-specific
string to the key), and update restore-keys similarly so each job restores only
its own cache; change the key expression referenced in the step (the key used
now: poetry-${{ matrix.python-version }}-${{ hashFiles('poetry.lock') }}) to
include the job identifier so caches do not clash.

202-207: Inconsistent PyInstaller flag style — combine spelling and syntax differences.

Lines 202–204 use --hidden-import=<value> (with hyphen, equals-sign format), while lines 205–206 use --hiddenimport <value> (no hyphen, space-separated). Both spellings are equivalent PyInstaller aliases, but the formatting differs in both the flag name and argument separator. Unifying to the --hidden-import=<value> style improves consistency.

♻️ Proposed fix
-           --hiddenimport litellm.llms.tokenizers \
-           --hiddenimport litellm.litellm_core_utils.tokenizers \
+           --hidden-import=litellm.llms.tokenizers \
+           --hidden-import=litellm.litellm_core_utils.tokenizers \
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/build-and-test.yaml around lines 202 - 207, The
PyInstaller flags are inconsistently formatted: change the two occurrences of
the alias using space-separated form ("--hiddenimport litellm.llms.tokenizers"
and "--hiddenimport litellm.litellm_core_utils.tokenizers") to the consistent
"--hidden-import=<value>" style used elsewhere (i.e.,
"--hidden-import=litellm.llms.tokenizers" and
"--hidden-import=litellm.litellm_core_utils.tokenizers") so all hidden-import
flags use the same hyphenated name and equals-sign argument form.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In @.github/workflows/build-and-test.yaml:
- Around line 103-109: Update the Poetry installer version pin from 1.4.0 to a
release that officially supports Python 3.12 (use at least 1.7.0; e.g., 1.7.1)
by changing the installer invocation string "curl -sSL
https://install.python-poetry.org | python3 - --version 1.4.0" to use the newer
version, and apply the same change to the second occurrence of that installer
invocation (the one in the build-binary job) so both places install Poetry
>=1.7.0.

---

Nitpick comments:
In @.github/workflows/build-and-test.yaml:
- Around line 92-101: The cache key for the "Cache Poetry installation and
dependencies" step collides across different jobs because it only uses
matrix.python-version and poetry.lock; update the key to namespace by job
purpose so test vs build-binary produce different caches (for example add ${{
github.job }} or a custom job-specific string to the key), and update
restore-keys similarly so each job restores only its own cache; change the key
expression referenced in the step (the key used now: poetry-${{
matrix.python-version }}-${{ hashFiles('poetry.lock') }}) to include the job
identifier so caches do not clash.
- Around line 202-207: The PyInstaller flags are inconsistently formatted:
change the two occurrences of the alias using space-separated form
("--hiddenimport litellm.llms.tokenizers" and "--hiddenimport
litellm.litellm_core_utils.tokenizers") to the consistent
"--hidden-import=<value>" style used elsewhere (i.e.,
"--hidden-import=litellm.llms.tokenizers" and
"--hidden-import=litellm.litellm_core_utils.tokenizers") so all hidden-import
flags use the same hyphenated name and equals-sign argument form.

@aantn
aantn enabled auto-merge (squash) February 22, 2026 16:22
@aantn
aantn merged commit 5f8d5b0 into master Feb 22, 2026
21 of 22 checks passed
@aantn
aantn deleted the claude/parallel-pytest-tests-eZNz6 branch February 22, 2026 16:48
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.

3 participants