Playwright E2E Tests #5287
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: Playwright E2E Tests | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: >- | |
| ${{ | |
| github.event.pull_request.number && format('{0}-pr-{1}', github.workflow, github.event.pull_request.number) || | |
| format('{0}-{1}', github.workflow, github.sha) | |
| }} | |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
| on: | |
| push: | |
| branches: [main, 'release/**'] | |
| # Always trigger on main/release branches; non-runtime detection handles skipping heavy jobs | |
| pull_request: | |
| types: [opened, synchronize, reopened, ready_for_review] | |
| merge_group: | |
| workflow_dispatch: | |
| inputs: | |
| force_full_hosted: | |
| description: 'Force full hosted CI (bypass optimized detect-changes)' | |
| required: false | |
| type: boolean | |
| default: false | |
| pull_request_base_ref: | |
| description: 'Pull request base branch for label/command dispatches' | |
| required: false | |
| type: string | |
| pull_request_base_sha: | |
| description: 'Pull request base SHA for label/command dispatches' | |
| required: false | |
| type: string | |
| jobs: | |
| detect-changes: | |
| # Branch deletion push events have no checkoutable release ref. | |
| if: github.event_name != 'push' || github.event.deleted != true | |
| permissions: | |
| contents: read | |
| actions: read | |
| issues: read | |
| runs-on: ubuntu-22.04 | |
| outputs: | |
| docs_only: ${{ steps.detect.outputs.docs_only }} | |
| non_runtime_only: ${{ steps.detect.outputs.non_runtime_only }} | |
| run_e2e_tests: ${{ steps.detect.outputs.run_e2e_tests }} | |
| should_run_hosted_ci: ${{ steps.hosted-ci.outputs.should_run_hosted_ci }} | |
| should_force_full_hosted_ci: ${{ steps.hosted-ci.outputs.should_force_full_hosted_ci }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| # Full history is only needed for workflow_dispatch base-SHA reruns. | |
| fetch-depth: ${{ github.event_name == 'workflow_dispatch' && '0' || '50' }} | |
| persist-credentials: false | |
| - name: Select hosted CI mode | |
| id: hosted-ci | |
| uses: ./.github/actions/hosted-ci-selectors | |
| with: | |
| force-full-hosted: ${{ inputs.force_full_hosted || false }} | |
| base-ref: ${{ inputs.pull_request_base_ref || '' }} | |
| - name: Detect relevant changes | |
| id: detect | |
| env: | |
| DISPATCH_BASE_REF: ${{ inputs.pull_request_base_ref || '' }} | |
| DISPATCH_BASE_SHA: ${{ inputs.pull_request_base_sha || '' }} | |
| run: | | |
| # Force-full hosted CI is the explicit escape hatch that bypasses | |
| # optimized change selection. Hosted readiness alone stays path-based. | |
| if [ "${{ steps.hosted-ci.outputs.should_force_full_hosted_ci }}" = "true" ]; then | |
| { | |
| echo "run_e2e_tests=true" | |
| echo "docs_only=false" | |
| echo "non_runtime_only=false" | |
| } >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| if [ -n "$DISPATCH_BASE_SHA" ]; then | |
| export GITHUB_BASE_REF="$DISPATCH_BASE_REF" | |
| BASE_REF="$DISPATCH_BASE_SHA" | |
| else | |
| BASE_REF="${{ github.event.pull_request.base.sha || github.event.merge_group.base_sha || github.event.before || 'origin/main' }}" | |
| fi | |
| script/ci-changes-detector "$BASE_REF" | |
| shell: bash | |
| - name: Guard docs-only main pushes | |
| if: | | |
| (github.event_name == 'push' && github.ref == 'refs/heads/main') || | |
| (github.event_name == 'merge_group' && | |
| github.event.merge_group.base_ref == 'refs/heads/main') | |
| uses: ./.github/actions/ensure-main-docs-safety | |
| with: | |
| docs-only: ${{ steps.detect.outputs.docs_only }} | |
| previous-sha: ${{ github.event.before || github.event.merge_group.base_sha }} | |
| playwright: | |
| needs: detect-changes | |
| runs-on: ubuntu-latest | |
| if: | | |
| needs.detect-changes.outputs.should_run_hosted_ci == 'true' && | |
| needs.detect-changes.outputs.run_e2e_tests == 'true' | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Read runtime versions | |
| id: tool-versions | |
| uses: ./.github/actions/read-tool-versions | |
| - name: Setup Ruby | |
| uses: ./.github/actions/setup-ruby | |
| with: | |
| # Keep the single E2E lane on the minimum runtime; matrix workflows cover latest. | |
| ruby-version: ${{ steps.tool-versions.outputs.minimum-ruby-minor-version }} | |
| - uses: actions/setup-node@v4 | |
| with: | |
| # Pin the single E2E lane to the exact Shakapacker floor from .minimum.tool-versions. | |
| node-version: ${{ steps.tool-versions.outputs.minimum-node-version }} | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@v4 | |
| - name: Get pnpm store directory | |
| shell: bash | |
| run: echo "STORE_PATH=$(pnpm store path --silent)" >> "$GITHUB_ENV" | |
| - name: Setup pnpm cache | |
| uses: actions/cache@v4 | |
| with: | |
| path: ${{ env.STORE_PATH }} | |
| key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} | |
| restore-keys: | | |
| ${{ runner.os }}-pnpm-store- | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Build workspace packages | |
| run: pnpm run build | |
| - name: Install dummy app Ruby dependencies | |
| uses: ./.github/actions/setup-bundle | |
| with: | |
| working-directory: react_on_rails/spec/dummy | |
| ruby-version: ${{ steps.tool-versions.outputs.minimum-ruby-minor-version }} | |
| install-libyaml: 'false' | |
| - name: Install Playwright browsers | |
| working-directory: react_on_rails/spec/dummy | |
| run: npx playwright install --with-deps | |
| - name: Generate React on Rails packs | |
| working-directory: react_on_rails/spec/dummy | |
| env: | |
| RAILS_ENV: test | |
| run: bundle exec rake react_on_rails:generate_packs | |
| - name: Build test assets | |
| working-directory: react_on_rails/spec/dummy | |
| run: pnpm run build:test | |
| - name: Run Playwright tests | |
| working-directory: react_on_rails/spec/dummy | |
| run: pnpm run test:e2e | |
| - uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: playwright-report | |
| path: react_on_rails/spec/dummy/e2e/playwright-report/ | |
| retention-days: 30 |