Skip to content

Add lightweight API test workflow with mock VLLM - #194

Merged
paultranvan merged 4 commits into
devfrom
feature/lightweight-api-tests
Jan 14, 2026
Merged

Add lightweight API test workflow with mock VLLM#194
paultranvan merged 4 commits into
devfrom
feature/lightweight-api-tests

Conversation

@paultranvan

@paultranvan paultranvan commented Jan 4, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds a new GitHub Actions workflow that tests the OpenRAG API without requiring VLLM or heavy ML dependencies. This provides much faster CI feedback compared to the existing smoke tests.

Performance comparison:

  • New API tests: ~2-3 minutes
  • Existing smoke tests: 10-30+ minutes

Key components

  • Mock VLLM server (mock_vllm.py): Lightweight FastAPI server that returns fake embeddings, allowing full API testing without actual ML model loading
  • Lightweight docker-compose: Includes PostgreSQL, Milvus, and mock VLLM (no real VLLM build)
  • Comprehensive pytest test suite (38 tests) covering:
    • Health checks and OpenAPI docs
    • Partition CRUD operations
    • File upload and indexing
    • Semantic search
    • User management
    • Queue and task management
    • Tools API
    • OpenAI-compatible endpoints

Files added

.github/workflows/
├── api_tests.yml                 # Workflow (runs on PR + push to main/dev)
└── api_tests/
    ├── docker-compose.yaml       # Test infrastructure
    ├── Dockerfile.mock-vllm      # Mock VLLM container
    ├── mock_vllm.py              # Mock embedding server
    └── fixtures/sample.txt       # Test file

tests/api_tests/
├── conftest.py                   # Pytest fixtures
├── test_health.py
├── test_partition.py
├── test_indexer.py
├── test_search.py
├── test_extract.py
├── test_users.py
├── test_queue.py
├── test_tools.py
├── test_openai_compat.py
└── test_actors.py

Test plan

  • All 38 tests pass locally (~25 seconds)
  • Verify GitHub Actions workflow runs successfully
  • Confirm services start correctly in CI environment

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Tests

    • Added a comprehensive API test suite covering health, search, indexing, partitions, queue/tasks, actors, OpenAI-compatible endpoints, tools, users, and extracts plus fixtures for sample files and partition lifecycle.
  • Chores

    • Added a CI workflow to spin up containerized services and run the API tests on pushes and pull requests.
  • Bug Fixes

    • Improved API error propagation and ID validation to surface correct HTTP errors and avoid invalid queries.

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

@coderabbitai

coderabbitai Bot commented Jan 4, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds a GitHub Actions workflow and CI test stack that brings up a Docker Compose environment (mock VLLM, Postgres, Etcd, MinIO, Milvus, OpenRAG), waits for readiness, runs pytest-based API tests in tests/api_tests/, collects service logs on failure, and tears down containers.

Changes

