ci: isolate test backend install in venv
Release / test-backend (push) Successful in 2m1s
Release / release (push) Successful in 2m3s

The persistent Gitea runner caches the setup-python toolcache between
runs. A previous run that produced wheels with broken metadata (no
Version field in METADATA) left a notify-bridge-server install with
no RECORD file in site-packages. The next run hits:

  Found existing installation: notify-bridge-server None
  error: uninstall-no-record-file

pip refuses to uninstall (no RECORD) and refuses to overlay (it tries
to uninstall first). Switching from a system-pip install into the
toolcache to an isolated /tmp/venv per run sidesteps the leak — each
CI run starts with empty site-packages.

Same change to build.yml and release.yml so the pre-merge gate and
the release-gate both run the same setup.
This commit is contained in:
2026-05-16 18:33:41 +03:00
parent 66f152ef2c
commit d7c48b06ee
2 changed files with 23 additions and 16 deletions
+13 -9
View File
@@ -50,19 +50,23 @@ jobs:
# Editable installs of packages/core + packages/server are extremely slow # Editable installs of packages/core + packages/server are extremely slow
# on the hosted runner — measured 4-6x slower than building wheels first # on the hosted runner — measured 4-6x slower than building wheels first
# because hatchling's editable hook re-resolves on every collection. We # because hatchling's editable hook re-resolves on every collection. We
# build wheels once, then install them (and only the test deps) into a # build wheels once into an isolated venv, then install them (and only
# plain venv. The wheels themselves are NOT cached because their hashes # the test deps). The venv isolation also prevents broken-wheel installs
# depend on every file under packages/ — invalidates on basically every # from leaking dist-info across runs on the persistent Gitea runner
# PR. Pip's HTTP cache for the test deps is enough. # (pip can't uninstall a wheel that landed without a RECORD file). The
- name: Build wheels # wheels themselves are NOT cached because their hashes depend on every
# file under packages/ — invalidates on basically every PR. Pip's HTTP
# cache for the test deps is enough.
- name: Build wheels in isolated venv
run: | run: |
python -m pip install --upgrade pip build python -m venv /tmp/venv
/tmp/venv/bin/pip install --upgrade pip build
mkdir -p /tmp/wheels mkdir -p /tmp/wheels
pip wheel --no-deps -w /tmp/wheels packages/core packages/server /tmp/venv/bin/pip wheel --no-deps -w /tmp/wheels packages/core packages/server
- name: Install backend + test deps - name: Install backend + test deps
run: | run: |
pip install /tmp/wheels/*.whl pytest pytest-asyncio httpx aioresponses prometheus_client /tmp/venv/bin/pip install /tmp/wheels/*.whl pytest pytest-asyncio httpx aioresponses prometheus_client
- name: Run pytest - name: Run pytest
env: env:
@@ -72,7 +76,7 @@ jobs:
NOTIFY_BRIDGE_CORS_ALLOWED_ORIGINS: "http://localhost:8420" NOTIFY_BRIDGE_CORS_ALLOWED_ORIGINS: "http://localhost:8420"
run: | run: |
cd packages/server cd packages/server
pytest tests --tb=short /tmp/venv/bin/pytest tests --tb=short
build-image: build-image:
if: ${{ !startsWith(gitea.event.head_commit.message, 'chore: release v') }} if: ${{ !startsWith(gitea.event.head_commit.message, 'chore: release v') }}
+10 -7
View File
@@ -20,17 +20,20 @@ jobs:
with: with:
python-version: "3.12" python-version: "3.12"
# Same wheel-first strategy as build.yml — editable install is too slow # Wheel-first strategy in an isolated venv — editable install is too slow,
# on the hosted runner. # and a plain pip install into the toolcache Python leaks state across
- name: Build wheels # runs on the persistent Gitea runner (previous broken wheel installs
# leave dist-info dirs that pip can't uninstall: "uninstall-no-record-file").
- name: Build wheels in isolated venv
run: | run: |
python -m pip install --upgrade pip build python -m venv /tmp/venv
/tmp/venv/bin/pip install --upgrade pip build
mkdir -p /tmp/wheels mkdir -p /tmp/wheels
pip wheel --no-deps -w /tmp/wheels packages/core packages/server /tmp/venv/bin/pip wheel --no-deps -w /tmp/wheels packages/core packages/server
- name: Install backend + test deps - name: Install backend + test deps
run: | run: |
pip install /tmp/wheels/*.whl pytest pytest-asyncio httpx aioresponses prometheus_client /tmp/venv/bin/pip install /tmp/wheels/*.whl pytest pytest-asyncio httpx aioresponses prometheus_client
- name: Run pytest - name: Run pytest
env: env:
@@ -40,7 +43,7 @@ jobs:
NOTIFY_BRIDGE_CORS_ALLOWED_ORIGINS: "http://localhost:8420" NOTIFY_BRIDGE_CORS_ALLOWED_ORIGINS: "http://localhost:8420"
run: | run: |
cd packages/server cd packages/server
pytest tests --tb=short /tmp/venv/bin/pytest tests --tb=short
release: release:
needs: [test-backend] needs: [test-backend]