From 895dda631c8ba01ad37e9aaef6c6c032b8a3e992 Mon Sep 17 00:00:00 2001 From: IgorSusmelj Date: Mon, 27 Oct 2025 17:43:47 +0100 Subject: [PATCH 1/3] Split up end2end frontend tests to speed them up --- .github/workflows/end2end_test.yml | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/.github/workflows/end2end_test.yml b/.github/workflows/end2end_test.yml index 93957f123..4ee654d69 100644 --- a/.github/workflows/end2end_test.yml +++ b/.github/workflows/end2end_test.yml @@ -20,7 +20,16 @@ env: jobs: end-to-end-test: - name: End2End Test + name: End2End Test (shard ${{ matrix.shard.index }}/${{ matrix.shard.total }}) + strategy: + fail-fast: false + matrix: + # Run each Playwright shard on its own runner to split the suite by file. + shard: + - index: 1 + total: 2 + - index: 2 + total: 2 runs-on: ubuntu-latest steps: - name: Checkout Code @@ -181,7 +190,12 @@ jobs: - name: Run end-to-end tests for indexed dataset if: steps.cache-e2e-tests.outputs.cache-hit != 'true' working-directory: lightly_studio_view - run: npx playwright test --reporter=html --trace=on + run: > + # Shard Playwright specs across runners for parallel execution. + npx playwright test + --reporter=html + --trace=on + --shard=${{ matrix.shard.index }}/${{ matrix.shard.total }} timeout-minutes: 10 ### Cleanup steps for the workflow ### @@ -196,7 +210,8 @@ jobs: uses: actions/upload-artifact@v4 if: failure() with: - name: Upload Playwright Report + # Each shard uploads its own Playwright HTML report. + name: Playwright Report shard ${{ matrix.shard.index }}-${{ matrix.shard.total }} path: lightly_studio_view/playwright-report retention-days: 5 From b568e3b8ae9ca59ba0dbf3fde30c716d7f4623b9 Mon Sep 17 00:00:00 2001 From: IgorSusmelj Date: Mon, 27 Oct 2025 19:00:32 +0100 Subject: [PATCH 2/3] Update tests --- .github/workflows/end2end_test.yml | 67 +++++++++++++----------------- 1 file changed, 28 insertions(+), 39 deletions(-) diff --git a/.github/workflows/end2end_test.yml b/.github/workflows/end2end_test.yml index 4ee654d69..d8152dbf9 100644 --- a/.github/workflows/end2end_test.yml +++ b/.github/workflows/end2end_test.yml @@ -61,29 +61,13 @@ jobs: path: lightly_studio/datasets/coco-128 key: coco-example-dataset - - name: Cache lightly_studio app build - id: cache-python-build - uses: actions/cache@v4 - with: - path: lightly_studio/dist - key: python-build-${{ hashFiles('lightly_studio/src/**', 'lightly_studio/pyproject.toml', 'lightly_studio_view/src/**', 'lightly_studio_view/public/**', 'lightly_studio_view/package.json', 'lightly_studio_view/package-lock.json') }} - - - name: Cache e2e-tests - id: cache-e2e-tests - uses: actions/cache@v4 - with: - path: lightly_studio_view/playwright-report - key: python-build-${{ hashFiles('lightly_studio/e2e-tests/index_dataset_for_end2end_ui_tests.py', 'lightly_studio/src/**', 'lightly_studio/pyproject.toml', 'lightly_studio_view/e2e/**', 'lightly_studio_view/src/**', 'lightly_studio_view/public/**', 'lightly_studio_view/package.json', 'lightly_studio_view/package-lock.json') }} - ### Setup steps for the workflow ### - name: Set Up Python - if: steps.cache-python-build.outputs.cache-hit != 'true' || steps.cache-e2e-tests.outputs.cache-hit != 'true' uses: actions/setup-python@v5 with: python-version: "3.8" - name: Set Up uv - if: steps.cache-python-build.outputs.cache-hit != 'true' || steps.cache-e2e-tests.outputs.cache-hit != 'true' uses: astral-sh/setup-uv@v6 with: version: "0.8.17" @@ -96,8 +80,8 @@ jobs: cache: 'npm' cache-dependency-path: lightly_studio_view/package-lock.json - - name: Install dependencies - if: steps.cache-e2e-tests.outputs.cache-hit != 'true' || steps.cache-python-build.outputs.cache-hit != 'true' + - name: Install npm dependencies + if: steps.cache-ui-build.outputs.cache-hit != 'true' working-directory: lightly_studio_view run: npm ci @@ -111,13 +95,12 @@ jobs: # Always ensure system packages for browsers are present on Ubuntu - name: Install Playwright system dependencies - if: steps.cache-e2e-tests.outputs.cache-hit != 'true' working-directory: lightly_studio_view run: npx playwright install-deps chromium # Only download browser binaries when cache misses; otherwise reuse cache - name: Install Playwright browsers - if: steps.cache-e2e-tests.outputs.cache-hit != 'true' && steps.cache-playwright-browsers.outputs.cache-hit != 'true' + if: steps.cache-playwright-browsers.outputs.cache-hit != 'true' working-directory: lightly_studio_view run: npx playwright install chromium @@ -128,33 +111,26 @@ jobs: git clone --depth=1 https://github.com/lightly-ai/dataset_examples_studio.git tmp_dataset_repo cp -r tmp_dataset_repo/coco_subset_128_images/* lightly_studio/datasets/coco-128/ rm -rf tmp_dataset_repo - + - name: Install lightly_studio python dependencies - if: steps.cache-python-build.outputs.cache-hit != 'true' working-directory: lightly_studio run: make install-optional-deps - - name: Export schema from backend - if: steps.cache-python-build.outputs.cache-hit != 'true' - working-directory: lightly_studio - run: make export-schema - - ### Buildging and steps for the workflow ### + ### Building steps for the workflow ### - name: Build the ui application - if: steps.cache-ui-build.outputs.cache-hit != 'true' || steps.cache-python-build.outputs.cache-hit != 'true' + if: steps.cache-ui-build.outputs.cache-hit != 'true' working-directory: lightly_studio_view run: | rm -rf build npm run build - name: Copy the built ui app to lightly_studio source folder - if: steps.cache-ui-build.outputs.cache-hit != 'true' || steps.cache-python-build.outputs.cache-hit != 'true' + if: steps.cache-ui-build.outputs.cache-hit != 'true' run: | rm -rf lightly_studio/src/lightly_studio/dist_lightly_studio_view_app cp -r lightly_studio_view/build/ lightly_studio/src/lightly_studio/dist_lightly_studio_view_app - - name: Index dataset with using lightly_studio pypi package - if: steps.cache-e2e-tests.outputs.cache-hit != 'true' + - name: Start lightly_studio server with test dataset working-directory: lightly_studio # TODO(Michal, 10/2025): Starting up the server redownloads the embedding model. Consider caching it. run: | @@ -163,14 +139,13 @@ jobs: id: server - name: Wait for the server to start - if: steps.cache-e2e-tests.outputs.cache-hit != 'true' timeout-minutes: 5 run: | echo "Waiting for the server to become available..." timeout=360 elapsed=0 interval=5 - + while [ $elapsed -lt $timeout ]; do if curl -s -f ${E2E_BASE_URL}/healthz > /dev/null 2>&1; then echo "✅ Server is up and running after ${elapsed} seconds!" @@ -180,7 +155,7 @@ jobs: sleep $interval elapsed=$((elapsed + interval)) done - + if [ $elapsed -ge $timeout ]; then echo "❌ Timed out waiting for server to become available" exit 1 @@ -188,7 +163,6 @@ jobs: ### Running end-to-end tests ### - name: Run end-to-end tests for indexed dataset - if: steps.cache-e2e-tests.outputs.cache-hit != 'true' working-directory: lightly_studio_view run: > # Shard Playwright specs across runners for parallel execution. @@ -200,7 +174,7 @@ jobs: ### Cleanup steps for the workflow ### - name: Show server logs after failure - if: failure() && steps.cache-e2e-tests.outputs.cache-hit != 'true' + if: failure() working-directory: lightly_studio run: | echo "Server logs:" @@ -211,11 +185,26 @@ jobs: if: failure() with: # Each shard uploads its own Playwright HTML report. - name: Playwright Report shard ${{ matrix.shard.index }}-${{ matrix.shard.total }} + name: playwright-report-shard-${{ matrix.shard.index }}-of-${{ matrix.shard.total }} path: lightly_studio_view/playwright-report retention-days: 5 - name: Stop lightly_studio application running in background - if: always() && steps.cache-e2e-tests.outputs.cache-hit != 'true' + if: always() run: | kill ${{ env.SERVER_PID }} || true + + # Summary job that reports overall test status + end-to-end-test-summary: + name: End2End Test + needs: end-to-end-test + runs-on: ubuntu-latest + if: always() + steps: + - name: Check test results + run: | + if [[ "${{ needs.end-to-end-test.result }}" != "success" ]]; then + echo "❌ One or more test shards failed" + exit 1 + fi + echo "✅ All end-to-end test shards passed successfully" From eed9561892874c2e093b9a9544889583aefe1d98 Mon Sep 17 00:00:00 2001 From: IgorSusmelj Date: Mon, 27 Oct 2025 19:18:24 +0100 Subject: [PATCH 3/3] Address bad comment and move up --- .github/workflows/end2end_test.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/end2end_test.yml b/.github/workflows/end2end_test.yml index d8152dbf9..4798a6ed4 100644 --- a/.github/workflows/end2end_test.yml +++ b/.github/workflows/end2end_test.yml @@ -80,8 +80,9 @@ jobs: cache: 'npm' cache-dependency-path: lightly_studio_view/package-lock.json + # Always install npm dependencies (needed for npx playwright commands) + # The setup-node npm cache makes this fast even on repeated runs - name: Install npm dependencies - if: steps.cache-ui-build.outputs.cache-hit != 'true' working-directory: lightly_studio_view run: npm ci @@ -162,14 +163,14 @@ jobs: fi ### Running end-to-end tests ### + # Shard Playwright specs across runners for parallel execution. - name: Run end-to-end tests for indexed dataset working-directory: lightly_studio_view - run: > - # Shard Playwright specs across runners for parallel execution. - npx playwright test - --reporter=html - --trace=on - --shard=${{ matrix.shard.index }}/${{ matrix.shard.total }} + run: | + npx playwright test \ + --reporter=html \ + --trace=on \ + --shard=${{ matrix.shard.index }}/${{ matrix.shard.total }} timeout-minutes: 10 ### Cleanup steps for the workflow ###