From 0f66bda8ec2a3a6ef52b30003cca6c37244728fa Mon Sep 17 00:00:00 2001 From: Jawad Khan Date: Wed, 26 Nov 2025 12:59:29 +0500 Subject: [PATCH 1/9] feat: Add export api --- .code-samples.meilisearch.yaml | 10 ++++++ docker-compose.yml | 12 +++++++ meilisearch/client.py | 51 +++++++++++++++++++++++++++++ meilisearch/config.py | 1 + tests/client/test_client_exports.py | 42 ++++++++++++++++++++++++ tests/common.py | 1 + tests/conftest.py | 29 ++++++++++++---- 7 files changed, 139 insertions(+), 7 deletions(-) create mode 100644 tests/client/test_client_exports.py diff --git a/.code-samples.meilisearch.yaml b/.code-samples.meilisearch.yaml index bf7062f3..8ced0b74 100644 --- a/.code-samples.meilisearch.yaml +++ b/.code-samples.meilisearch.yaml @@ -514,6 +514,16 @@ faceted_search_1: |- }) post_dump_1: |- client.create_dump() +export_post_1: |- + client.export( + url='https://remote-meilisearch-instance.com', + api_key='masterKey', + pay_load_size='50MiB', + indexes={ + 'movies*': {}, + 'books*': {}, + }, + ) phrase_search_1: |- client.index('movies').search('"african american" horror') sorting_guide_update_sortable_attributes_1: |- diff --git a/docker-compose.yml b/docker-compose.yml index 1f9f9630..71470e7d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,10 +6,13 @@ services: working_dir: /home/package environment: - MEILISEARCH_URL=http://meilisearch:7700 + - MEILISEARCH_URL_2=http://meilisearch2:7700 depends_on: - meilisearch + - meilisearch2 links: - meilisearch + - meilisearch2 volumes: - ./:/home/package @@ -20,3 +23,12 @@ services: environment: - MEILI_MASTER_KEY=masterKey - MEILI_NO_ANALYTICS=true + + meilisearch2: + image: getmeili/meilisearch:latest + container_name: meili2 + ports: + - "7701:7700" + environment: + - MEILI_MASTER_KEY=masterKey + - MEILI_NO_ANALYTICS=true diff --git a/meilisearch/client.py b/meilisearch/client.py index 99f8a5da..21dadf52 100644 --- a/meilisearch/client.py +++ b/meilisearch/client.py @@ -631,6 +631,57 @@ def create_dump(self) -> TaskInfo: return TaskInfo(**task) + def export( + self, + url: str, + api_key: Optional[str] = None, + pay_load_size: Optional[str] = None, + indexes: Optional[Mapping[str, Any]] = None, + ) -> TaskInfo: + """Trigger the creation of a Meilisearch export. + + Parameters + ---------- + url: + A string pointing to a remote Meilisearch instance, including its port if necessary. + + api_key: + A security key with index.create, settings.update, and documents.add permissions + to a secured Meilisearch instance. + + pay_load_size: + The maximum size of each single data payload in a human-readable format such as "100MiB". + Larger payloads are generally more efficient, but require significantly more powerful machines. + + indexes: + A set of objects whose keys correspond to patterns matching the indexes you want to export. + By default, Meilisearch exports all documents across all indexes. + + Returns + ------- + task_info: + TaskInfo instance containing information about a task to track the progress of an asynchronous process. + https://www.meilisearch.com/docs/reference/api/export#create-an-export + + Raises + ------ + MeilisearchApiError + An error containing details about why Meilisearch can't process your request. + Meilisearch error codes are described + here: https://www.meilisearch.com/docs/reference/errors/error_codes#meilisearch-errors + """ + payload: Dict[str, Any] = {"url": url} + if api_key is not None: + payload["apiKey"] = api_key + if pay_load_size is not None: + payload["payloadSize"] = pay_load_size + if indexes is not None: + payload["indexes"] = indexes + + task = self.http.post(self.config.paths.exports, body=payload) + + return TaskInfo(**task) + def create_snapshot(self) -> TaskInfo: """Trigger the creation of a Meilisearch snapshot. diff --git a/meilisearch/config.py b/meilisearch/config.py index df39e64a..36594613 100644 --- a/meilisearch/config.py +++ b/meilisearch/config.py @@ -49,6 +49,7 @@ class Paths: network = "network" experimental_features = "experimental-features" webhooks = "webhooks" + exports = "export" def __init__( self, diff --git a/tests/client/test_client_exports.py b/tests/client/test_client_exports.py new file mode 100644 index 00000000..cff04759 --- /dev/null +++ b/tests/client/test_client_exports.py @@ -0,0 +1,42 @@ +import os + +import pytest + +from tests import common + +pytestmark = pytest.mark.skipif( + not os.getenv("MEILISEARCH_URL_2"), + reason="Export API tests run only when second server is configured", +) + + +def test_export_creation(client, client2, index_with_documents): + """Tests the creation of a Meilisearch export.""" + index = index_with_documents() + export_task = client.export(common.BASE_URL_2, api_key=common.MASTER_KEY) + task_result = client.wait_for_task(export_task.task_uid) + assert task_result.status == "succeeded" + + index2 = client2.get_index(index.uid) + assert index2.uid == index.uid + assert index2.primary_key == index.get_primary_key() + assert index2.get_documents().total == index.get_documents().total + + +def test_export_creation_with_index_filter(client, client2, index_with_documents): + """Tests the creation of a Meilisearch export with specific index UIDs.""" + index_with_documents() + index = index_with_documents(common.INDEX_UID2) + + indexes = {common.INDEX_UID2: {"filter": None}} + export_task = client.export(common.BASE_URL_2, api_key=common.MASTER_KEY, indexes=indexes) + task_result = client.wait_for_task(export_task.task_uid) + assert task_result.status == "succeeded" + + response = client2.get_indexes() + assert response["total"] == 1 + index2 = client2.get_index(common.INDEX_UID2) + + assert index2.uid == index.uid + assert index2.primary_key == index.get_primary_key() + assert index.get_documents().total == index2.get_documents().total diff --git a/tests/common.py b/tests/common.py index 253ec760..5be04cd1 100644 --- a/tests/common.py +++ b/tests/common.py @@ -2,6 +2,7 @@ MASTER_KEY = "masterKey" BASE_URL = os.getenv("MEILISEARCH_URL", "http://127.0.0.1:7700") +BASE_URL_2 = os.getenv("MEILISEARCH_URL_2", "http://127.0.0.1:7701") INDEX_UID = "indexUID" INDEX_UID2 = "indexUID2" diff --git a/tests/conftest.py b/tests/conftest.py index b9aeed65..bd00c625 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,4 +1,5 @@ # pylint: disable=redefined-outer-name +import os import json from typing import Optional @@ -16,19 +17,31 @@ def client(): return meilisearch.Client(common.BASE_URL, common.MASTER_KEY) +@fixture(scope="session") +def client2(): + return meilisearch.Client(common.BASE_URL_2, common.MASTER_KEY) + + +def _clear_indexes(meilisearch_client): + """Deletes all the indexes in the Meilisearch instance.""" + + indexes = meilisearch_client.get_indexes() + for index in indexes["results"]: + task = meilisearch_client.index(index.uid).delete() + meilisearch_client.wait_for_task(task.task_uid) + + @fixture(autouse=True) -def clear_indexes(client): +def clear_indexes(client, client2): """ Auto-clears the indexes after each test function run. Makes all the test functions independent. """ # Yields back to the test function. yield - # Deletes all the indexes in the Meilisearch instance. - indexes = client.get_indexes() - for index in indexes["results"]: - task = client.index(index.uid).delete() - client.wait_for_task(task.task_uid) + _clear_indexes(client) + if os.getenv("MEILISEARCH_URL_2"): + _clear_indexes(client2) @fixture(autouse=True) @@ -47,12 +60,14 @@ def clear_webhooks(client): @fixture(autouse=True) -def clear_all_tasks(client): +def clear_all_tasks(client, client2): """ Auto-clears the tasks after each test function run. Makes all the test functions independent. """ client.delete_tasks({"statuses": ["succeeded", "failed", "canceled"]}) + if os.getenv("MEILISEARCH_URL_2"): + client2.delete_tasks({"statuses": ["succeeded", "failed", "canceled"]}) @fixture(scope="function") From 2156d270ed34225846149e027ce2e2e5ee140fbd Mon Sep 17 00:00:00 2001 From: Jawad Khan Date: Wed, 26 Nov 2025 13:09:16 +0500 Subject: [PATCH 2/9] fix: fixed import order --- tests/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index bd00c625..41c44360 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,6 +1,6 @@ # pylint: disable=redefined-outer-name -import os import json +import os from typing import Optional import requests From 10decc3dee31a790332c81ef9f9881201bfdeac9 Mon Sep 17 00:00:00 2001 From: Jawad Khan Date: Wed, 26 Nov 2025 13:14:01 +0500 Subject: [PATCH 3/9] fix: fixed param name --- .code-samples.meilisearch.yaml | 2 +- meilisearch/client.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.code-samples.meilisearch.yaml b/.code-samples.meilisearch.yaml index 8ced0b74..5dd1089b 100644 --- a/.code-samples.meilisearch.yaml +++ b/.code-samples.meilisearch.yaml @@ -518,7 +518,7 @@ export_post_1: |- client.export( url='https://remote-meilisearch-instance.com', api_key='masterKey', - pay_load_size='50MiB', + payload_size='50MiB', indexes={ 'movies*': {}, 'books*': {}, diff --git a/meilisearch/client.py b/meilisearch/client.py index 21dadf52..62ad5252 100644 --- a/meilisearch/client.py +++ b/meilisearch/client.py @@ -635,7 +635,7 @@ def export( self, url: str, api_key: Optional[str] = None, - pay_load_size: Optional[str] = None, + payload_size: Optional[str] = None, indexes: Optional[Mapping[str, Any]] = None, ) -> TaskInfo: """Trigger the creation of a Meilisearch export. @@ -649,7 +649,7 @@ def export( A security key with index.create, settings.update, and documents.add permissions to a secured Meilisearch instance. - pay_load_size: + payload_size: The maximum size of each single data payload in a human-readable format such as "100MiB". Larger payloads are generally more efficient, but require significantly more powerful machines. @@ -673,8 +673,8 @@ def export( payload: Dict[str, Any] = {"url": url} if api_key is not None: payload["apiKey"] = api_key - if pay_load_size is not None: - payload["payloadSize"] = pay_load_size + if payload_size is not None: + payload["payloadSize"] = payload_size if indexes is not None: payload["indexes"] = indexes From 196918e0a8ba4d00e70440ad67a429d681335cca Mon Sep 17 00:00:00 2001 From: Jawad Khan Date: Thu, 1 Jan 2026 18:24:03 +0500 Subject: [PATCH 4/9] fix: fixes test cases --- .code-samples.meilisearch.yaml | 2 +- .github/workflows/tests.yml | 2 ++ docker-compose.yml | 2 +- meilisearch/client.py | 2 +- tests/client/test_client_exports.py | 36 +++++++++++++++++++++-------- tests/common.py | 2 +- tests/conftest.py | 16 +++++++++++-- 7 files changed, 47 insertions(+), 15 deletions(-) diff --git a/.code-samples.meilisearch.yaml b/.code-samples.meilisearch.yaml index 5dd1089b..e75dc353 100644 --- a/.code-samples.meilisearch.yaml +++ b/.code-samples.meilisearch.yaml @@ -518,7 +518,7 @@ export_post_1: |- client.export( url='https://remote-meilisearch-instance.com', api_key='masterKey', - payload_size='50MiB', + payload_size='50 MiB', indexes={ 'movies*': {}, 'books*': {}, diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 3210f8b5..612e6df3 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -31,6 +31,8 @@ jobs: run: pipenv install --dev --python=${{ matrix.python-version }} - name: Meilisearch (latest version) setup with Docker run: docker run -d -p 7700:7700 getmeili/meilisearch-enterprise:latest meilisearch --no-analytics --master-key=masterKey + - name: Meilisearch (latest version) secondary server for testing setup with Docker + run: docker run -d -p 7701:7700 getmeili/meilisearch-enterprise:latest meilisearch2 --no-analytics --master-key=masterKey - name: Test with pytest run: pipenv run pytest --cov-report=xml diff --git a/docker-compose.yml b/docker-compose.yml index 71470e7d..529312be 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -25,7 +25,7 @@ services: - MEILI_NO_ANALYTICS=true meilisearch2: - image: getmeili/meilisearch:latest + image: getmeili/meilisearch-enterprise:latest container_name: meili2 ports: - "7701:7700" diff --git a/meilisearch/client.py b/meilisearch/client.py index 62ad5252..ca6fdd0e 100644 --- a/meilisearch/client.py +++ b/meilisearch/client.py @@ -650,7 +650,7 @@ def export( to a secured Meilisearch instance. payload_size: - The maximum size of each single data payload in a human-readable format such as "100MiB". + The maximum size of each single data payload in a human-readable format such as "100 MiB". Larger payloads are generally more efficient, but require significantly more powerful machines. indexes: diff --git a/tests/client/test_client_exports.py b/tests/client/test_client_exports.py index cff04759..8b78dc8b 100644 --- a/tests/client/test_client_exports.py +++ b/tests/client/test_client_exports.py @@ -1,4 +1,5 @@ import os +import time import pytest @@ -10,7 +11,9 @@ ) -def test_export_creation(client, client2, index_with_documents): +def test_export_creation( + client, client2, index_with_documents, enable_vector_search +): # pylint: disable=unused-argument """Tests the creation of a Meilisearch export.""" index = index_with_documents() export_task = client.export(common.BASE_URL_2, api_key=common.MASTER_KEY) @@ -20,23 +23,38 @@ def test_export_creation(client, client2, index_with_documents): index2 = client2.get_index(index.uid) assert index2.uid == index.uid assert index2.primary_key == index.get_primary_key() - assert index2.get_documents().total == index.get_documents().total + assert_exported_count(index2, index.get_documents().total) -def test_export_creation_with_index_filter(client, client2, index_with_documents): +def test_export_creation_with_index_filter( + client, client2, index_with_documents, enable_vector_search +): # pylint: disable=unused-argument """Tests the creation of a Meilisearch export with specific index UIDs.""" - index_with_documents() - index = index_with_documents(common.INDEX_UID2) + index = index_with_documents() - indexes = {common.INDEX_UID2: {"filter": None}} + indexes = {index.uid: {"filter": None}} export_task = client.export(common.BASE_URL_2, api_key=common.MASTER_KEY, indexes=indexes) task_result = client.wait_for_task(export_task.task_uid) assert task_result.status == "succeeded" response = client2.get_indexes() assert response["total"] == 1 - index2 = client2.get_index(common.INDEX_UID2) - + index2 = client2.get_index(index.uid) assert index2.uid == index.uid assert index2.primary_key == index.get_primary_key() - assert index.get_documents().total == index2.get_documents().total + assert_exported_count(index2, index.get_documents().total) + + +def assert_exported_count(index, expected_count): + # Wait up to 20 seconds for documents to be imported + max_attempts = 20 + for attempt in range(max_attempts): + doc_count = index.get_documents().total + if doc_count == expected_count: + return + if attempt < max_attempts - 1: + time.sleep(1) + + # Final check with clear failure message + actual_count = index.get_documents().total + assert actual_count == expected_count diff --git a/tests/common.py b/tests/common.py index 5be04cd1..c19212de 100644 --- a/tests/common.py +++ b/tests/common.py @@ -2,7 +2,7 @@ MASTER_KEY = "masterKey" BASE_URL = os.getenv("MEILISEARCH_URL", "http://127.0.0.1:7700") -BASE_URL_2 = os.getenv("MEILISEARCH_URL_2", "http://127.0.0.1:7701") +BASE_URL_2 = os.getenv("MEILISEARCH_URL_2") INDEX_UID = "indexUID" INDEX_UID2 = "indexUID2" diff --git a/tests/conftest.py b/tests/conftest.py index 41c44360..7d8c6964 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -269,14 +269,26 @@ def enable_vector_search(): requests.patch( f"{common.BASE_URL}/experimental-features", headers={"Authorization": f"Bearer {common.MASTER_KEY}"}, - json={"vectorStore": True}, + json={"vectorStoreSetting": True}, + timeout=10, + ) + requests.patch( + f"{common.BASE_URL_2}/experimental-features", + headers={"Authorization": f"Bearer {common.MASTER_KEY}"}, + json={"vectorStoreSetting": True}, timeout=10, ) yield requests.patch( f"{common.BASE_URL}/experimental-features", headers={"Authorization": f"Bearer {common.MASTER_KEY}"}, - json={"vectorStore": False}, + json={"vectorStoreSetting": False}, + timeout=10, + ) + requests.patch( + f"{common.BASE_URL_2}/experimental-features", + headers={"Authorization": f"Bearer {common.MASTER_KEY}"}, + json={"vectorStoreSetting": False}, timeout=10, ) From 148a7c14e14e95d6cb8b77c50492c47509c0ab77 Mon Sep 17 00:00:00 2001 From: Jawad Khan Date: Thu, 1 Jan 2026 18:32:57 +0500 Subject: [PATCH 5/9] fix: fixes test cases --- .github/workflows/tests.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 612e6df3..bef0c0dc 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -32,9 +32,11 @@ jobs: - name: Meilisearch (latest version) setup with Docker run: docker run -d -p 7700:7700 getmeili/meilisearch-enterprise:latest meilisearch --no-analytics --master-key=masterKey - name: Meilisearch (latest version) secondary server for testing setup with Docker - run: docker run -d -p 7701:7700 getmeili/meilisearch-enterprise:latest meilisearch2 --no-analytics --master-key=masterKey + run: docker run -d -p 7701:7700 getmeili/meilisearch-enterprise:latest meilisearch --no-analytics --master-key=masterKey - name: Test with pytest run: pipenv run pytest --cov-report=xml + env: + MEILISEARCH_URL_2: "http://127.0.0.1:7701" pylint: name: pylint From b7108e942d673dc1a9b979aefbdb7cc616027043 Mon Sep 17 00:00:00 2001 From: Jawad Khan Date: Thu, 1 Jan 2026 18:57:58 +0500 Subject: [PATCH 6/9] fix: fixes test cases --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index bef0c0dc..2ffbe069 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -32,7 +32,7 @@ jobs: - name: Meilisearch (latest version) setup with Docker run: docker run -d -p 7700:7700 getmeili/meilisearch-enterprise:latest meilisearch --no-analytics --master-key=masterKey - name: Meilisearch (latest version) secondary server for testing setup with Docker - run: docker run -d -p 7701:7700 getmeili/meilisearch-enterprise:latest meilisearch --no-analytics --master-key=masterKey + run: docker run -d -p 7701:7700 getmeili/meilisearch-enterprise:latest meilisearch2 --no-analytics --master-key=masterKey - name: Test with pytest run: pipenv run pytest --cov-report=xml env: From 88912c3cfbc561389f47a23730d6c2ea67ba4037 Mon Sep 17 00:00:00 2001 From: Jawad Khan Date: Thu, 1 Jan 2026 19:01:54 +0500 Subject: [PATCH 7/9] fix: fixes test cases --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2ffbe069..699d3127 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -32,7 +32,7 @@ jobs: - name: Meilisearch (latest version) setup with Docker run: docker run -d -p 7700:7700 getmeili/meilisearch-enterprise:latest meilisearch --no-analytics --master-key=masterKey - name: Meilisearch (latest version) secondary server for testing setup with Docker - run: docker run -d -p 7701:7700 getmeili/meilisearch-enterprise:latest meilisearch2 --no-analytics --master-key=masterKey + run: docker run -d --name meilisearch2 -p 7701:7700 getmeili/meilisearch-enterprise:latest meilisearch --no-analytics --master-key=masterKey - name: Test with pytest run: pipenv run pytest --cov-report=xml env: From c819e706339a391565f32e2bc895bccd23e6b55f Mon Sep 17 00:00:00 2001 From: Jawad Khan Date: Thu, 1 Jan 2026 19:09:07 +0500 Subject: [PATCH 8/9] fix: fixes test cases --- .github/workflows/tests.yml | 2 +- tests/conftest.py | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 699d3127..2f69048e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -30,7 +30,7 @@ jobs: - name: Install dependencies run: pipenv install --dev --python=${{ matrix.python-version }} - name: Meilisearch (latest version) setup with Docker - run: docker run -d -p 7700:7700 getmeili/meilisearch-enterprise:latest meilisearch --no-analytics --master-key=masterKey + run: docker run -d --name meilisearch -p 7700:7700 getmeili/meilisearch-enterprise:latest meilisearch --no-analytics --master-key=masterKey - name: Meilisearch (latest version) secondary server for testing setup with Docker run: docker run -d --name meilisearch2 -p 7701:7700 getmeili/meilisearch-enterprise:latest meilisearch --no-analytics --master-key=masterKey - name: Test with pytest diff --git a/tests/conftest.py b/tests/conftest.py index 7d8c6964..cc61935a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -19,6 +19,8 @@ def client(): @fixture(scope="session") def client2(): + if not os.getenv("MEILISEARCH_URL_2"): + return None return meilisearch.Client(common.BASE_URL_2, common.MASTER_KEY) @@ -40,7 +42,7 @@ def clear_indexes(client, client2): # Yields back to the test function. yield _clear_indexes(client) - if os.getenv("MEILISEARCH_URL_2"): + if client2 is not None: _clear_indexes(client2) @@ -66,7 +68,7 @@ def clear_all_tasks(client, client2): Makes all the test functions independent. """ client.delete_tasks({"statuses": ["succeeded", "failed", "canceled"]}) - if os.getenv("MEILISEARCH_URL_2"): + if client2 is not None: client2.delete_tasks({"statuses": ["succeeded", "failed", "canceled"]}) From 9ea1c399ae732cdc2ebeb20c1b778f80a679ae24 Mon Sep 17 00:00:00 2001 From: Jawad Khan Date: Thu, 1 Jan 2026 19:11:48 +0500 Subject: [PATCH 9/9] fix: fixes test cases --- .github/workflows/tests.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2f69048e..cfb00d47 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -33,6 +33,15 @@ jobs: run: docker run -d --name meilisearch -p 7700:7700 getmeili/meilisearch-enterprise:latest meilisearch --no-analytics --master-key=masterKey - name: Meilisearch (latest version) secondary server for testing setup with Docker run: docker run -d --name meilisearch2 -p 7701:7700 getmeili/meilisearch-enterprise:latest meilisearch --no-analytics --master-key=masterKey + - name: Wait for Meilisearch servers to be ready + run: | + echo "Waiting for primary Meilisearch server..." + timeout 30 bash -c 'until curl -f http://127.0.0.1:7700/health > /dev/null 2>&1; do sleep 1; done' || exit 1 + echo "Primary Meilisearch server is ready" + + echo "Waiting for secondary Meilisearch server..." + timeout 30 bash -c 'until curl -f http://127.0.0.1:7701/health > /dev/null 2>&1; do sleep 1; done' || exit 1 + echo "Secondary Meilisearch server is ready" - name: Test with pytest run: pipenv run pytest --cov-report=xml env: