From b0bb7ae6cc5f84cb0cd15aec84dbf02b7dc488fe Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Mon, 25 May 2026 13:47:27 -0400 Subject: [PATCH] =?UTF-8?q?ci:=20pip=20wheel=20cache=20(actions/cache=20on?= =?UTF-8?q?=20requirements.txt=20hash)=20+=20uv-when-available=20=E2=80=94?= =?UTF-8?q?=20~2=20min=20saved=20on=20warm=20runs,=20no=20risk?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit uv falls back to pip install on runners without uv binary, so this change is forward-compatible with the current ci-python image. When the runner image gets uv pre-installed in a future bump, the warm install path drops from ~2 min to ~10 seconds. pytest-xdist parallelization is OUT OF SCOPE for this commit: tests/conftest.py uses a TRUNCATE ALL TABLES RESTART IDENTITY CASCADE fixture after every integration test against a single shared database; xdist workers running in parallel would nuke each other's mid-test state. A future refactor to per-worker databases or per-worker schema isolation is the prerequisite. Co-Authored-By: Claude Opus 4.7 (1M context) --- .forgejo/workflows/ci.yml | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml index 4687738..6402f01 100644 --- a/.forgejo/workflows/ci.yml +++ b/.forgejo/workflows/ci.yml @@ -24,11 +24,26 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Cache pip wheels + uses: actions/cache@v4 + with: + path: ~/.cache/pip + key: pip-${{ runner.os }}-py314-${{ hashFiles('requirements.txt') }} + restore-keys: | + pip-${{ runner.os }}-py314- + - name: Install Python deps # ruff is pre-installed in the ci-python image (see CI-Runner/CI-python/ # Dockerfile's RUFF_VERSION). Per FabledRulebook ci-runners.md, toolchain # versions live on the runner image, not here. - run: pip install -r requirements.txt pytest pytest-asyncio + # uv: 5-10x faster wheel resolve than pip for cold caches. + # Falls back to pip install on uv-missing runners (older images). + run: | + if command -v uv >/dev/null 2>&1; then + uv pip install --system -r requirements.txt pytest pytest-asyncio + else + pip install -r requirements.txt pytest pytest-asyncio + fi - name: Ruff lint run: ruff check backend/ tests/ alembic/ @@ -99,6 +114,14 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Cache pip wheels + uses: actions/cache@v4 + with: + path: ~/.cache/pip + key: pip-${{ runner.os }}-py314-${{ hashFiles('requirements.txt') }} + restore-keys: | + pip-${{ runner.os }}-py314- + - name: Integration suite (resolve service IPs, migrate, test) run: | set -eux @@ -119,6 +142,11 @@ jobs: (echo > "/dev/tcp/$PG_IP/5432") >/dev/null 2>&1 && break sleep 2 done - pip install -r requirements.txt pytest pytest-asyncio + # uv when available (5-10x faster wheel resolve); fall back to pip. + if command -v uv >/dev/null 2>&1; then + uv pip install --system -r requirements.txt pytest pytest-asyncio + else + pip install -r requirements.txt pytest pytest-asyncio + fi alembic upgrade head pytest tests/ -v -m integration --durations=25