Cohort / File(s) Summary
CI Workflow
\.github/workflows/api_tests.yml``
New GitHub Actions workflow triggered on push/PR to main/dev; checks out repo, sets up Docker Compose & Python 3.12, starts services, performs layered health checks, runs pytest against tests/api_tests/, prints service logs on failure, and always tears down the environment.
Mock VLLM Service
\.github/workflows/api_tests/Dockerfile.mock-vllm`, `.github/workflows/api_tests/mock_vllm.py``
Adds a FastAPI-based mock embedding service (384-d deterministic embeddings) and Dockerfile to build/run it for CI (/health, /v1/models, /v1/embeddings).
Docker Compose & Fixtures
\.github/workflows/api_tests/docker-compose.yaml`, `.github/workflows/api_tests/fixtures/sample.txt``
New docker-compose wiring services (mock-vllm, rdb, etcd, minio, milvus, openrag) with healthchecks, env vars, ports (OpenRAG on 8080), volumes, and a sample fixture document for indexing tests.
Test Fixtures
\tests/api_tests/init.py`, `tests/api_tests/conftest.py``
New pytest fixtures: session-scoped api_client, autouse readiness poller, temp sample text/markdown files, unique partition name, and created_partition lifecycle fixture that creates and cleans up partitions.
API Tests
\tests/api_tests/*`<br>`tests/api_tests/test_health.py`, `tests/api_tests/test_partition.py`, `tests/api_tests/test_indexer.py`, `tests/api_tests/test_search.py`, `tests/api_tests/test_extract.py`, `tests/api_tests/test_openai_compat.py`, `tests/api_tests/test_queue.py`, `tests/api_tests/test_tools.py`, `tests/api_tests/test_actors.py`, `tests/api_tests/test_users.py``
~10 new test modules covering health, partitions CRUD, supported types, file upload/indexing and task status, semantic search, extract endpoints, OpenAI-compatible endpoints, queue/tasks, tools schema, actors, and user endpoints. Tests tolerate multiple valid status codes and optional endpoint availability.
Vectordb Validation
\openrag/components/indexer/vectordb/vectordb.py``
Adds input validation in get_chunk_by_id: attempts to convert chunk_id to int, returns None if invalid, and uses integer _id in Milvus queries.
Extract Error Handling
\openrag/routers/extract.py``
Ensures HTTPException from get_extract is re-raised unchanged by adding a dedicated except HTTPException branch so original HTTP errors propagate.

Sequence Diagram(s)

sequenceDiagram
  actor GitHubActions as "GitHub Actions"
  participant DockerCompose as "Docker Compose"
  participant MockVLLM as "mock-vllm"
  participant Milvus as "Milvus"
  participant OpenRAG as "OpenRAG API"
  participant TestRunner as "Pytest (httpx)"

  GitHubActions->>DockerCompose: checkout + docker compose up -d
  DockerCompose->>MockVLLM: start service
  DockerCompose->>Milvus: start service
  DockerCompose->>OpenRAG: build & start (depends on others)
  GitHubActions->>MockVLLM: poll /health until ready
  GitHubActions->>OpenRAG: poll /health_check until ready
  GitHubActions->>TestRunner: run pytest tests/api_tests/
  TestRunner->>OpenRAG: send API requests (health, index, search, etc.)
  OpenRAG->>MockVLLM: request embeddings
  OpenRAG->>Milvus: store/query vectors
  TestRunner->>GitHubActions: reports results
  GitHubActions->>DockerCompose: docker compose down -v (always)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels

feat

Suggested reviewers

  • dodekapod

Poem

🐰 Hop, hop — CI springs to life tonight,

Containers hum and tests align in light,
Mock embedders buzz, vectors find their way,
Assertions nibble carrots, green checks play,
A rabbit cheers: "All systems passing — hooray!"

🚥 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 clearly and specifically describes the main change: adding a new GitHub Actions API test workflow that uses a lightweight mock VLLM server instead of a real VLLM dependency.
Docstring Coverage ✅ Passed Docstring coverage is 94.00% which is sufficient. The required threshold is 80.00%.

✏️ 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.

Adds a new GitHub Actions workflow that tests the OpenRAG API without
requiring VLLM or heavy ML dependencies. This runs much faster than
the existing smoke tests (2-3 min vs 10-30+ min).

Key components:
- Mock VLLM server that returns fake embeddings for testing
- Lightweight docker-compose with PostgreSQL, Milvus, and mock VLLM
- Comprehensive pytest test suite (38 tests) covering:
  - Health checks and OpenAPI docs
  - Partition CRUD operations
  - File upload and indexing
  - Semantic search
  - User management
  - Queue and task management
  - Tools API
  - OpenAI-compatible endpoints

The workflow runs on every PR and push to main/dev branches.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@paultranvan
paultranvan force-pushed the feature/lightweight-api-tests branch from 4c00952 to dceb272 Compare January 9, 2026 17:09
@paultranvan
paultranvan changed the base branch from main to dev January 9, 2026 17:09
@paultranvan
paultranvan marked this pull request as ready for review January 9, 2026 17:10

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 8

🤖 Fix all issues with AI agents
In @.github/workflows/api_tests.yml:
- Around line 41-43: The pipeline step that waits for mock-vllm uses the command
"timeout 60 bash -c 'until curl -sf http://localhost:8000/health 2>/dev/null; do
sleep 2; done' || true" which masks failures; remove the "|| true" so the job
fails when the timeout is reached (or replace it with an explicit error/log and
exit 1) to ensure the workflow does not proceed if mock-vllm failed to start.

In @tests/api_tests/test_extract.py:
- Around line 8-12: The test method test_get_nonexistent_extract currently
allows a 500 status which masks server errors; update the assertion in
test_get_nonexistent_extract (where
api_client.get("/extract/nonexistent-id-12345") is called) to assert
response.status_code == 404 only so missing resources must return Not Found; if
the API intentionally returns 500 for missing extracts, change the API instead,
but do not keep accepting 500 in this test.

In @tests/api_tests/test_indexer.py:
- Around line 127-130: The test test_get_nonexistent_task currently accepts 500
which masks server errors; change the assertion to require a 404 for the
api_client.get("/indexer/task/nonexistent-task-12345") call by replacing the
permissive assertion (response.status_code in [404, 500]) with a strict check
for 404 (e.g., assert response.status_code == 404) so the test fails on internal
server errors instead of treating them as expected.

In @tests/api_tests/test_openai_compat.py:
- Around line 31-41: The test function test_chat_completions_invalid_model
currently allows a 200 success for a nonexistent model; change the assertion so
the API must return an error status (not 200). Update the assertion on the
response from api_client.post("/v1/chat/completions", ...) to assert
response.status_code is in an error set (e.g., [400, 404, 500]) and optionally
assert the response body contains an error field/message to ensure the invalid
model is reported.
- Around line 22-29: The test_chat_completions_endpoint currently allows 500
which can hide validation bugs; update the assertion in
test_chat_completions_endpoint so the accepted response.status_code values are
only 400, 404, or 422 (remove 500) and/or add an explicit failure if status_code
== 500 to ensure server errors are surfaced; modify the assertion in that
function to assert response.status_code in [400, 404, 422] (or add a separate
assert response.status_code != 500) to tighten the expected outcomes.

In @tests/api_tests/test_partition.py:
- Around line 28-35: Update test_create_duplicate_partition_fails to explicitly
assert the first api_client.post(f"/partition/{test_partition_name}") returned a
success status (e.g., 200 or 201) before making the second POST so a failing
first call can't mask failures; remove the manual cleanup delete and rely on the
existing test fixture for teardown (or convert the test to use the fixture that
guarantees partition cleanup), keeping the duplicate-create assertion that
response.status_code is in [400, 409].

In @tests/api_tests/test_search.py:
- Around line 57-65: The test_search_multiple_partitions test currently ignores
the indexed_partition fixture; update the API call in
test_search_multiple_partitions to pass the partition filter using the
indexed_partition value (e.g., add the appropriate partition parameter to the
params dict sent to api_client.get for "/search") so the search is constrained
to the partition known to be indexed; ensure you use the correct query key
expected by the endpoint (e.g., "partition" or "partitions") when adding
indexed_partition to the params.

In @tests/api_tests/test_users.py:
- Around line 32-35: The test function test_get_nonexistent_user currently
accepts a 500 as valid, which masks server errors; update the assertion in
test_get_nonexistent_user (in tests/api_tests/test_users.py) to require a 404
Not Found (e.g., assert response.status_code == 404) so the test fails on 500
responses and surfaces server errors for fixing.
🧹 Nitpick comments (15)
tests/api_tests/test_actors.py (2)

2-2: Unused import.

pytest is imported but not used in this module.

Suggested fix
 """Ray actors API tests."""
-import pytest

8-18: Test is very permissive - consider tightening assertions.

Accepting 307 (redirect) and 403 (forbidden) alongside 200 means this test will pass even when the endpoint is misconfigured or authorization is broken. If 307 or 403 are expected in CI, consider using follow_redirects=True on the client or documenting why these are acceptable. Otherwise, this test provides limited validation.

tests/api_tests/test_tools.py (2)

2-2: Unused import.

pytest is imported but not used in this module.

Suggested fix
 """Tools API tests."""
-import pytest

18-25: Missing status code assertion before parsing response.

If the endpoint returns a non-200 response, response.json() may fail or return unexpected data, leading to confusing test failures.

Suggested fix
     def test_tool_has_required_fields(self, api_client):
         """Test that tools have required fields."""
         response = api_client.get("/v1/tools")
+        assert response.status_code == 200
         data = response.json()
 
         for tool in data:
             assert "name" in tool
             assert "description" in tool
tests/api_tests/test_extract.py (1)

5-18: Consider adding positive test cases.

Currently only negative scenarios are tested. Consider adding a test that verifies successful extract retrieval with a valid ID (possibly after creating/indexing a document first).

tests/api_tests/test_users.py (1)

23-30: Consider asserting successful info_response first.

Line 27 silently defaults to user_id=1 if the ID is missing. While this provides a fallback, it may mask issues with the /users/info endpoint. Consider asserting info_response.status_code == 200 before extracting the ID.

💡 Suggested improvement
     def test_get_user_by_id(self, api_client):
         """Test getting user by ID."""
         # First get current user to know a valid ID
         info_response = api_client.get("/users/info")
+        assert info_response.status_code == 200
         user_id = info_response.json().get("id", 1)

         response = api_client.get(f"/users/{user_id}")
         assert response.status_code == 200
tests/api_tests/test_indexer.py (2)

68-92: Test accepts too many outcomes, reducing its value.

The fixed time.sleep(2) is fragile and may be insufficient on slower systems. More importantly, accepting both success (200/201/202) and error (400/409) status codes means the test doesn't enforce any specific behavior for duplicate uploads. Consider either:

  1. Deciding on the expected duplicate-upload behavior (replace or reject) and testing only that path, or
  2. Splitting into two separate tests: one for replacement and one for rejection.

Also consider polling the task status instead of using a fixed sleep.


112-119: URL parsing is fragile.

Line 115 uses brittle string manipulation (task_url.split("/")[3:]) that assumes a specific URL structure. Consider using urllib.parse for more robust URL parsing.

💡 Suggested improvement
+from urllib.parse import urlparse
+
 # ...
 
         # Extract task ID from response
         if "task_status_url" in data:
             task_url = data["task_status_url"]
-            # Get relative path
-            task_path = "/" + "/".join(task_url.split("/")[3:])
+            # Get path from URL
+            parsed = urlparse(task_url)
+            task_path = parsed.path
         elif "task_id" in data:
             task_path = f"/indexer/task/{data['task_id']}"
         else:
             pytest.skip("No task ID in response")
tests/api_tests/test_openai_compat.py (1)

43-50: Test is too permissive with acceptable status codes.

Accepting both success (200) and multiple error codes (400, 404, 422, 500) makes this test non-deterministic and reduces its value. Consider testing specific scenarios separately (e.g., endpoint disabled vs. valid request) or removing 500 from accepted codes.

tests/api_tests/test_queue.py (1)

15-23: Consider validating response structure and filter correctness.

The filtered task tests only verify status codes. Consider adding assertions to validate the response structure (e.g., presence of "tasks" key) and, if feasible, that the returned tasks match the requested filter status.

♻️ Proposed enhancement
 def test_list_active_tasks(self, api_client):
     """Test listing active tasks."""
     response = api_client.get("/queue/tasks", params={"task_status": "active"})
     assert response.status_code == 200
+    data = response.json()
+    assert "tasks" in data

 def test_list_completed_tasks(self, api_client):
     """Test listing completed tasks."""
     response = api_client.get("/queue/tasks", params={"task_status": "completed"})
     assert response.status_code == 200
+    data = response.json()
+    assert "tasks" in data
tests/api_tests/test_partition.py (2)

15-26: Prefer the created_partition fixture for automatic cleanup.

Manual cleanup on Line 26 could be skipped if the test fails before reaching that line, potentially polluting subsequent tests. Consider using the created_partition fixture which ensures cleanup even if assertions fail.

♻️ Proposed refactor using fixture
-def test_create_partition(self, api_client, test_partition_name):
+def test_create_partition(self, api_client, created_partition):
     """Test creating a new partition."""
-    response = api_client.post(f"/partition/{test_partition_name}")
-    assert response.status_code in [200, 201]
-
     # Verify it exists
     response = api_client.get("/partition/")
     partitions = [p["partition"] for p in response.json()["partitions"]]
-    assert test_partition_name in partitions
-
-    # Cleanup
-    api_client.delete(f"/partition/{test_partition_name}")
+    assert created_partition in partitions

51-54: Status code 500 seems overly permissive for a not-found scenario.

Accepting 500 (internal server error) for a non-existent partition lookup might mask actual server bugs. Consider whether 404 is the expected response and if 500 should be investigated separately.

💡 Suggested adjustment
 def test_delete_nonexistent_partition(self, api_client):
     """Test deleting non-existent partition returns error."""
     response = api_client.delete("/partition/nonexistent-partition-xyz123")
-    assert response.status_code in [404, 500]
+    assert response.status_code == 404

If the API legitimately returns 500 for this case, consider documenting why or filing an issue to improve the API's error handling.

tests/api_tests/test_search.py (3)

25-33: URL parsing logic is brittle.

The task URL parsing on Lines 27-28 assumes a specific URL structure (task_path = "/" + "/".join(task_url.split("/")[3:])). This could break if the API changes URL formats or if the URL contains query parameters.

♻️ More robust URL parsing
 # Wait for indexing to complete
 if "task_status_url" in data:
     task_url = data["task_status_url"]
-    task_path = "/" + "/".join(task_url.split("/")[3:])
+    # Parse URL to extract path, handling both absolute and relative URLs
+    from urllib.parse import urlparse
+    parsed = urlparse(task_url)
+    task_path = parsed.path
 elif "task_id" in data:
     task_path = f"/indexer/task/{data['task_id']}"
 else:

35-43: Consider the implications of using pytest.skip in a fixture.

When indexing fails (Line 42), pytest.skip is called from within the fixture. This will skip all tests that depend on indexed_partition, which may be the intended behavior. However, this could mask underlying indexing issues if they occur frequently.

Consider whether failing loudly (raising an exception) would be more appropriate for CI environments to catch indexing problems early, or if skipping is acceptable for flaky test environments.


78-94: Overly permissive status codes may hide bugs.

Both test_search_empty_query (Line 85) and test_search_nonexistent_partition (Line 94) accept status code 500. Internal server errors might indicate actual bugs rather than expected edge-case behavior.

💡 More specific status code expectations
 def test_search_empty_query(self, api_client, indexed_partition):
     """Test search with empty query."""
     response = api_client.get(
         f"/search/partition/{indexed_partition}",
         params={"text": "", "top_k": 5}
     )
-    # Should return error or empty results
-    assert response.status_code in [200, 400, 422]
+    # Empty query should return validation error
+    assert response.status_code in [400, 422]

 def test_search_nonexistent_partition(self, api_client):
     """Test searching non-existent partition."""
     response = api_client.get(
         "/search/partition/nonexistent-partition-xyz",
         params={"text": "test", "top_k": 5}
     )
-    # May return empty results or error
-    assert response.status_code in [200, 404, 500]
+    # Non-existent partition should return not found
+    assert response.status_code == 404

If the API legitimately returns 500 for these cases, document why or consider filing API improvement issues.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ce7a280 and dceb272.

📒 Files selected for processing (17)
  • .github/workflows/api_tests.yml
  • .github/workflows/api_tests/Dockerfile.mock-vllm
  • .github/workflows/api_tests/docker-compose.yaml
  • .github/workflows/api_tests/fixtures/sample.txt
  • .github/workflows/api_tests/mock_vllm.py
  • tests/api_tests/__init__.py
  • tests/api_tests/conftest.py
  • tests/api_tests/test_actors.py
  • tests/api_tests/test_extract.py
  • tests/api_tests/test_health.py
  • tests/api_tests/test_indexer.py
  • tests/api_tests/test_openai_compat.py
  • tests/api_tests/test_partition.py
  • tests/api_tests/test_queue.py
  • tests/api_tests/test_search.py
  • tests/api_tests/test_tools.py
  • tests/api_tests/test_users.py
🧰 Additional context used
🧬 Code graph analysis (10)
tests/api_tests/test_health.py (1)
tests/api_tests/conftest.py (1)
  • api_client (16-19)
tests/api_tests/test_partition.py (1)
tests/api_tests/conftest.py (3)
  • api_client (16-19)
  • test_partition_name (81-83)
  • created_partition (87-96)
tests/api_tests/test_actors.py (1)
tests/api_tests/conftest.py (1)
  • api_client (16-19)
tests/api_tests/test_extract.py (1)
tests/api_tests/conftest.py (1)
  • api_client (16-19)
tests/api_tests/test_tools.py (1)
tests/api_tests/conftest.py (1)
  • api_client (16-19)
tests/api_tests/test_queue.py (1)
tests/api_tests/conftest.py (1)
  • api_client (16-19)
tests/api_tests/test_indexer.py (1)
tests/api_tests/conftest.py (4)
  • api_client (16-19)
  • created_partition (87-96)
  • sample_text_file (39-53)
  • sample_markdown_file (57-77)
tests/api_tests/test_users.py (1)
tests/api_tests/conftest.py (1)
  • api_client (16-19)
tests/api_tests/test_openai_compat.py (1)
tests/api_tests/conftest.py (1)
  • api_client (16-19)
tests/api_tests/test_search.py (1)
tests/api_tests/conftest.py (3)
  • api_client (16-19)
  • created_partition (87-96)
  • sample_text_file (39-53)
🪛 actionlint (1.7.10)
.github/workflows/api_tests/docker-compose.yaml

4-4: "jobs" section is missing in workflow

(syntax-check)


4-4: "on" section is missing in workflow

(syntax-check)


4-4: unexpected key "services" for "workflow" section. expected one of "concurrency", "defaults", "env", "jobs", "name", "on", "permissions", "run-name"

(syntax-check)


126-126: unexpected key "volumes" for "workflow" section. expected one of "concurrency", "defaults", "env", "jobs", "name", "on", "permissions", "run-name"

(syntax-check)

🪛 Ruff (0.14.10)
tests/api_tests/conftest.py

95-96: try-except-pass detected, consider logging the exception

(S110)


95-95: Do not catch blind exception: Exception

(BLE001)

tests/api_tests/test_search.py

57-57: Unused method argument: indexed_partition

(ARG002)

.github/workflows/api_tests/mock_vllm.py

38-38: Probable use of insecure hash functions in hashlib: md5

(S324)


80-80: Possible binding to all interfaces

(S104)

⏰ 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). (2)
  • GitHub Check: api-tests
  • GitHub Check: index-backup-restore
🔇 Additional comments (22)
tests/api_tests/__init__.py (1)

1-1: Inconsistency: PR summary mentions extensive test infrastructure but only __init__.py provided for review.

The PR objectives describe adding 38 test modules, mock_vllm.py, docker-compose configuration, Dockerfile.mock-vllm, GitHub Actions workflow, and test fixtures, but only this package initialization file has been provided for review.

Please clarify:

  • Are the other files intentionally excluded from this review?
  • If included, please provide them so a comprehensive review can be performed on the full test infrastructure.

The __init__.py file itself is correct as a package marker.

.github/workflows/api_tests/Dockerfile.mock-vllm (1)

1-6: LGTM - Clean minimal Dockerfile for CI testing.

The Dockerfile is appropriately lightweight for a mock service. Consider pinning package versions for reproducibility (e.g., fastapi==0.115.0 uvicorn==0.32.0 pydantic==2.10.0), though this is optional for a CI-only mock service where reproducibility is less critical.

.github/workflows/api_tests/docker-compose.yaml (1)

1-127: Well-structured Docker Compose configuration for API testing.

The service dependencies, health checks, and configuration are well thought out. The static analysis hints from actionlint are false positives - actionlint incorrectly parsed this docker-compose.yaml as a GitHub Actions workflow file due to its location under .github/workflows/.

Note: The hardcoded credentials (postgres password, minio keys) are acceptable for an isolated CI test environment.

.github/workflows/api_tests/mock_vllm.py (2)

36-43: MD5 usage is acceptable here for deterministic test data.

The static analysis flag (S324) about MD5 is a false positive in this context. MD5 is not being used for cryptographic security but rather to generate deterministic fake embeddings from text, which is appropriate for test mocking.


78-80: Binding to 0.0.0.0 is required for Docker container usage.

The static analysis flag (S104) about binding to all interfaces is expected here since this server runs inside a Docker container and needs to accept connections from other containers in the compose network.

tests/api_tests/test_health.py (1)

1-23: LGTM - Clean health check and OpenAPI validation tests.

The tests are focused and appropriately verify API availability and documentation accessibility. Good foundation for the test suite.

.github/workflows/api_tests/fixtures/sample.txt (1)

1-42: LGTM - Good test fixture content.

The fixture provides structured, meaningful content for testing file upload and indexing functionality. The size and structure are appropriate for fast CI tests.

tests/api_tests/test_users.py (2)

8-13: LGTM!

Test correctly validates the current user info endpoint returns 200 with an ID field.


15-21: LGTM!

Test appropriately validates the list users endpoint and acknowledges the unauthenticated context in the comment.

.github/workflows/api_tests.yml (4)

1-11: LGTM!

Workflow triggers and job configuration are appropriate for API testing. The 15-minute timeout provides adequate buffer while preventing hung workflows.


13-31: LGTM!

Setup steps are well-configured with appropriate version pinning and minimal test dependencies.


65-69: LGTM!

Test execution step is properly configured with appropriate timeout and output settings.


71-86: LGTM!

Failure logging and cleanup steps are well-designed. The if: always() ensures cleanup runs regardless of test outcome, and the -v flag properly removes volumes.

tests/api_tests/test_indexer.py (4)

7-20: LGTM!

Test correctly validates the supported types endpoint and checks for common file extensions.


26-39: LGTM!

Test properly handles multiple success status codes appropriate for asynchronous upload operations and validates task tracking information in the response.


41-52: LGTM!

Test appropriately validates markdown file upload with proper status code expectations.


54-66: LGTM!

Test correctly validates file upload with custom metadata.

tests/api_tests/test_openai_compat.py (1)

12-20: LGTM!

Test appropriately handles both enabled (200) and disabled (404) states, with proper validation when the endpoint is available.

tests/api_tests/conftest.py (3)

22-35: LGTM! Health check logic is sound.

The wait-for-API fixture correctly uses a direct httpx client rather than the session-scoped api_client fixture, since it needs to run before the session starts. The retry logic with 60 attempts × 2s intervals provides adequate time (120s) for services to start.


86-96: Cleanup exception handling is acceptable for test fixtures.

The broad exception catch in cleanup (Lines 93-96) was flagged by static analysis. While generally not ideal, this pattern is acceptable in test cleanup code to ensure teardown doesn't fail the test. The fixture prioritizes test isolation over reporting cleanup failures.


38-77: LGTM! Sample file fixtures are well-structured.

The text and markdown fixtures provide appropriate test content for validating file upload, indexing, and search functionality.

tests/api_tests/test_search.py (1)

10-45: Fixture correctly handles multiple indexing response formats.

The indexed_partition fixture properly handles both task_status_url and task_id response formats, with a reasonable fallback sleep. The polling logic with state checks for success/failure provides good coverage.

Comment thread .github/workflows/api_tests.yml Outdated
Comment thread tests/api_tests/test_extract.py Outdated
Comment thread tests/api_tests/test_indexer.py Outdated
Comment thread tests/api_tests/test_openai_compat.py Outdated
Comment thread tests/api_tests/test_openai_compat.py Outdated
Comment on lines +28 to +35
def test_create_duplicate_partition_fails(self, api_client, test_partition_name):
"""Test creating duplicate partition returns error."""
api_client.post(f"/partition/{test_partition_name}")
response = api_client.post(f"/partition/{test_partition_name}")
assert response.status_code in [400, 409]

# Cleanup
api_client.delete(f"/partition/{test_partition_name}")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Assert first creation succeeds and use fixture for cleanup.

The test doesn't verify that the first partition creation succeeded (Line 30), which could lead to false positives if both calls fail. Also, manual cleanup could be skipped if assertions fail.

🔧 Proposed fix
 def test_create_duplicate_partition_fails(self, api_client, test_partition_name):
     """Test creating duplicate partition returns error."""
-    api_client.post(f"/partition/{test_partition_name}")
+    response = api_client.post(f"/partition/{test_partition_name}")
+    assert response.status_code in [200, 201], "First partition creation should succeed"
+    
     response = api_client.post(f"/partition/{test_partition_name}")
     assert response.status_code in [400, 409]
-
-    # Cleanup
-    api_client.delete(f"/partition/{test_partition_name}")
+    
+    # Cleanup (or use created_partition fixture)
+    try:
+        api_client.delete(f"/partition/{test_partition_name}")
+    except Exception:
+        pass
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def test_create_duplicate_partition_fails(self, api_client, test_partition_name):
"""Test creating duplicate partition returns error."""
api_client.post(f"/partition/{test_partition_name}")
response = api_client.post(f"/partition/{test_partition_name}")
assert response.status_code in [400, 409]
# Cleanup
api_client.delete(f"/partition/{test_partition_name}")
def test_create_duplicate_partition_fails(self, api_client, test_partition_name):
"""Test creating duplicate partition returns error."""
response = api_client.post(f"/partition/{test_partition_name}")
assert response.status_code in [200, 201], "First partition creation should succeed"
response = api_client.post(f"/partition/{test_partition_name}")
assert response.status_code in [400, 409]
# Cleanup (or use created_partition fixture)
try:
api_client.delete(f"/partition/{test_partition_name}")
except Exception:
pass
🤖 Prompt for AI Agents
In @tests/api_tests/test_partition.py around lines 28 - 35, Update
test_create_duplicate_partition_fails to explicitly assert the first
api_client.post(f"/partition/{test_partition_name}") returned a success status
(e.g., 200 or 201) before making the second POST so a failing first call can't
mask failures; remove the manual cleanup delete and rely on the existing test
fixture for teardown (or convert the test to use the fixture that guarantees
partition cleanup), keeping the duplicate-create assertion that
response.status_code is in [400, 409].

Comment on lines +57 to +65
def test_search_multiple_partitions(self, api_client, indexed_partition):
"""Test searching across partitions."""
response = api_client.get(
"/search",
params={"text": "machine learning", "top_k": 5}
)
assert response.status_code == 200
data = response.json()
assert "documents" in data

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Bug: indexed_partition parameter is unused.

The test_search_multiple_partitions test receives indexed_partition but never uses it. This means the test searches across partitions without ensuring any partition is actually indexed, potentially causing false positives if the test passes despite indexing failures.

🐛 Proposed fix
 def test_search_multiple_partitions(self, api_client, indexed_partition):
     """Test searching across partitions."""
+    # Ensure partition is indexed before searching
+    assert indexed_partition is not None
+    
     response = api_client.get(
         "/search",
-        params={"text": "machine learning", "top_k": 5}
+        params={
+            "text": "machine learning", 
+            "top_k": 5,
+            "partitions": [indexed_partition]
+        }
     )
     assert response.status_code == 200
     data = response.json()
     assert "documents" in data

Note: Verify the correct parameter name for partition filtering in the /search endpoint.

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Ruff (0.14.10)

57-57: Unused method argument: indexed_partition

(ARG002)

🤖 Prompt for AI Agents
In @tests/api_tests/test_search.py around lines 57 - 65, The
test_search_multiple_partitions test currently ignores the indexed_partition
fixture; update the API call in test_search_multiple_partitions to pass the
partition filter using the indexed_partition value (e.g., add the appropriate
partition parameter to the params dict sent to api_client.get for "/search") so
the search is constrained to the partition known to be indexed; ensure you use
the correct query key expected by the endpoint (e.g., "partition" or
"partitions") when adding indexed_partition to the params.

Comment thread tests/api_tests/test_users.py Outdated
- Remove `|| true` from mock-vllm wait step to fail explicitly on timeout
- Change status code assertions from [404, 500] to 404 only for
  non-existent resources (extract, task, user, partition)
- Remove 500 from acceptable codes in OpenAI compat tests
- Remove 200 from invalid model test (should return error)
- Add assertion that first partition creation succeeds before
  testing duplicate rejection

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In @tests/api_tests/test_openai_compat.py:
- Around line 22-29: Update the assertion in test_chat_completions_endpoint to
accept 500 (and 200) like the completions test: modify the accepted status codes
list in the test_chat_completions_endpoint function from [400, 404, 422] to
[200, 400, 404, 422, 500] so it matches the error handling behavior
(HTTPException(status_code=500)) implemented in the chat/completions handlers
and mirrors test_completions_endpoint.

In @tests/api_tests/test_partition.py:
- Around line 39-43: The test_delete_partition function currently posts to
create a partition but doesn't assert the creation succeeded; update the test to
verify the POST to api_client.post(f"/partition/{test_partition_name}") returned
a successful status (e.g., 200 or 201) and optionally validate any returned body
before calling api_client.delete, then assert the delete response status_code in
[200, 204]; reference the test function name test_delete_partition and the
api_client.post / api_client.delete calls to locate and modify the code.

In @tests/api_tests/test_users.py:
- Around line 23-30: In test_get_user_by_id, assert the prerequisite /users/info
call succeeded and returned an id before using it: check
info_response.status_code == 200 and that "id" exists in info_response.json()
(do not use the fallback default 1), then set user_id from the JSON and proceed
to call api_client.get(f"/users/{user_id}") so failures in the prerequisite
request fail the test clearly; update the assertions in the test_get_user_by_id
function accordingly.
🧹 Nitpick comments (1)
tests/api_tests/test_extract.py (1)

13-17: test_extract_invalid_id_format doesn’t send an ID (it’s “missing param”, not “invalid format”).

GET /extract/ is testing the collection path (or a missing path param), not an invalid ID. If you want “invalid format”, pass a clearly invalid ID (e.g., not-a-uuid) and assert the contract-accurate code (commonly 422 for FastAPI UUID path params). Otherwise, rename the test to reflect what it’s actually verifying.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dceb272 and ec6c9fc.

📒 Files selected for processing (6)
  • .github/workflows/api_tests.yml
  • tests/api_tests/test_extract.py
  • tests/api_tests/test_indexer.py
  • tests/api_tests/test_openai_compat.py
  • tests/api_tests/test_partition.py
  • tests/api_tests/test_users.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/api_tests/test_indexer.py
  • .github/workflows/api_tests.yml
🧰 Additional context used
🧬 Code graph analysis (4)
tests/api_tests/test_partition.py (1)
tests/api_tests/conftest.py (3)
  • api_client (16-19)
  • test_partition_name (81-83)
  • created_partition (87-96)
tests/api_tests/test_extract.py (1)
tests/api_tests/conftest.py (1)
  • api_client (16-19)
tests/api_tests/test_openai_compat.py (1)
tests/api_tests/conftest.py (1)
  • api_client (16-19)
tests/api_tests/test_users.py (1)
tests/api_tests/conftest.py (1)
  • api_client (16-19)
⏰ 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). (2)
  • GitHub Check: api-tests
  • GitHub Check: index-backup-restore
🔇 Additional comments (12)
tests/api_tests/test_extract.py (1)

8-11: The test is correctly written and does not require modification.

The /extract/{extract_id} route accepts a plain string parameter (extract_id: str) with no validation constraints. There is no UUID type annotation or format validation that would cause "nonexistent-id-12345" to return a 422 error. The vectordb simply performs string matching on the ID and returns None for nonexistent chunks, which the handler correctly converts to a 404 response. The test will work as intended.

Likely an incorrect or invalid review comment.

tests/api_tests/test_users.py (3)

8-13: LGTM!

The test correctly validates the current user endpoint and checks for the required "id" field in the response.


15-21: LGTM!

The test properly validates the users list endpoint and includes a helpful comment about authentication behavior.


32-35: LGTM!

The test properly validates the error handling for non-existent users.

tests/api_tests/test_openai_compat.py (3)

12-20: LGTM!

The test correctly handles both the enabled and disabled states of the models endpoint, with proper validation of the response structure when available.


31-41: Same status code inconsistency as test_chat_completions_endpoint.

This test also excludes 500 while test_completions_endpoint accepts it. See the comment on Lines 22-29.


43-50: Status code handling looks reasonable.

This test appropriately accepts a range of status codes including 500, which is reasonable for LLM endpoints that may encounter runtime errors. The chat completions endpoints should likely be aligned with this approach.

tests/api_tests/test_partition.py (5)

8-13: LGTM!

The test correctly validates the partition listing endpoint.


15-26: LGTM!

The test properly validates partition creation and cleanup. The manual cleanup is appropriate here since the test explicitly validates the creation flow.


28-37: LGTM!

The test properly validates duplicate partition rejection with a clear assertion (Line 31) that the initial creation succeeded, as mentioned in the PR objectives.


45-51: LGTM!

The test correctly validates listing files in an empty partition and appropriately uses the created_partition fixture for setup and cleanup.


53-56: LGTM!

The test properly validates error handling for deleting a non-existent partition.

Comment on lines +22 to +29
def test_chat_completions_endpoint(self, api_client):
"""Test chat completions endpoint exists or is disabled."""
response = api_client.post(
"/v1/chat/completions",
json={"model": "openrag-all", "messages": []}
)
# 404 if endpoint disabled, 400/422 if enabled but invalid input
assert response.status_code in [400, 404, 422]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, locate and read the test file
find . -name "test_openai_compat.py" -type f

Repository: linagora/openrag

Length of output: 99


🏁 Script executed:

#!/bin/bash
# Get line count to understand file size
wc -l tests/api_tests/test_openai_compat.py 2>/dev/null || find . -name "test_openai_compat.py" -type f -exec wc -l {} \;

Repository: linagora/openrag

Length of output: 100


🏁 Script executed:

#!/bin/bash
# Read the test file around the mentioned lines
cat -n tests/api_tests/test_openai_compat.py | head -60

Repository: linagora/openrag

Length of output: 2339


🏁 Script executed:

#!/bin/bash
# Search for chat completions implementation
rg -n "chat.*completions|/v1/chat" --type=py -A 5 -B 2

Repository: linagora/openrag

Length of output: 5824


🏁 Script executed:

#!/bin/bash
# Search for completions endpoint implementation to understand error handling
rg -n "def.*completions|@.*route.*completions" --type=py -A 10

Repository: linagora/openrag

Length of output: 4848


🏁 Script executed:

#!/bin/bash
# Read the chat completions endpoint implementation
cat -n openrag/routers/openai.py | head -200 | tail -100

Repository: linagora/openrag

Length of output: 4102


🏁 Script executed:

#!/bin/bash
# Find and read the completions endpoint implementation
rg -n "^def.*completions|^@router.post.*completions" openrag/routers/openai.py -A 30

Repository: linagora/openrag

Length of output: 42


🏁 Script executed:

#!/bin/bash
# Check for any error handling or 500 status code raising in the endpoints
rg -n "500|Internal|raise.*Exception|except" openrag/routers/openai.py -B 2 -A 2

Repository: linagora/openrag

Length of output: 3007


🏁 Script executed:

#!/bin/bash
# Look for the full structure of both endpoint handlers
ast-grep --pattern 'async def $_($$$) {
  $$$
  log = logger.bind($_)
  $$$
}'

Repository: linagora/openrag

Length of output: 42


Include 500 status code in accepted responses to match the completions endpoint.

Both test_chat_completions_endpoint and test_completions_endpoint use identical error handling patterns that can raise 500 on any exception during request processing. The chat completions endpoint implementation (lines 187–192 and 225–230) explicitly raises HTTPException(status_code=500) for runtime failures, matching the completions endpoint behavior (lines 302–307 and 317–322). Update line 29 to accept [200, 400, 404, 422, 500] for consistency and to prevent test failures from legitimate server errors.

🤖 Prompt for AI Agents
In @tests/api_tests/test_openai_compat.py around lines 22 - 29, Update the
assertion in test_chat_completions_endpoint to accept 500 (and 200) like the
completions test: modify the accepted status codes list in the
test_chat_completions_endpoint function from [400, 404, 422] to [200, 400, 404,
422, 500] so it matches the error handling behavior
(HTTPException(status_code=500)) implemented in the chat/completions handlers
and mirrors test_completions_endpoint.

Comment on lines +39 to +43
def test_delete_partition(self, api_client, test_partition_name):
"""Test deleting a partition."""
api_client.post(f"/partition/{test_partition_name}")
response = api_client.delete(f"/partition/{test_partition_name}")
assert response.status_code in [200, 204]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add assertion for partition creation.

The test deletes a partition without verifying that creation succeeded (Line 41). If creation fails, the test becomes ambiguous—it would actually be testing deletion of a non-existent partition rather than successful deletion.

✨ Proposed fix
     def test_delete_partition(self, api_client, test_partition_name):
         """Test deleting a partition."""
-        api_client.post(f"/partition/{test_partition_name}")
+        create_response = api_client.post(f"/partition/{test_partition_name}")
+        assert create_response.status_code in [200, 201], "Failed to create partition for deletion test"
         response = api_client.delete(f"/partition/{test_partition_name}")
         assert response.status_code in [200, 204]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def test_delete_partition(self, api_client, test_partition_name):
"""Test deleting a partition."""
api_client.post(f"/partition/{test_partition_name}")
response = api_client.delete(f"/partition/{test_partition_name}")
assert response.status_code in [200, 204]
def test_delete_partition(self, api_client, test_partition_name):
"""Test deleting a partition."""
create_response = api_client.post(f"/partition/{test_partition_name}")
assert create_response.status_code in [200, 201], "Failed to create partition for deletion test"
response = api_client.delete(f"/partition/{test_partition_name}")
assert response.status_code in [200, 204]
🤖 Prompt for AI Agents
In @tests/api_tests/test_partition.py around lines 39 - 43, The
test_delete_partition function currently posts to create a partition but doesn't
assert the creation succeeded; update the test to verify the POST to
api_client.post(f"/partition/{test_partition_name}") returned a successful
status (e.g., 200 or 201) and optionally validate any returned body before
calling api_client.delete, then assert the delete response status_code in [200,
204]; reference the test function name test_delete_partition and the
api_client.post / api_client.delete calls to locate and modify the code.

Comment on lines +23 to +30
def test_get_user_by_id(self, api_client):
"""Test getting user by ID."""
# First get current user to know a valid ID
info_response = api_client.get("/users/info")
user_id = info_response.json().get("id", 1)

response = api_client.get(f"/users/{user_id}")
assert response.status_code == 200

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add assertion for the prerequisite API call.

The test fetches the current user ID without verifying the prerequisite request succeeded. If /users/info fails or returns data without an "id" field, the fallback value 1 masks the problem, potentially leading to false positives or confusing test failures.

✨ Proposed fix
     def test_get_user_by_id(self, api_client):
         """Test getting user by ID."""
         # First get current user to know a valid ID
         info_response = api_client.get("/users/info")
+        assert info_response.status_code == 200
-        user_id = info_response.json().get("id", 1)
+        user_id = info_response.json()["id"]
 
         response = api_client.get(f"/users/{user_id}")
         assert response.status_code == 200
🤖 Prompt for AI Agents
In @tests/api_tests/test_users.py around lines 23 - 30, In test_get_user_by_id,
assert the prerequisite /users/info call succeeded and returned an id before
using it: check info_response.status_code == 200 and that "id" exists in
info_response.json() (do not use the fallback default 1), then set user_id from
the JSON and proceed to call api_client.get(f"/users/{user_id}") so failures in
the prerequisite request fail the test clearly; update the assertions in the
test_get_user_by_id function accordingly.

- Fix extract router to re-raise HTTPException before generic handler
- Fix get_chunk_by_id to handle Milvus Int64 _id field properly:
  - Convert string chunk_id to integer before querying
  - Return None for invalid ID formats instead of raising exception

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
openrag/components/indexer/vectordb/vectordb.py (1)

727-727: Consider using parameterized queries for consistency.

While the f-string filter is safe due to integer validation, using parameterized queries would align with the pattern used in get_file_chunks (lines 660-661):

♻️ Suggested refactor for consistency
         response = await self._async_client.query(
             collection_name=self.collection_name,
-            filter=f"_id == {chunk_id_int}",
+            filter="_id == {chunk_id}",
+            filter_params={"chunk_id": chunk_id_int},
             limit=1,
         )
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ec6c9fc and 9b7351d.

📒 Files selected for processing (2)
  • openrag/components/indexer/vectordb/vectordb.py
  • openrag/routers/extract.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). (2)
  • GitHub Check: api-tests
  • GitHub Check: index-backup-restore
🔇 Additional comments (3)
openrag/routers/extract.py (1)

69-70: LGTM! Critical fix for proper HTTP error codes.

This correctly preserves the intended 404 and 403 responses raised earlier in the function instead of converting them to 500 errors via the generic exception handler.

openrag/components/indexer/vectordb/vectordb.py (2)

712-714: LGTM: Clear documentation of Int64 handling and None return cases.

The docstring updates accurately reflect the Milvus Int64 _id requirements and all possible return scenarios.


717-722: LGTM: Robust input validation prevents invalid Milvus queries.

The string-to-integer conversion with graceful error handling correctly prevents invalid _id queries and maintains consistency with the "not found" return behavior.

The CI workflow checks mock-vllm health from the host via curl,
but the port wasn't exposed. Add port mapping 8000:8000.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
.github/workflows/api_tests/docker-compose.yaml (1)

50-50: Update MinIO to a more recent release.

The MinIO version (RELEASE.2023-03-20T20-16-18Z) is from March 2023 and is over 2.5 years old. While this release contains important security patches, consider updating to a more recent version such as RELEASE.2025-10-15T17-29-55Z (current as of early 2026) to benefit from additional security patches and improvements.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9b7351d and 9e88ece.

📒 Files selected for processing (1)
  • .github/workflows/api_tests/docker-compose.yaml
🧰 Additional context used
🪛 actionlint (1.7.10)
.github/workflows/api_tests/docker-compose.yaml

4-4: "jobs" section is missing in workflow

(syntax-check)


4-4: "on" section is missing in workflow

(syntax-check)


4-4: unexpected key "services" for "workflow" section. expected one of "concurrency", "defaults", "env", "jobs", "name", "on", "permissions", "run-name"

(syntax-check)


128-128: unexpected key "volumes" for "workflow" section. expected one of "concurrency", "defaults", "env", "jobs", "name", "on", "permissions", "run-name"

(syntax-check)

⏰ 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). (2)
  • GitHub Check: api-tests
  • GitHub Check: index-backup-restore
🔇 Additional comments (2)
.github/workflows/api_tests/docker-compose.yaml (2)

109-109: No action needed—the PROMPTS_DIR path is correct.

The relative path ../prompts/example1 resolves correctly within the container. The Dockerfile copies prompts/ to /app/prompts/, and since the container's working directory is /app/openrag, the relative path ../prompts/example1 correctly resolves to /app/prompts/example1. The directory structure is properly set up during the Docker build process.

Likely an incorrect or invalid review comment.


94-94: No action needed — these environment variables are not used by the OpenRAG service.

The BASE_URL and VLM_BASE_URL variables set in the docker-compose.yaml are only consumed by the evaluation-pipeline scripts (automatic-evaluation-pipeline/generate_questions.py and benchmark.py), not by the main OpenRAG API service. The OpenRAG service itself does not reference these environment variables, so setting them to localhost URLs does not cause connection failures. The API service correctly listens on port 8080 as defined in the docker-compose configuration.

Likely an incorrect or invalid review comment.

@Ahmath-Gadji Ahmath-Gadji left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

@paultranvan

Copy link
Copy Markdown
Collaborator Author

Next actions:

@paultranvan
paultranvan merged commit 4a7b23d into dev Jan 14, 2026
5 checks passed
@Ahmath-Gadji
Ahmath-Gadji deleted the feature/lightweight-api-tests branch January 15, 2026 09:09
This was referenced Jan 15, 2026
@Ahmath-Gadji Ahmath-Gadji added chore No production code impact, typically improve tooling, code quality, etc enhancement New feature or request and removed chore No production code impact, typically improve tooling, code quality, etc labels Jan 22, 2026
This was referenced Jan 28, 2026
@coderabbitai coderabbitai Bot mentioned this pull request Feb 9, 2026
@coderabbitai coderabbitai Bot mentioned this pull request Feb 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants