name: "functional" on: pull_request: push: branches: - main - 5.0-dev concurrency: group: "${{ github.event.pull_request.number }}-${{ github.ref_name }}-${{ github.workflow }}" cancel-in-progress: true permissions: {} env: CI: true UV_EXCLUDE_NEWER: 7 days jobs: changes: permissions: contents: read pull-requests: read name: "changes" runs-on: ubuntu-latest outputs: should_run: ${{ steps.changes.outputs.should_run }} sha: ${{ steps.changes.outputs.sha }} pr_number: ${{ steps.changes.outputs.pr_number }} source_branch: ${{ steps.changes.outputs.source_branch }} source_repo: ${{ steps.changes.outputs.source_repo }} steps: - uses: actions/checkout@v4 - uses: "gradio-app/gradio/.github/actions/changes@main" id: changes with: filter: "functional" token: ${{ secrets.GITHUB_TOKEN }} build: name: "build-frontend" permissions: contents: read runs-on: ubuntu-20.04-16core needs: changes if: needs.changes.outputs.should_run == 'true' steps: - uses: actions/checkout@v4 # Build the frontend exactly once and share it with both SSR test legs # (below) via an artifact. Previously each leg rebuilt it independently, # paying the ~3min `pnpm build` twice. This action sets up node/pnpm, # installs deps and builds into `gradio/templates/**` (the SPA + the SSR # server bundle) — no Python/venv needed (the build only reads the # checked-in `gradio/package.json` for the version string). - name: build frontend uses: "gradio-app/gradio/.github/actions/install-frontend-deps@main" - name: upload built frontend templates uses: actions/upload-artifact@v4 with: name: gradio-templates path: gradio/templates retention-days: 1 include-hidden-files: true test: # Browser legs keep their original check names (functional-test-SSR=true/ # false); reload runs as its own leg named functional-reload. name: "${{ matrix.suite == 'reload' && 'functional-reload' || format('functional-test-SSR={0}', matrix.ssr) }}" permissions: contents: read runs-on: ubuntu-20.04-16core needs: [changes, build] strategy: fail-fast: false matrix: # Reload tests get their own leg instead of running after the browser # suite inside each SSR leg: the ~99s serial reload run is taken off the # browser legs' critical path. Reload doesn't depend on SSR mode (the # reload step never set GRADIO_SSR_MODE), so it runs once here rather # than redundantly in both legs. include: - { suite: browser, ssr: true } - { suite: browser, ssr: false } - { suite: reload } if: needs.changes.outputs.should_run == 'true' steps: - uses: actions/checkout@v4 # `skip_build: true` skips the frontend build (we download it from the # `build` job instead). `skip_docs_gen: true` skips website JSON/CSS-var # doc generation (~80s, irrelevant to browser tests); it's a new input on # install-all-deps, so it only takes effect once this PR is merged and the # @main action carries it (the current @main ignores the unknown input). - name: install dependencies id: install_deps uses: "gradio-app/gradio/.github/actions/install-all-deps@main" with: python_version: "3.10" test: true skip_build: true skip_docs_gen: true - name: download built frontend templates uses: actions/download-artifact@v4 with: name: gradio-templates path: gradio/templates - name: verify frontend templates present run: | test -f gradio/templates/frontend/index.html \ || { echo "::error::frontend templates missing after artifact download"; ls -laR gradio/templates | head -50; exit 1; } test -d gradio/templates/node/build \ || { echo "::error::SSR node build missing after artifact download"; ls -laR gradio/templates | head -50; exit 1; } - name: cache playwright browsers uses: actions/cache@v4 with: path: ~/.cache/ms-playwright key: playwright-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }} restore-keys: | playwright-${{ runner.os }}- - name: install playwright timeout-minutes: 3 run: pnpm exec playwright install chromium --only-shell - name: build essential packages run: pnpm --filter @gradio/utils --filter @gradio/theme package - name: run browser tests if: matrix.suite == 'browser' env: GRADIO_SSR_MODE: ${{ matrix.ssr }} # 16-core runner + largely wait-bound tests → parallelize beyond the # historical default of 4 workers (see .config/playwright.config.js). PW_BROWSER_WORKERS: 8 run: | . venv/bin/activate pnpm test:browser - name: upload screenshots uses: actions/upload-artifact@v4 if: always() && matrix.suite == 'browser' with: name: playwright-screenshots-SSR-${{ matrix.ssr }} path: | ./test-results - name: run reload mode test if: matrix.suite == 'reload' run: | . venv/bin/activate pnpm test:browser:reload - name: upload reload mode screenshots uses: actions/upload-artifact@v4 if: always() && matrix.suite == 'reload' with: name: reload-mode-playwright-screenshots path: | ./test-results