fix(test): throw on legacy test signature; case-insensitive PSModuleP… #9562
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Test | |
| on: | |
| push: | |
| branches: | |
| - master | |
| - release/v* | |
| pull_request: | |
| workflow_call: | |
| inputs: | |
| rebuild-docker-images-call: | |
| description: "Force rebuild of Docker images?" | |
| required: false | |
| type: boolean | |
| default: false | |
| workflow_dispatch: | |
| inputs: | |
| rebuild-docker-images: | |
| description: "Force rebuild of Docker images?" | |
| required: false | |
| type: boolean | |
| default: false | |
| reset-vitest-smart-cache: | |
| description: "Reset Vitest smart cache (will cause all tests to run without caching for this run, then cache will be repopulated for future runs)" | |
| required: false | |
| type: boolean | |
| default: false | |
| collect-coverage: | |
| description: "Collect v8 code coverage during the run and publish a merged coverage report (adds per-shard overhead; off by default)" | |
| required: false | |
| type: boolean | |
| default: true | |
| # concurrency: | |
| # group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} | |
| # cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| env: | |
| TEST_IMAGE_NODE_MAJOR_VERSION: 22 | |
| jobs: | |
| check-if-docker-build: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| outputs: | |
| force-docker-build: ${{ steps.changes.outputs.docker == 'true' || steps.changes.outputs.workflow == 'true' }} | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| - name: Determine if Dockerfiles changed | |
| uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1 | |
| id: changes | |
| with: | |
| filters: | | |
| docker: | |
| - 'docker/*/Dockerfile' | |
| - 'docker/build.sh' | |
| workflow: | |
| - '.github/workflows/docker-build.yml' | |
| run-docker-build: | |
| needs: check-if-docker-build | |
| if: | | |
| always() && | |
| (needs.check-if-docker-build.outputs.force-docker-build == 'true' || | |
| inputs.rebuild-docker-images == 'true' || inputs.rebuild-docker-images == true || | |
| inputs.rebuild-docker-images-call == 'true' || inputs.rebuild-docker-images-call == true) | |
| uses: ./.github/workflows/docker-build.yml | |
| # ------------------------- | |
| # Linting + Shard Planning (unified job outputting map for all platforms) | |
| # ------------------------- | |
| validate-and-shard: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| outputs: | |
| linux: ${{ steps.plan.outputs.linux }} | |
| windows: ${{ steps.plan.outputs.windows }} | |
| macos: ${{ steps.plan.outputs.macos }} | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: Setup Tests | |
| uses: ./.github/actions/pretest | |
| with: | |
| cache-key: v-39.8.10-linux-electron | |
| cache-path: ~/.cache/electron | |
| reset-vitest-smart-cache: ${{ inputs.reset-vitest-smart-cache }} | |
| collect-coverage: ${{ inputs.collect-coverage }} | |
| - name: Validate files | |
| run: pnpm ci:validate | |
| - name: Lint files | |
| run: pnpm lint | |
| - name: Output shard plan | |
| run: pnpm ci:test:count | |
| - id: plan | |
| run: | | |
| # Get shard counts for all platforms as JSON | |
| SHARD_JSON=$(pnpm --silent ci:test:count | tail -n1) | |
| # Extract individual platform arrays | |
| LINUX_SHARDS=$(echo "$SHARD_JSON" | jq -c '.linux') | |
| WINDOWS_SHARDS=$(echo "$SHARD_JSON" | jq -c '.win32') | |
| MACOS_SHARDS=$(echo "$SHARD_JSON" | jq -c '.darwin') | |
| # Set outputs | |
| echo "linux=$LINUX_SHARDS" >> $GITHUB_OUTPUT | |
| echo "windows=$WINDOWS_SHARDS" >> $GITHUB_OUTPUT | |
| echo "macos=$MACOS_SHARDS" >> $GITHUB_OUTPUT | |
| # Debug output | |
| echo "Planned shards:" | |
| echo " Linux: $LINUX_SHARDS" | |
| echo " Windows: $WINDOWS_SHARDS" | |
| echo " macOS: $MACOS_SHARDS" | |
| # ------------------------- | |
| # Unified Test Jobs (one per OS, sharding within) | |
| # ------------------------- | |
| test-linux: | |
| name: Test Linux (Shard ${{ matrix.shard }}) | |
| needs: [check-if-docker-build, run-docker-build, validate-and-shard] | |
| if: | | |
| always() && | |
| needs.check-if-docker-build.result == 'success' && | |
| (needs.run-docker-build.result == 'success' || needs.run-docker-build.result == 'skipped') | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| shard: ${{ fromJson(needs.validate-and-shard.outputs.linux) }} | |
| include: | |
| - platform: linux | |
| runner: ubuntu-latest | |
| cache-path: ~/.cache/electron | |
| cache-key: v-39.8.10-linux-electron | |
| runs-on: ${{ matrix.runner }} | |
| timeout-minutes: 60 | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| fetch-depth: 2 | |
| persist-credentials: false | |
| - name: Cleanup runner | |
| uses: ./.github/actions/cleanup-runner | |
| - name: Setup Tests | |
| uses: ./.github/actions/pretest | |
| with: | |
| cache-path: ${{ matrix.cache-path }} | |
| cache-key: ${{ matrix.cache-key }} | |
| reset-vitest-smart-cache: ${{ inputs.reset-vitest-smart-cache }} | |
| collect-coverage: ${{ inputs.collect-coverage }} | |
| - name: Download test-runner if exists | |
| if: needs.run-docker-build.result == 'success' | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: electron-builder-all-${{ env.TEST_IMAGE_NODE_MAJOR_VERSION }} | |
| path: ${{ runner.temp }} | |
| - name: Load test runner image if needed | |
| if: needs.run-docker-build.result == 'success' | |
| run: | | |
| docker image load --input ${{ runner.temp }}/electron-builder-all-${{ env.TEST_IMAGE_NODE_MAJOR_VERSION }}.tar | |
| docker image ls -a | |
| - name: Write Docker secrets env file | |
| run: | | |
| printf 'CSC_KEY_PASSWORD=%s\n' "$CSC_KEY_PASSWORD_SECRET" > "${{ runner.temp }}/docker-secrets.env" | |
| chmod 600 "${{ runner.temp }}/docker-secrets.env" | |
| env: | |
| CSC_KEY_PASSWORD_SECRET: ${{ secrets.WIN_CSC_KEY_PASSWORD }} | |
| - name: Run shard in docker | |
| run: | | |
| echo $TEST_RUNNER_IMAGE_TAG | |
| pnpm test:linux | |
| env: | |
| ADDITIONAL_DOCKER_ARGS: "--env-file ${{ runner.temp }}/docker-secrets.env -e VITEST_SHARD_INDEX=${{ matrix.shard }} -e VITEST_SMART_CACHE_FILE=./test/vitest-scripts/vitest-config/_vitest-smart-cache.json -e RESET_VITEST_SHARD_CACHE=${{ inputs.reset-vitest-smart-cache }} -e VITEST_COVERAGE=${{ inputs.collect-coverage }}" | |
| TEST_RUNNER_IMAGE_TAG: electronuserland/builder:${{ env.TEST_IMAGE_NODE_MAJOR_VERSION }}-wine-mono | |
| - name: Upload test artifacts | |
| if: always() | |
| uses: ./.github/actions/upload-test-artifacts | |
| with: | |
| name: ${{ matrix.platform }}-${{ matrix.shard }} | |
| test-windows: | |
| name: Test Windows (Shard ${{ matrix.shard }}) | |
| needs: validate-and-shard | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| shard: ${{ fromJson(needs.validate-and-shard.outputs.windows) }} | |
| include: | |
| - platform: windows | |
| runner: windows-latest | |
| cache-path: ~\AppData\Local\electron\Cache | |
| cache-key: v-39.8.10-windows-electron | |
| runs-on: ${{ matrix.runner }} | |
| timeout-minutes: 60 | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: Setup Tests | |
| uses: ./.github/actions/pretest | |
| with: | |
| cache-key: ${{ matrix.cache-key }} | |
| cache-path: ${{ matrix.cache-path }} | |
| reset-vitest-smart-cache: ${{ inputs.reset-vitest-smart-cache }} | |
| collect-coverage: ${{ inputs.collect-coverage }} | |
| - name: Pre-initialize NuGet IsolatedStorage | |
| shell: pwsh | |
| run: | | |
| # NuGet 2.x (bundled in the Squirrel.Windows vendor) uses IsolatedStorageFile.GetUserStoreForAssembly() | |
| # for user settings. On fresh Windows CI runners this directory may not exist, causing the first | |
| # NuGet invocation to fail with IsolatedStorageException (0x80131468). Pre-creating it lets | |
| # the CLR create its hashed subdirectory without error. | |
| New-Item -ItemType Directory -Force -Path "$env:LOCALAPPDATA\IsolatedStorage" | Out-Null | |
| - name: Run shard | |
| run: pnpm ci:test | |
| env: | |
| CSC_KEY_PASSWORD: ${{ secrets.WIN_CSC_KEY_PASSWORD }} | |
| VITEST_SHARD_INDEX: ${{ matrix.shard }} | |
| VITEST_SMART_CACHE_FILE: ${{ github.workspace }}\test\vitest-scripts\vitest-config\_vitest-smart-cache.json | |
| - name: Upload test artifacts | |
| if: always() | |
| uses: ./.github/actions/upload-test-artifacts | |
| with: | |
| name: ${{ matrix.platform }}-${{ matrix.shard }} | |
| test-macos: | |
| name: Test macOS (Shard ${{ matrix.shard }}) | |
| needs: validate-and-shard | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| shard: ${{ fromJson(needs.validate-and-shard.outputs.macos) }} | |
| include: | |
| - platform: macos | |
| runner: macos-26 | |
| cache-path: ~/Library/Caches/electron | |
| cache-key: v-39.8.10-macos-electron | |
| runs-on: ${{ matrix.runner }} | |
| timeout-minutes: 60 | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: Setup Tests | |
| uses: ./.github/actions/pretest | |
| with: | |
| cache-path: ${{ matrix.cache-path }} | |
| cache-key: ${{ matrix.cache-key }} | |
| reset-vitest-smart-cache: ${{ inputs.reset-vitest-smart-cache }} | |
| collect-coverage: ${{ inputs.collect-coverage }} | |
| - name: Silence the damn GH runner warnings (temporary until GH updates their runners to a newer macOS base toolset bundle) | |
| run: | | |
| brew uninstall bicep || true # Not actually a dependency, but GH runners have it preinstalled and it prints annoying warnings about missing .NET workloads | |
| brew untap aws/tap azure/bicep || true | |
| - name: Install toolset via brew | |
| run: | | |
| brew install rpm | |
| brew install snapcraft | |
| - name: Run shard | |
| run: pnpm ci:test | |
| env: | |
| VITEST_SHARD_INDEX: ${{ matrix.shard }} | |
| VITEST_SMART_CACHE_FILE: ${{ github.workspace }}/test/vitest-scripts/vitest-config/_vitest-smart-cache.json | |
| - name: Upload test artifacts | |
| if: always() | |
| uses: ./.github/actions/upload-test-artifacts | |
| with: | |
| name: ${{ matrix.platform }}-${{ matrix.shard }} | |
| # ------------------------- | |
| # Special test jobs | |
| # ------------------------- | |
| # Need to separate from other tests because logic is specific to when TOKEN env vars are set | |
| test-updater: | |
| name: Test Updater | |
| needs: [check-if-docker-build, run-docker-build] | |
| if: | | |
| always() && | |
| needs.check-if-docker-build.result == 'success' && | |
| (needs.run-docker-build.result == 'success' || needs.run-docker-build.result == 'skipped') | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 60 | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: Cleanup runner | |
| uses: ./.github/actions/cleanup-runner | |
| - name: Setup Tests | |
| uses: ./.github/actions/pretest | |
| with: | |
| cache-path: ~/.cache/electron | |
| cache-key: v-39.8.10-update-electron | |
| reset-vitest-smart-cache: ${{ inputs.reset-vitest-smart-cache }} | |
| collect-coverage: ${{ inputs.collect-coverage }} | |
| - name: Verify Docs Generation | |
| run: pnpm generate:all | |
| - name: Verify Site Generation | |
| run: pnpm docs:all | |
| - name: Download test-runner if exists | |
| if: needs.run-docker-build.result == 'success' | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: electron-builder-all-${{ env.TEST_IMAGE_NODE_MAJOR_VERSION }} | |
| path: ${{ runner.temp }} | |
| - name: Load test runner image if needed | |
| if: needs.run-docker-build.result == 'success' | |
| run: | | |
| docker image load --input ${{ runner.temp }}/electron-builder-all-${{ env.TEST_IMAGE_NODE_MAJOR_VERSION }}.tar | |
| docker image ls -a | |
| # The updater tests no longer hit live provider endpoints, so no provider tokens are injected. | |
| # The file must always exist (even empty) because docker --env-file fails on a missing file | |
| # and the R2 append step below is skipped on forks. | |
| - name: Create Docker secrets env file | |
| run: | | |
| : > "${{ runner.temp }}/docker-secrets.env" | |
| chmod 600 "${{ runner.temp }}/docker-secrets.env" | |
| # Gated on the upstream repository so forks cannot substitute their own R2 credentials; | |
| # without these vars the R2 live smoke test is skipped (test.ifEnv). | |
| - name: Add R2 secrets to Docker secrets env file | |
| if: github.repository == 'electron-userland/electron-builder' | |
| run: | | |
| printf 'CF_R2_ACCESS_KEY_ID=%s\nCF_R2_SECRET_ACCESS_KEY=%s\nCF_R2_ACCOUNT_ID=%s\nCF_R2_BUCKET=%s\nCF_R2_PUBLIC_URL=%s\n' \ | |
| "$CF_R2_ACCESS_KEY_ID_SECRET" "$CF_R2_SECRET_ACCESS_KEY_SECRET" "$CF_R2_ACCOUNT_ID_SECRET" "$CF_R2_BUCKET_SECRET" "$CF_R2_PUBLIC_URL_SECRET" \ | |
| >> "${{ runner.temp }}/docker-secrets.env" | |
| env: | |
| CF_R2_ACCESS_KEY_ID_SECRET: ${{ secrets.CF_R2_ACCESS_KEY_ID }} | |
| CF_R2_SECRET_ACCESS_KEY_SECRET: ${{ secrets.CF_R2_SECRET_ACCESS_KEY }} | |
| CF_R2_ACCOUNT_ID_SECRET: ${{ secrets.CF_R2_ACCOUNT_ID }} | |
| CF_R2_BUCKET_SECRET: ${{ secrets.CF_R2_BUCKET }} | |
| CF_R2_PUBLIC_URL_SECRET: ${{ secrets.CF_R2_PUBLIC_URL }} | |
| - name: Test | |
| run: | | |
| echo $TEST_RUNNER_IMAGE_TAG | |
| pnpm test:linux | |
| env: | |
| TEST_FILES: nsisUpdaterTest,PublishManagerTest,differentialUpdateTest,GitlabPublisherTest,R2PublisherTest | |
| TEST_RUNNER_IMAGE_TAG: electronuserland/builder:${{ env.TEST_IMAGE_NODE_MAJOR_VERSION }}-wine-mono | |
| ADDITIONAL_DOCKER_ARGS: "--env-file ${{ runner.temp }}/docker-secrets.env -e VITEST_SMART_CACHE_FILE=./test/vitest-scripts/vitest-config/_vitest-smart-cache.json -e RESET_VITEST_SHARD_CACHE=${{ inputs.reset-vitest-smart-cache }} -e VITEST_COVERAGE=${{ inputs.collect-coverage }}" | |
| - name: Upload test artifacts | |
| if: always() | |
| uses: ./.github/actions/upload-test-artifacts | |
| with: | |
| name: updater | |
| test-snap: | |
| name: Test Snap (${{ matrix.core }}) | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 60 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| core: [core18, core20, core22, core24] | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: Setup Tests | |
| uses: ./.github/actions/pretest | |
| with: | |
| cache-path: ~/.cache/electron | |
| cache-key: v-39.8.10-native-electron | |
| reset-vitest-smart-cache: ${{ inputs.reset-vitest-smart-cache }} | |
| collect-coverage: ${{ inputs.collect-coverage }} | |
| - name: Test snap ${{ matrix.core }} (Docker) | |
| run: SNAP_CORE=${{ matrix.core }} ./test/src/linux/test-snap.sh | |
| env: | |
| VITEST_SMART_CACHE_FILE: ${{ github.workspace }}/test/vitest-scripts/vitest-config/_vitest-smart-cache.json | |
| RESET_VITEST_SHARD_CACHE: ${{ inputs.reset-vitest-smart-cache }} | |
| # Native install+launch test — core24 only; requires snapcraft + unsquashfs on the runner. | |
| - name: Disable background apt services (prevent apt lock contention) | |
| if: matrix.core == 'core24' | |
| run: | | |
| sudo systemctl stop unattended-upgrades apt-daily.service apt-daily-upgrade.service || true | |
| sudo systemctl disable apt-daily.timer apt-daily-upgrade.timer || true | |
| sudo systemctl kill --kill-who=all apt-daily.service apt-daily-upgrade.service || true | |
| while sudo fuser /var/lib/apt/lists/lock /var/lib/dpkg/lock /var/lib/dpkg/lock-frontend >/dev/null 2>&1; do | |
| echo "Waiting for apt lock to be released…" | |
| sleep 2 | |
| done | |
| - name: Install snapcraft natively | |
| if: matrix.core == 'core24' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y squashfs-tools xvfb | |
| # Pin to the 8.x track: snapcraft 9.0.0 (latest/stable) intermittently hangs while | |
| # apt-fetching destructive-mode stagePackages, causing the core24 test to time out. | |
| sudo snap install snapcraft --classic --channel=8.x/stable | |
| - name: Test snap core24 native (install + launch) | |
| if: matrix.core == 'core24' | |
| run: pnpm ci:test | |
| env: | |
| TEST_FILES: snapHeavyTest | |
| SNAP_TEST_CORES: core24 | |
| SNAPCRAFT_BUILD_ENVIRONMENT: host | |
| RUN_SNAP_TESTS: "true" | |
| VITEST_SMART_CACHE_FILE: ${{ github.workspace }}/test/vitest-scripts/vitest-config/_vitest-smart-cache.json | |
| RESET_VITEST_SHARD_CACHE: ${{ inputs.reset-vitest-smart-cache }} | |
| - name: Upload test artifacts | |
| if: always() | |
| uses: ./.github/actions/upload-test-artifacts | |
| with: | |
| name: snap-${{ matrix.core }} | |
| test-e2e: | |
| name: Test e2e Auto Updater Linux | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 60 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| test_config: | |
| - stem: archlinux | |
| env: | |
| PACKAGE_MANAGER_TO_TEST: pacman | |
| - stem: rpm | |
| env: | |
| PACKAGE_MANAGER_TO_TEST: dnf | |
| - stem: rpm | |
| env: | |
| PACKAGE_MANAGER_TO_TEST: zypper | |
| - stem: rpm | |
| env: | |
| PACKAGE_MANAGER_TO_TEST: yum | |
| - stem: rpm | |
| env: | |
| PACKAGE_MANAGER_TO_TEST: rpm | |
| - stem: debian | |
| env: | |
| PACKAGE_MANAGER_TO_TEST: apt | |
| - stem: debian | |
| env: | |
| PACKAGE_MANAGER_TO_TEST: dpkg | |
| - stem: appimage | |
| env: | |
| RUN_APP_IMAGE_TEST: true | |
| steps: | |
| - name: Checkout code repository | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: Setup Tests | |
| uses: ./.github/actions/pretest | |
| with: | |
| cache-path: ~/.cache/electron | |
| cache-key: v-39.8.10-linux-e2e-electron | |
| reset-vitest-smart-cache: ${{ inputs.reset-vitest-smart-cache }} | |
| collect-coverage: ${{ inputs.collect-coverage }} | |
| - name: docker build | |
| run: ./test/src/updater/test-specific-platforms.sh ${{ matrix.test_config.stem }} build | |
| - name: e2e Linux Updater tests (install, auto-update, uninstall) | |
| run: ./test/src/updater/test-specific-platforms.sh ${{ matrix.test_config.stem }} run | |
| env: | |
| ADDITIONAL_DOCKER_ARGS: >- | |
| -e PACKAGE_MANAGER_TO_TEST=${{ matrix.test_config.env.PACKAGE_MANAGER_TO_TEST || '' }} | |
| -e RUN_APP_IMAGE_TEST=${{ matrix.test_config.env.RUN_APP_IMAGE_TEST || false }} | |
| -e VITEST_SMART_CACHE_FILE=./test/vitest-scripts/vitest-config/_vitest-smart-cache.json | |
| -e RESET_VITEST_SHARD_CACHE=${{ inputs.reset-vitest-smart-cache }} -e VITEST_COVERAGE=${{ inputs.collect-coverage }} | |
| - name: Upload test artifacts | |
| if: always() | |
| uses: ./.github/actions/upload-test-artifacts | |
| with: | |
| name: e2e-${{ matrix.test_config.env.PACKAGE_MANAGER_TO_TEST || matrix.test_config.stem }} | |
| # ------------------------- | |
| # Merge Smart Cache Artifacts | |
| # ------------------------- | |
| merge-smart-cache: | |
| needs: [test-linux, test-windows, test-macos, test-e2e, test-updater, test-snap] | |
| if: always() | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - uses: ./.github/actions/pnpm | |
| - name: Download all smart cache artifacts | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| pattern: vitest-smart-cache-* | |
| path: smart-cache-artifacts | |
| continue-on-error: true | |
| - name: Merge cache files | |
| run: pnpm ci:test:merge-cache | |
| # ------------------------- | |
| # Aggregate per-shard test reports → run summary + combined downloadable report | |
| # ------------------------- | |
| - name: Download all test report artifacts | |
| if: always() | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| pattern: vitest-report-* | |
| path: report-artifacts | |
| continue-on-error: true | |
| # Per-test / per-shard / total durations + a combined list of every failed test, written to the | |
| # run's Summary page (GITHUB_STEP_SUMMARY) and the console. Never fails the job — it is reporting. | |
| - name: Write test summary | |
| if: always() | |
| continue-on-error: true | |
| run: pnpm ci:test:summary --results-dir report-artifacts | |
| - name: Gather blob reports | |
| if: always() | |
| run: | | |
| mkdir -p vitest-blobs | |
| # Prefix each blob with its artifact name (report-artifacts/<artifact>/vitest-blobs/blob-*.json) | |
| # so two shards that happen to share a blob filename (same platform+shard+pid across different | |
| # runners) can't overwrite each other. vitest --merge-reports accepts arbitrary blob filenames. | |
| find report-artifacts -type f -name 'blob-*.json' | while read -r f; do | |
| art=$(basename "$(dirname "$(dirname "$f")")") | |
| cp "$f" "vitest-blobs/${art}__$(basename "$f")" | |
| done | |
| echo "Collected $(ls vitest-blobs 2>/dev/null | wc -l) blob report(s)" | |
| # Combined @vitest/ui HTML report (+ merged v8 coverage when collect-coverage is on) from every | |
| # shard's blob. Runs from the repo root so blob paths and reporter resolution line up. | |
| - name: Merge reports into combined HTML report | |
| if: always() | |
| continue-on-error: true | |
| run: pnpm ci:test:merge-reports | |
| env: | |
| VITEST_COVERAGE: ${{ inputs.collect-coverage }} | |
| - name: Upload combined test report | |
| if: always() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: vitest-combined-report | |
| path: | | |
| html-report/ | |
| merged-test-report.json | |
| merged-coverage/ | |
| retention-days: 14 | |
| if-no-files-found: warn | |
| - name: Delete individual cache artifacts | |
| uses: geekyeggo/delete-artifact@176a747ab7e287e3ff4787bf8a148716375ca118 # v6.0.0 | |
| with: | |
| name: | | |
| vitest-smart-cache-* | |
| vitest-report-* | |
| failOnError: false | |
| continue-on-error: true | |
| - name: Copy merged cache to canonical path | |
| if: always() | |
| run: cp merged-cache/_vitest-smart-cache.json test/vitest-scripts/vitest-config/_vitest-smart-cache.json | |
| - name: Compute Vitest smart cache ref | |
| if: always() | |
| run: | | |
| PR_NUM="${{ github.event.pull_request.number }}" | |
| if [ -n "$PR_NUM" ]; then | |
| echo "VITEST_CACHE_REF=PR-${PR_NUM}" >> "$GITHUB_ENV" | |
| else | |
| # Artifact names cannot contain "/", so sanitize slashes in branch | |
| # names like "release/v26" -> "release-v26" (keep in sync with detectRef in fetch-smart-cache.ts). | |
| echo "VITEST_CACHE_REF=${GITHUB_REF_NAME//\//-}" >> "$GITHUB_ENV" | |
| fi | |
| - name: Upload vitest smart cache artifact | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| if: always() | |
| with: | |
| name: vitest-smart-cache-${{ env.VITEST_CACHE_REF }} | |
| path: merged-cache/_vitest-smart-cache.json | |
| retention-days: 90 | |
| overwrite: true | |