From f3cc292dafa894a5ade2c0440e632d89fcba3654 Mon Sep 17 00:00:00 2001 From: yuneng-jiang Date: Sun, 15 Mar 2026 20:54:35 -0700 Subject: [PATCH] [Infra] Speed up CI: batch pip installs and fix pytest -n parallelism Several test jobs were underutilizing their CPU allocation (~25%) because they were either missing pytest-xdist -n or using -n 2 on 4-vCPU machines. Batching individual pip install calls into single commands reduces resolver overhead and saves ~30-60s per job. Co-Authored-By: Claude Opus 4.6 --- .circleci/config.yml | 158 +++++++++---------------------------------- 1 file changed, 33 insertions(+), 125 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f29e6a485d..6aefb57b0f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -155,50 +155,18 @@ jobs: command: | python -m pip install --upgrade pip python -m pip install -r .circleci/requirements.txt - pip install "pytest==7.3.1" - pip install "pytest-retry==1.6.3" - pip install "pytest-asyncio==0.21.1" - pip install "pytest-cov==5.0.0" - pip install "mypy==1.18.2" - pip install "google-generativeai==0.3.2" - pip install "google-cloud-aiplatform==1.43.0" - pip install pyarrow - pip install "boto3==1.36.0" - pip install "aioboto3==13.4.0" - pip install langchain - pip install lunary==0.2.5 - pip install "azure-identity==1.16.1" - pip install "langfuse==2.59.7" - pip install "logfire==0.29.0" - pip install numpydoc - pip install traceloop-sdk==0.21.1 - pip install opentelemetry-api==1.25.0 - pip install opentelemetry-sdk==1.25.0 - pip install opentelemetry-exporter-otlp==1.25.0 - pip install openai==1.100.1 - pip install prisma==0.11.0 - pip install "detect_secrets==1.5.0" - pip install "httpx==0.24.1" - pip install "respx==0.22.0" - pip install fastapi - pip install "gunicorn==21.2.0" - pip install "anyio==4.2.0" - pip install "aiodynamo==23.10.1" - pip install "asyncio==3.4.3" - pip install "apscheduler==3.10.4" - pip install "PyGithub==1.59.1" - pip install argon2-cffi - pip install "pytest-mock==3.12.0" - pip install python-multipart - pip install google-cloud-aiplatform - pip install prometheus-client==0.20.0 - pip install "pydantic==2.10.2" - pip install "diskcache==5.6.1" - pip install "Pillow==10.3.0" - pip install "jsonschema==4.22.0" - pip install "pytest-xdist==3.6.1" - pip install "pytest-timeout==2.2.0" - pip install "websockets==13.1.0" + pip install "pytest==7.3.1" "pytest-retry==1.6.3" "pytest-asyncio==0.21.1" "pytest-cov==5.0.0" \ + "mypy==1.18.2" "google-generativeai==0.3.2" "google-cloud-aiplatform==1.43.0" pyarrow \ + "boto3==1.36.0" "aioboto3==13.4.0" langchain lunary==0.2.5 \ + "azure-identity==1.16.1" "langfuse==2.59.7" "logfire==0.29.0" numpydoc \ + traceloop-sdk==0.21.1 opentelemetry-api==1.25.0 opentelemetry-sdk==1.25.0 \ + opentelemetry-exporter-otlp==1.25.0 openai==1.100.1 prisma==0.11.0 \ + "detect_secrets==1.5.0" "httpx==0.24.1" "respx==0.22.0" fastapi \ + "gunicorn==21.2.0" "anyio==4.2.0" "aiodynamo==23.10.1" "asyncio==3.4.3" \ + "apscheduler==3.10.4" "PyGithub==1.59.1" argon2-cffi "pytest-mock==3.12.0" \ + python-multipart prometheus-client==0.20.0 "pydantic==2.10.2" \ + "diskcache==5.6.1" "Pillow==10.3.0" "jsonschema==4.22.0" \ + "pytest-xdist==3.6.1" "pytest-timeout==2.2.0" "websockets==13.1.0" pip install semantic_router --no-deps pip install aurelio_sdk --no-deps pip uninstall posthog -y @@ -283,50 +251,18 @@ jobs: command: | python -m pip install --upgrade pip python -m pip install -r .circleci/requirements.txt - pip install "pytest==7.3.1" - pip install "pytest-retry==1.6.3" - pip install "pytest-asyncio==0.21.1" - pip install "pytest-cov==5.0.0" - pip install "mypy==1.18.2" - pip install "google-generativeai==0.3.2" - pip install "google-cloud-aiplatform==1.43.0" - pip install pyarrow - pip install "boto3==1.36.0" - pip install "aioboto3==13.4.0" - pip install langchain - pip install lunary==0.2.5 - pip install "azure-identity==1.16.1" - pip install "langfuse==2.59.7" - pip install "logfire==0.29.0" - pip install numpydoc - pip install traceloop-sdk==0.21.1 - pip install opentelemetry-api==1.25.0 - pip install opentelemetry-sdk==1.25.0 - pip install opentelemetry-exporter-otlp==1.25.0 - pip install openai==1.100.1 - pip install prisma==0.11.0 - pip install "detect_secrets==1.5.0" - pip install "httpx==0.24.1" - pip install "respx==0.22.0" - pip install fastapi - pip install "gunicorn==21.2.0" - pip install "anyio==4.2.0" - pip install "aiodynamo==23.10.1" - pip install "asyncio==3.4.3" - pip install "apscheduler==3.10.4" - pip install "PyGithub==1.59.1" - pip install argon2-cffi - pip install "pytest-mock==3.12.0" - pip install python-multipart - pip install google-cloud-aiplatform - pip install prometheus-client==0.20.0 - pip install "pydantic==2.10.2" - pip install "diskcache==5.6.1" - pip install "Pillow==10.3.0" - pip install "jsonschema==4.22.0" - pip install "pytest-xdist==3.6.1" - pip install "pytest-timeout==2.2.0" - pip install "websockets==13.1.0" + pip install "pytest==7.3.1" "pytest-retry==1.6.3" "pytest-asyncio==0.21.1" "pytest-cov==5.0.0" \ + "mypy==1.18.2" "google-generativeai==0.3.2" "google-cloud-aiplatform==1.43.0" pyarrow \ + "boto3==1.36.0" "aioboto3==13.4.0" langchain lunary==0.2.5 \ + "azure-identity==1.16.1" "langfuse==2.59.7" "logfire==0.29.0" numpydoc \ + traceloop-sdk==0.21.1 opentelemetry-api==1.25.0 opentelemetry-sdk==1.25.0 \ + opentelemetry-exporter-otlp==1.25.0 openai==1.100.1 prisma==0.11.0 \ + "detect_secrets==1.5.0" "httpx==0.24.1" "respx==0.22.0" fastapi \ + "gunicorn==21.2.0" "anyio==4.2.0" "aiodynamo==23.10.1" "asyncio==3.4.3" \ + "apscheduler==3.10.4" "PyGithub==1.59.1" argon2-cffi "pytest-mock==3.12.0" \ + python-multipart prometheus-client==0.20.0 "pydantic==2.10.2" \ + "diskcache==5.6.1" "Pillow==10.3.0" "jsonschema==4.22.0" \ + "pytest-xdist==3.6.1" "pytest-timeout==2.2.0" "websockets==13.1.0" pip install semantic_router --no-deps pip install aurelio_sdk --no-deps pip uninstall posthog -y @@ -1345,14 +1281,7 @@ jobs: command: | python -m pip install --upgrade pip python -m pip install -r requirements.txt - pip install "pytest==7.3.1" - pip install "pytest-retry==1.6.3" - pip install "pytest-cov==5.0.0" - pip install "pytest-asyncio==0.21.1" - pip install "respx==0.22.0" - pip install "pytest-xdist==3.6.1" - pip install "pytest-timeout==2.2.0" - pip install "websockets" + pip install "pytest==7.3.1" "pytest-retry==1.6.3" "pytest-cov==5.0.0" "pytest-asyncio==0.21.1" "respx==0.22.0" "pytest-xdist==3.6.1" "pytest-timeout==2.2.0" "websockets" # Run pytest and generate JUnit XML report - run: name: Run realtime tests @@ -1622,18 +1551,14 @@ jobs: command: | python -m pip install --upgrade pip python -m pip install -r requirements.txt - pip install "pytest==7.3.1" - pip install "pytest-retry==1.6.3" - pip install "pytest-cov==5.0.0" - pip install "pytest-asyncio==0.21.1" - pip install "respx==0.22.0" + pip install "pytest==7.3.1" "pytest-retry==1.6.3" "pytest-cov==5.0.0" "pytest-asyncio==0.21.1" "respx==0.22.0" "pytest-xdist==3.6.1" # Run pytest and generate JUnit XML report - run: name: Run tests command: | pwd ls - python -m pytest -vv tests/ocr_tests --cov=litellm --cov-report=xml -x -s -v --junitxml=test-results/junit.xml --durations=5 + python -m pytest -vv tests/ocr_tests --cov=litellm --cov-report=xml -x -v --junitxml=test-results/junit.xml --durations=5 -n 4 no_output_timeout: 15m - run: name: Rename the coverage files @@ -1665,19 +1590,14 @@ jobs: command: | python -m pip install --upgrade pip python -m pip install -r requirements.txt - pip install "pytest==7.3.1" - pip install "pytest-retry==1.6.3" - pip install "pytest-cov==5.0.0" - pip install "pytest-asyncio==0.21.1" - pip install "respx==0.22.0" - pip install "pytest-xdist==3.6.1" + pip install "pytest==7.3.1" "pytest-retry==1.6.3" "pytest-cov==5.0.0" "pytest-asyncio==0.21.1" "respx==0.22.0" "pytest-xdist==3.6.1" # Run pytest and generate JUnit XML report - run: name: Run tests command: | pwd ls - python -m pytest -vv tests/search_tests --cov=litellm --cov-report=xml -x -s -v --junitxml=test-results/junit.xml --durations=5 -n 2 + python -m pytest -vv tests/search_tests --cov=litellm --cov-report=xml -x -v --junitxml=test-results/junit.xml --durations=5 -n 4 no_output_timeout: 15m - run: name: Rename the coverage files @@ -2051,19 +1971,14 @@ jobs: command: | python -m pip install --upgrade pip python -m pip install -r requirements.txt - pip install "pytest==7.3.1" - pip install "pytest-retry==1.6.3" - pip install "pytest-cov==5.0.0" - pip install "pytest-asyncio==0.21.1" - pip install "respx==0.22.0" - pip install "pytest-xdist==3.6.1" + pip install "pytest==7.3.1" "pytest-retry==1.6.3" "pytest-cov==5.0.0" "pytest-asyncio==0.21.1" "respx==0.22.0" "pytest-xdist==3.6.1" # Run pytest and generate JUnit XML report - run: name: Run tests command: | pwd ls - python -m pytest -vv tests/pass_through_unit_tests --cov=litellm --cov-report=xml -x -s -v --junitxml=test-results/junit.xml --durations=5 -n 2 + python -m pytest -vv tests/pass_through_unit_tests --cov=litellm --cov-report=xml -x -v --junitxml=test-results/junit.xml --durations=5 -n 4 no_output_timeout: 15m - run: name: Rename the coverage files @@ -3368,16 +3283,9 @@ jobs: - run: name: Install Dependencies command: | - pip install "pytest==7.3.1" - pip install "pytest-asyncio==0.21.1" - pip install aiohttp python -m pip install --upgrade pip - pip install "pytest==7.3.1" - pip install "pytest-retry==1.6.3" - pip install "pytest-mock==3.12.0" - pip install "pytest-asyncio==0.21.1" - pip install "mypy==1.18.2" - pip install apscheduler + pip install "pytest==7.3.1" "pytest-asyncio==0.21.1" "pytest-retry==1.6.3" \ + "pytest-mock==3.12.0" "mypy==1.18.2" aiohttp apscheduler - run: name: Build Docker image command: |