# Produce a build of element-web with this version of react-sdk # and any matching branches of element-web and js-sdk, output it # as an artifact and run end-to-end tests. name: End to End Tests on: # CRON to run all Projects at 6am UTC schedule: - cron: "0 6 * * *" pull_request: {} merge_group: types: [checks_requested] push: branches: [develop, master] repository_dispatch: types: [element-web-notify] # support triggering from other workflows workflow_call: inputs: skip: type: boolean required: false default: false description: "A boolean to skip the playwright check itself while still creating the passing check. Useful when only running in Merge Queues." matrix-js-sdk-sha: type: string required: false description: "The Git SHA of matrix-js-sdk to build against. By default, will use a matching branch name if it exists, or develop." concurrency: group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }} cancel-in-progress: true env: # fetchdep.sh needs to know our PR number PR_NUMBER: ${{ github.event.pull_request.number }} # Use 6 runners in the default case, but 4 when running on a schedule where we run all 5 projects (20 runners total) NUM_RUNNERS: ${{ github.event_name == 'schedule' && 4 || 6 }} NX_DEFAULT_OUTPUT_STYLE: stream-without-prefixes permissions: {} # No permissions required jobs: build: name: "Build Element-Web" runs-on: ubuntu-24.04 if: inputs.skip != true outputs: num-runners: ${{ env.NUM_RUNNERS }} runners-matrix: ${{ steps.runner-vars.outputs.matrix }} steps: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: repository: element-hq/element-web persist-credentials: false - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4 - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6 with: cache: "pnpm" node-version: "lts/*" - name: Fetch layered build env: # tell layered.sh to check out the right sha of the JS-SDK & EW, if they were given one JS_SDK_GITHUB_BASE_REF: ${{ inputs.matrix-js-sdk-sha }} run: scripts/layered.sh - name: Copy config working-directory: apps/web run: cp element.io/develop/config.json config.json - name: Build env: CI_PACKAGE: true working-directory: apps/web run: VERSION=$(scripts/get-version-from-git.sh) pnpm run build - name: Upload Artifact uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7 with: name: webapp path: apps/web/webapp retention-days: 1 - name: Calculate runner variables id: runner-vars uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 with: script: | const numRunners = parseInt(process.env.NUM_RUNNERS, 10); const matrix = Array.from({ length: numRunners }, (_, i) => i + 1); core.setOutput("matrix", JSON.stringify(matrix)); playwright: name: "Run Tests [${{ matrix.project }}] ${{ matrix.runner }}/${{ needs.build.outputs.num-runners }}" needs: build if: inputs.skip != true runs-on: ubuntu-24.04 permissions: actions: read issues: read pull-requests: read strategy: fail-fast: false matrix: # Run multiple instances in parallel to speed up the tests runner: ${{ fromJSON(needs.build.outputs.runners-matrix) }} project: - Chrome - Firefox - WebKit - Dendrite - Pinecone runAllTests: - ${{ github.event_name == 'schedule' || contains(github.event.pull_request.labels.*.name, 'X-Run-All-Tests') }} # Skip the Firefox & Safari runs unless this was a cron trigger or PR has X-Run-All-Tests label exclude: - runAllTests: false project: Firefox - runAllTests: false project: WebKit - runAllTests: false project: Dendrite - runAllTests: false project: Pinecone steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: persist-credentials: false repository: element-hq/element-web - name: 📥 Download artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 with: name: webapp path: apps/web/webapp - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4 - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6 with: cache: "pnpm" cache-dependency-path: pnpm-lock.yaml node-version: "lts/*" - name: Install dependencies run: pnpm install --frozen-lockfile - name: Get installed Playwright version id: playwright run: echo "version=$(pnpm --silent -- playwright --version | awk '{print $2}')" >> $GITHUB_OUTPUT - name: Cache playwright binaries uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5 id: playwright-cache with: path: ~/.cache/ms-playwright key: ${{ runner.os }}-${{ runner.arch }}-playwright-${{ steps.playwright.outputs.version }} - name: Install Playwright browsers if: steps.playwright-cache.outputs.cache-hit != 'true' working-directory: apps/web run: pnpm playwright install --with-deps --no-shell - name: Install system dependencies for WebKit # Some WebKit dependencies seem to lay outside the cache and will need to be installed separately if: matrix.project == 'WebKit' && steps.playwright-cache.outputs.cache-hit == 'true' working-directory: apps/web run: pnpm playwright install-deps webkit # We skip tests tagged with @mergequeue when running on PRs, but run them in MQ and everywhere else - name: Run Playwright tests working-directory: apps/web run: | pnpm playwright test \ --shard "$SHARD" \ --project="${{ matrix.project }}" \ ${{ (github.event_name == 'pull_request' && matrix.runAllTests == false ) && '--grep-invert @mergequeue' || '' }} env: SHARD: ${{ format('{0}/{1}', matrix.runner, needs.build.outputs.num-runners) }} - name: Upload blob report to GitHub Actions Artifacts if: always() uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7 with: name: all-blob-reports-${{ matrix.project }}-${{ matrix.runner }} path: apps/web/blob-report retention-days: 1 downstream-modules: name: Downstream Playwright tests [element-modules] needs: build if: inputs.skip != true && github.event_name == 'merge_group' uses: element-hq/element-modules/.github/workflows/reusable-playwright-tests.yml@main # zizmor: ignore[unpinned-uses] with: webapp-artifact: webapp complete: name: end-to-end-tests needs: - playwright - downstream-modules if: always() runs-on: ubuntu-24.04 steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 if: inputs.skip != true with: persist-credentials: false repository: element-hq/element-web - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4 if: inputs.skip != true - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6 if: inputs.skip != true with: cache: "pnpm" node-version: "lts/*" - name: Install dependencies if: inputs.skip != true run: pnpm install --frozen-lockfile - name: Download blob reports from GitHub Actions Artifacts if: inputs.skip != true uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 with: pattern: all-blob-reports-* path: apps/web/all-blob-reports merge-multiple: true - name: Merge into HTML Report if: inputs.skip != true working-directory: apps/web run: pnpm playwright merge-reports --reporter=html,./playwright/flaky-reporter.ts,@element-hq/element-web-playwright-common/lib/stale-screenshot-reporter.js ./all-blob-reports env: # Only pass creds to the flaky-reporter on main branch runs GITHUB_TOKEN: ${{ github.ref_name == 'develop' && secrets.ELEMENT_BOT_TOKEN || '' }} PLAYWRIGHT_HTML_TITLE: ${{ case(github.event_name == 'pull_request', format('EW Playwright Report PR-{0}', env.PR_NUMBER), 'EW Playwright Report') }} # Upload the HTML report even if one of our reporters fails, this can happen when stale screenshots are detected - name: Upload HTML report if: always() && inputs.skip != true uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7 with: name: html-report path: apps/web/playwright-report retention-days: 14 if-no-files-found: error - if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') run: exit 1