name: "UI: Tests" on: push: branches: - "master" - "v5.*" pull_request: branches: - "master" - "v5.*" concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true env: UI_WORKING_DIR: ./ui permissions: {} jobs: ui-tests: runs-on: ubuntu-latest timeout-minutes: 20 permissions: contents: read defaults: run: working-directory: ./ui steps: - name: Harden Runner uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3 with: egress-policy: block allowed-endpoints: > github.com:443 registry.npmjs.org:443 fonts.googleapis.com:443 fonts.gstatic.com:443 api.github.com:443 release-assets.githubusercontent.com:443 cdn.playwright.dev:443 objects.githubusercontent.com:443 playwright.download.prss.microsoft.com:443 - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: # zizmor: ignore[artipacked] persist-credentials: true # Required by tj-actions/changed-files to fetch PR branch - name: Check for UI changes id: check-changes uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6 with: files: | ui/** .github/workflows/ui-tests.yml files_ignore: | ui/CHANGELOG.md ui/README.md ui/AGENTS.md - name: Get changed source files for targeted tests id: changed-source if: steps.check-changes.outputs.any_changed == 'true' uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6 with: files: | ui/**/*.ts ui/**/*.tsx files_ignore: | ui/**/*.test.ts ui/**/*.test.tsx ui/**/*.spec.ts ui/**/*.spec.tsx ui/vitest.config.ts ui/vitest.setup.ts - name: Check for critical path changes (run all tests) id: critical-changes if: steps.check-changes.outputs.any_changed == 'true' uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6 with: files: | ui/lib/** ui/types/** ui/config/** ui/middleware.ts ui/vitest.config.ts ui/vitest.setup.ts - name: Setup Node.js if: steps.check-changes.outputs.any_changed == 'true' uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version-file: 'ui/.nvmrc' - name: Setup pnpm if: steps.check-changes.outputs.any_changed == 'true' uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0 with: package_json_file: ui/package.json run_install: false - name: Get pnpm store directory if: steps.check-changes.outputs.any_changed == 'true' shell: bash run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - name: Setup pnpm and Next.js cache if: steps.check-changes.outputs.any_changed == 'true' uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: | ${{ env.STORE_PATH }} ${{ env.UI_WORKING_DIR }}/node_modules ${{ env.UI_WORKING_DIR }}/.next/cache key: ${{ runner.os }}-pnpm-nextjs-${{ hashFiles('ui/pnpm-lock.yaml') }}-${{ hashFiles('ui/**/*.ts', 'ui/**/*.tsx', 'ui/**/*.js', 'ui/**/*.jsx') }} restore-keys: | ${{ runner.os }}-pnpm-nextjs-${{ hashFiles('ui/pnpm-lock.yaml') }}- ${{ runner.os }}-pnpm-nextjs- - name: Install dependencies if: steps.check-changes.outputs.any_changed == 'true' run: pnpm install --frozen-lockfile --prefer-offline - name: Run healthcheck if: steps.check-changes.outputs.any_changed == 'true' run: pnpm run healthcheck - name: Run pnpm audit if: steps.check-changes.outputs.any_changed == 'true' run: pnpm run audit - name: Run unit tests (all - critical paths changed) if: steps.check-changes.outputs.any_changed == 'true' && steps.critical-changes.outputs.any_changed == 'true' run: | echo "Critical paths changed - running ALL unit tests" pnpm run test:unit - name: Run unit tests (related to changes only) if: steps.check-changes.outputs.any_changed == 'true' && steps.critical-changes.outputs.any_changed != 'true' && steps.changed-source.outputs.all_changed_files != '' run: | echo "Running tests related to changed files:" echo "${STEPS_CHANGED_SOURCE_OUTPUTS_ALL_CHANGED_FILES}" # Convert space-separated to vitest related format (remove ui/ prefix for relative paths) CHANGED_FILES=$(echo "${STEPS_CHANGED_SOURCE_OUTPUTS_ALL_CHANGED_FILES}" | tr ' ' '\n' | sed 's|^ui/||' | tr '\n' ' ') pnpm exec vitest related $CHANGED_FILES --run --project unit env: STEPS_CHANGED_SOURCE_OUTPUTS_ALL_CHANGED_FILES: ${{ steps.changed-source.outputs.all_changed_files }} - name: Run unit tests (test files only changed) if: steps.check-changes.outputs.any_changed == 'true' && steps.critical-changes.outputs.any_changed != 'true' && steps.changed-source.outputs.all_changed_files == '' run: | echo "Only test files changed - running ALL unit tests" pnpm run test:unit - name: Cache Playwright browsers if: steps.check-changes.outputs.any_changed == 'true' id: playwright-cache uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: ~/.cache/ms-playwright key: ${{ runner.os }}-playwright-chromium-${{ hashFiles('ui/pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}-playwright-chromium- - name: Install Playwright Chromium browser if: steps.check-changes.outputs.any_changed == 'true' && steps.playwright-cache.outputs.cache-hit != 'true' run: pnpm exec playwright install chromium - name: Run browser tests if: steps.check-changes.outputs.any_changed == 'true' run: pnpm run test:browser - name: Build application if: steps.check-changes.outputs.any_changed == 'true' run: pnpm run build