Stabilize CI disk usage and run Ollama E2E on arm64 (#2167)

* Stabilize CI disk usage and Ollama CPU backend

Place both uv cache and project environments on /mnt, and pin Ollama while disabling unstable AVX-512/AMX CPU backends before E2E inference on AMD64 runners.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ca3a8dc1-1c88-4c27-88e1-07f7e18b3e6b

* Harden Ollama CPU backend diagnostics

Log CPU metadata and enabled backends for ARM runners too, and leave previously disabled libraries untouched.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ca3a8dc1-1c88-4c27-88e1-07f7e18b3e6b

* fix(ci): stabilize uv and Ollama jobs

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 15a357e4-85bf-4b12-bca8-a9c3e3e45b2c

* refactor(ci): run Ollama inference on arm64

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 15a357e4-85bf-4b12-bca8-a9c3e3e45b2c

* chore(ci): finalize arm64 Ollama workflow

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ca3a8dc1-1c88-4c27-88e1-07f7e18b3e6b

* fix(ci): stabilize Ollama CPU backend selection

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ca3a8dc1-1c88-4c27-88e1-07f7e18b3e6b

* refactor(ci): keep Ollama E2E on arm64

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ca3a8dc1-1c88-4c27-88e1-07f7e18b3e6b

* fix(ci): reclaim uv cache before coverage

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ca3a8dc1-1c88-4c27-88e1-07f7e18b3e6b

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Sharon Hart
2026-07-16 10:08:56 +03:00
committed by GitHub
parent 0ac87d5abe
commit 517d13eee6
2 changed files with 41 additions and 26 deletions

View File

@@ -92,11 +92,12 @@ jobs:
env: env:
COVERAGE_THRESHOLD: 90 COVERAGE_THRESHOLD: 90
PRIMARY_PYTHON: '3.13' PRIMARY_PYTHON: '3.13'
# uv's wheel cache lives on the roomy /mnt disk (like the old # Co-locate uv's cache and environment so packages can be hardlinked instead
# POETRY_CACHE_DIR); it is persisted across runs by "Cache uv downloads". # of duplicated on the runner's single filesystem.
# UV_LINK_MODE=copy avoids cross-filesystem hardlink warnings.
UV_CACHE_DIR: /mnt/uv-cache UV_CACHE_DIR: /mnt/uv-cache
UV_LINK_MODE: copy UV_PROJECT_ENVIRONMENT: /mnt/uv-venv
UV_LINK_MODE: hardlink
PIP_NO_CACHE_DIR: '1'
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.0 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.0
@@ -112,12 +113,11 @@ jobs:
- name: Install uv - name: Install uv
run: python -m pip install uv==0.11.6 run: python -m pip install uv==0.11.6
- name: Prepare uv cache directory on /mnt - name: Prepare uv directories on /mnt
run: | run: |
# /mnt is root-owned, so create the cache dir and hand it to the # /mnt is root-owned, so hand both uv directories to the runner user.
# runner user before uv (or the cache restore) writes to it. sudo mkdir -p "$UV_CACHE_DIR" "$UV_PROJECT_ENVIRONMENT"
sudo mkdir -p "$UV_CACHE_DIR" sudo chown -R "$(id -u):$(id -g)" "$UV_CACHE_DIR" "$UV_PROJECT_ENVIRONMENT"
sudo chown -R "$(id -u):$(id -g)" "$UV_CACHE_DIR"
- name: Cache uv downloads - name: Cache uv downloads
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.0 uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.0
@@ -150,7 +150,8 @@ jobs:
# Override the locked PyPI presidio-analyzer with the in-repo copy so # Override the locked PyPI presidio-analyzer with the in-repo copy so
# tests run against local analyzer changes; later steps use # tests run against local analyzer changes; later steps use
# `uv run --no-sync` so uv won't revert this editable install. # `uv run --no-sync` so uv won't revert this editable install.
uv pip install -e ../presidio-analyzer/. uv pip install --python "$UV_PROJECT_ENVIRONMENT/bin/python" \
-e ../presidio-analyzer/.
- name: Download spaCy models - name: Download spaCy models
if: matrix.component.spacy-models != '' if: matrix.component.spacy-models != ''
@@ -160,11 +161,19 @@ jobs:
uv run --no-sync python -m spacy download $model uv run --no-sync python -m spacy download $model
done done
- name: Reclaim dependency cache space
run: |
# Dependencies are installed, so prune before coverage needs workspace space.
# Hardlinked environment files remain valid when their cache links are removed.
uv cache prune --ci
df -h / /mnt
du -sh "$UV_CACHE_DIR" "$UV_PROJECT_ENVIRONMENT"
- name: Run tests with coverage - name: Run tests with coverage
working-directory: ${{ matrix.component.path }} working-directory: ${{ matrix.component.path }}
run: | run: |
PACKAGE_NAME=$(echo "${{ matrix.component.path }}" | sed 's/-/_/g') PACKAGE_NAME=$(echo "${{ matrix.component.path }}" | sed 's/-/_/g')
uv run --no-sync pytest --cov=$PACKAGE_NAME --cov-report=xml:coverage.xml --cov-report=term --cov-report=html -vv --tb=short uv run --no-sync pytest --cov=$PACKAGE_NAME --cov-report=xml:coverage.xml --cov-report=term -vv --tb=short
if [ "${{ github.event_name }}" = "pull_request" ]; then if [ "${{ github.event_name }}" = "pull_request" ]; then
echo "Checking PR difference coverage (>= ${{ env.COVERAGE_THRESHOLD }}%) with diff-cover..." echo "Checking PR difference coverage (>= ${{ env.COVERAGE_THRESHOLD }}%) with diff-cover..."
@@ -195,12 +204,6 @@ jobs:
pip install --require-hashes -r ${{ github.workspace }}/.github/pipelines/requirements-build.txt pip install --require-hashes -r ${{ github.workspace }}/.github/pipelines/requirements-build.txt
python -m build --wheel python -m build --wheel
- name: Minimize uv cache
if: always()
run: |
# Trim the persisted cache (recommended for CI by the uv docs).
uv cache prune --ci
build-platform-images: build-platform-images:
name: Build ${{ matrix.image }} (${{ matrix.platform }}) name: Build ${{ matrix.image }} (${{ matrix.platform }})
runs-on: ${{ matrix.runner }} runs-on: ${{ matrix.runner }}
@@ -337,16 +340,22 @@ jobs:
- name: Wait for services to be ready - name: Wait for services to be ready
run: sleep 60 run: sleep 60
- name: Download Ollama model for Ollama LangExtract recognizer tests - name: Download Ollama model for LangExtract recognizer tests
if: matrix.platform == 'linux/arm64'
run: | run: |
docker exec $(docker ps -qf "name=ollama") ollama pull qwen2.5:1.5b ollama_container="$(docker compose -f docker-compose.yml ps -q ollama)"
docker exec $(docker ps -qf "name=ollama") ollama run qwen2.5:1.5b docker exec "$ollama_container" ollama pull qwen2.5:1.5b
docker exec "$ollama_container" ollama run qwen2.5:1.5b
- name: Run E2E tests - name: Run E2E tests
working-directory: e2e-tests working-directory: e2e-tests
run: | run: |
source env/bin/activate source env/bin/activate
pytest -vv --tb=short pytest_args=()
if [ "${{ matrix.platform }}" != "linux/arm64" ]; then
pytest_args=(-k "not ollama")
fi
pytest -vv --tb=short "${pytest_args[@]}"
- name: Capture Docker logs on failure (${{ matrix.platform }}) - name: Capture Docker logs on failure (${{ matrix.platform }})
if: failure() if: failure()
@@ -424,16 +433,22 @@ jobs:
- name: Wait for services to be ready - name: Wait for services to be ready
run: sleep 60 run: sleep 60
- name: Download Ollama model for Ollama LangExtract recognizer tests - name: Download Ollama model for LangExtract recognizer tests
if: matrix.platform == 'linux/arm64'
run: | run: |
docker exec $(docker ps -qf "name=ollama") ollama pull qwen2.5:1.5b ollama_container="$(docker compose -f docker-compose.yml ps -q ollama)"
docker exec $(docker ps -qf "name=ollama") ollama run qwen2.5:1.5b docker exec "$ollama_container" ollama pull qwen2.5:1.5b
docker exec "$ollama_container" ollama run qwen2.5:1.5b
- name: Run E2E tests - name: Run E2E tests
working-directory: e2e-tests working-directory: e2e-tests
run: | run: |
source env/bin/activate source env/bin/activate
pytest -vv --tb=short pytest_args=()
if [ "${{ matrix.platform }}" != "linux/arm64" ]; then
pytest_args=(-k "not ollama")
fi
pytest -vv --tb=short "${pytest_args[@]}"
- name: Capture Docker logs on failure - name: Capture Docker logs on failure
if: failure() if: failure()

View File

@@ -1,6 +1,6 @@
services: services:
ollama: ollama:
image: ollama/ollama:latest image: ollama/ollama:0.32.0@sha256:57f573b47f1f71ebb445789f279fe3e596a8beab182f7cf486db9205bad87c5a
ports: ports:
- "127.0.0.1:11434:11434" # or "127.0.0.1:11435:11434" - "127.0.0.1:11434:11434" # or "127.0.0.1:11435:11434"
volumes: volumes: