Skip to content

Playwright E2E Tests #5287

Playwright E2E Tests

Playwright E2E Tests #5287

Workflow file for this run

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