From 9287145c2800370d41f201e47cceb66984f61adf Mon Sep 17 00:00:00 2001 From: Greyson LaLonde Date: Wed, 10 Sep 2025 14:12:32 -0400 Subject: [PATCH] feat: add test duration caching for optimized pytest-split --- .github/workflows/tests.yml | 17 +++++ .github/workflows/update-test-durations.yml | 70 +++++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 .github/workflows/update-test-durations.yml diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a5b860c9e..08ba3bbd7 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -45,14 +45,31 @@ jobs: - name: Install the project run: uv sync --all-groups --all-extras + - name: Restore test durations + uses: actions/cache/restore@v4 + with: + path: .test_durations_py${{ matrix.python-version }} + key: test-durations-py${{ matrix.python-version }}- + restore-keys: | + test-durations-py${{ matrix.python-version }}- + - name: Run tests (group ${{ matrix.group }} of 8) run: | + if [ -f .test_durations_py${{ matrix.python-version }} ]; then + echo "Using cached test durations for optimal splitting" + DURATIONS_ARG="--durations-path=.test_durations_py${{ matrix.python-version }}" + else + echo "No cached durations found, tests will be split evenly" + DURATIONS_ARG="" + fi + uv run pytest \ --block-network \ --timeout=30 \ -vv \ --splits 8 \ --group ${{ matrix.group }} \ + $DURATIONS_ARG \ --durations=10 \ -n auto \ --maxfail=3 diff --git a/.github/workflows/update-test-durations.yml b/.github/workflows/update-test-durations.yml new file mode 100644 index 000000000..5f12a648a --- /dev/null +++ b/.github/workflows/update-test-durations.yml @@ -0,0 +1,70 @@ +name: Update Test Durations + +on: + push: + branches: + - main + paths: + - 'tests/**/*.py' + workflow_dispatch: + +permissions: + contents: read + +jobs: + update-durations: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ['3.10', '3.11', '3.12', '3.13'] + env: + OPENAI_API_KEY: fake-api-key + PYTHONUNBUFFERED: 1 + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Restore global uv cache + id: cache-restore + uses: actions/cache/restore@v4 + with: + path: | + ~/.cache/uv + ~/.local/share/uv + .venv + key: uv-main-py${{ matrix.python-version }}-${{ hashFiles('uv.lock') }} + restore-keys: | + uv-main-py${{ matrix.python-version }}- + + - name: Install uv + uses: astral-sh/setup-uv@v6 + with: + version: "0.8.4" + python-version: ${{ matrix.python-version }} + enable-cache: false + + - name: Install the project + run: uv sync --all-groups --all-extras + + - name: Run all tests and store durations + run: | + uv run pytest --store-durations --durations-path=.test_durations_py${{ matrix.python-version }} -n auto + continue-on-error: true + + - name: Save durations to cache + if: always() + uses: actions/cache/save@v4 + with: + path: .test_durations_py${{ matrix.python-version }} + key: test-durations-py${{ matrix.python-version }}-${{ github.sha }} + + - name: Save uv caches + if: steps.cache-restore.outputs.cache-hit != 'true' + uses: actions/cache/save@v4 + with: + path: | + ~/.cache/uv + ~/.local/share/uv + .venv + key: uv-main-py${{ matrix.python-version }}-${{ hashFiles('uv.lock') }} \ No newline at end of file