Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Speed up tests runs by sharding using tenbin #28953

Draft
wants to merge 14 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 45 additions & 21 deletions .github/workflows/end-to-end-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@ jobs:
with:
repository: element-hq/element-web

# Restore playwright-results.json file, which records the execution time of each test file.
# The splitTests function uses this file for sharding.
# We do this in the build stage to ensure it remains consistent if a playwright test got manually restarted
- name: Restore playwright-results.json
uses: actions/cache/restore@v4
with:
path: playwright-results.json
key: playwright-results

- uses: actions/setup-node@v4
with:
cache: "yarn"
Expand All @@ -77,14 +86,15 @@ jobs:
env:
CI_PACKAGE: true
VERSION: "${{ steps.layered_build.outputs.VERSION }}"
run: |
yarn build
run: yarn build

- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: webapp
path: webapp
name: build
path: |
webapp
playwright-results.json
retention-days: 1

- name: Calculate runner variables
Expand Down Expand Up @@ -122,6 +132,8 @@ jobs:
project: Firefox
- runAllTests: false
project: WebKit
env:
SHARD_BLOB_NAME: blob-report-${{ matrix.project }}-${{ matrix.runner }}
steps:
- uses: actions/checkout@v4
with:
Expand All @@ -131,8 +143,7 @@ jobs:
- name: 📥 Download artifact
uses: actions/download-artifact@v4
with:
name: webapp
path: webapp
name: build

- uses: actions/setup-node@v4
with:
Expand Down Expand Up @@ -168,63 +179,76 @@ jobs:
- name: Run Playwright tests
run: |
yarn playwright test \
--shard "${{ matrix.runner }}/${{ needs.build.outputs.num-runners }}" \
--project="${{ matrix.project }}" \
${{ (github.event_name == 'pull_request' && matrix.runAllTests == false ) && '--grep-invert @mergequeue' || '' }}
env:
SHARD: "${{ matrix.runner }}/${{ needs.build.outputs.num-runners }}"
PLAYWRIGHT_BLOB_OUTPUT_FILE: ${{ env.SHARD_BLOB_NAME }}.zip

- name: Upload blob report to GitHub Actions Artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: all-blob-reports-${{ matrix.project }}-${{ matrix.runner }}
path: blob-report
name: ${{ env.SHARD_BLOB_NAME }}
path: ${{ env.SHARD_BLOB_NAME }}.zip
retention-days: 1
if-no-files-found: error

complete:
name: end-to-end-tests
report:
name: Report results
needs: playwright
if: always()
if: ${{ !cancelled() && inputs.skip != true }}
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
if: inputs.skip != true
with:
persist-credentials: false
repository: element-hq/element-web

- uses: actions/setup-node@v4
if: inputs.skip != true
with:
cache: "yarn"
node-version: "lts/*"

- name: Install dependencies
if: inputs.skip != true
run: yarn install --frozen-lockfile

- name: Download blob reports from GitHub Actions Artifacts
if: inputs.skip != true
uses: actions/download-artifact@v4
with:
pattern: all-blob-reports-*
pattern: blob-report-*
path: all-blob-reports
merge-multiple: true

- name: Merge into HTML Report
if: inputs.skip != true
run: yarn playwright merge-reports --reporter=html,./playwright/flaky-reporter.ts,./playwright/stale-screenshot-reporter.ts ./all-blob-reports
run: yarn playwright merge-reports --reporter=html,json,./playwright/flaky-reporter.ts,./playwright/stale-screenshot-reporter.ts ./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_JSON_OUTPUT_NAME: playwright-results.json

- name: Cache playwright-results.json
uses: actions/cache/save@v4
with:
path: playwright-results.json
key: playwright-results

# 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
if: always()
uses: actions/upload-artifact@v4
with:
name: html-report
path: playwright-report
retention-days: 14

- if: needs.playwright.result != 'skipped' && needs.playwright.result != 'success'
complete:
name: end-to-end-tests
needs:
- playwright
- report
if: ${{ !cancelled() }}
runs-on: ubuntu-24.04
steps:
- if: needs.playwright.result == 'failure' || needs.report.result == 'failure'
run: exit 1
28 changes: 28 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ jobs:
id: cpu-cores
uses: SimenB/github-actions-cpu-cores@97ba232459a8e02ff6121db9362b09661c875ab8 # v2

# Restore tenbin-report.json file, which records the execution time of each test file.
# @tenbin/jest/sequencer uses this file for sharding.
- name: Restore tenbin-report.json
uses: actions/cache/restore@v4
with:
path: tenbin-report.json
key: tenbin-report

- name: Run tests
run: |
yarn test \
Expand All @@ -78,6 +86,13 @@ jobs:
# tell jest to use coloured output
FORCE_COLOR: true

# @tenbin/jest/reporter generates tenbin-report.json for each shard.
- name: Upload tenbin-report.json
uses: actions/upload-artifact@v4
with:
name: tenbin-report-${{ matrix.runner }}
path: tenbin-report.json

- name: Move coverage files into place
if: env.ENABLE_COVERAGE == 'true'
run: mv coverage/lcov.info coverage/${{ steps.setupNode.outputs.node-version }}-${{ matrix.runner }}.lcov.info
Expand Down Expand Up @@ -112,3 +127,16 @@ jobs:
context: SonarCloud Code Analysis
sha: ${{ github.sha }}
target_url: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}

# Download, merge & upload tenbin-report.json
- uses: actions/download-artifact@v4
with:
path: tenbin-report
pattern: tenbin-report-*
- name: Merge tenbin-report
run: jq -s add tenbin-report/**/tenbin-report.json > tenbin-report.json
- name: Cache tenbin-report.json
uses: actions/cache/save@v4
with:
path: tenbin-report.json
key: tenbin-report
3 changes: 2 additions & 1 deletion jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,12 @@ const config: Config = {
testResultsProcessor: "@casualbot/jest-sonar-reporter",
prettierPath: null,
moduleDirectories: ["node_modules", "test/test-utils"],
testSequencer: "@tenbin/jest/sequencer",
};

// if we're running under GHA, enable the GHA reporter
if (env["GITHUB_ACTIONS"] !== undefined) {
const reporters: Config["reporters"] = [["github-actions", { silent: false }], "summary"];
const reporters: Config["reporters"] = [["github-actions", { silent: false }], "summary", "@tenbin/jest/reporter"];

// if we're running against the develop branch, also enable the slow test reporter
if (env["GITHUB_REF"] == "refs/heads/develop") {
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@
"@sentry/webpack-plugin": "^2.7.1",
"@stylistic/eslint-plugin": "^2.9.0",
"@svgr/webpack": "^8.0.0",
"@tenbin/jest": "^0.5.0",
"@tenbin/playwright": "^0.5.0",
"@testcontainers/postgresql": "^10.16.0",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.4.8",
Expand Down
8 changes: 8 additions & 0 deletions playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Please see LICENSE files in the repository root for full details.
*/

import { defineConfig, devices } from "@playwright/test";
import { splitTests } from "@tenbin/playwright";

const baseURL = process.env["BASE_URL"] ?? "http://localhost:8080";

Expand Down Expand Up @@ -70,4 +71,11 @@ export default defineConfig({
snapshotDir: "playwright/snapshots",
snapshotPathTemplate: "{snapshotDir}/{testFilePath}/{arg}-{platform}{ext}",
forbidOnly: !!process.env.CI,
testMatch: process.env.SHARD
? splitTests({
shard: process.env.SHARD,
pattern: ["playwright/e2e/**/*.spec.ts"],
reportFile: "playwright-results.json",
})
: undefined,
});
26 changes: 25 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2717,6 +2717,29 @@
"@svgr/plugin-jsx" "8.1.0"
"@svgr/plugin-svgo" "8.1.0"

"@tenbin/core@0.5.0":
version "0.5.0"
resolved "https://registry.yarnpkg.com/@tenbin/core/-/core-0.5.0.tgz#394f74d90e618e9c15a1f376871a5247b06e35d7"
integrity sha512-QawJTsn1svoLDJipr0dDl/L3npkiMmA1pO5OfveoV6/hajQSrEI0QJtxg/kXMyi0P+EUJ55KL0BVsDkh78OvZA==

"@tenbin/jest@^0.5.0":
version "0.5.0"
resolved "https://registry.yarnpkg.com/@tenbin/jest/-/jest-0.5.0.tgz#5f89396de18d5aa1f78d91926cf8941be89aa2e5"
integrity sha512-CWjyHGMzibiQWJYXuXEsiPgEmXPjoPfRJItTFbvNEmW4lWazuMsQcihxs4ZpyCUq8LxDDMFYf2Egt7ZMjsTEQA==
dependencies:
"@jest/test-sequencer" "^29.7.0"
"@tenbin/core" "0.5.0"
picocolors "^1.1.0"

"@tenbin/playwright@^0.5.0":
version "0.5.0"
resolved "https://registry.yarnpkg.com/@tenbin/playwright/-/playwright-0.5.0.tgz#8203d3419144fb812430663cc6362658df462abd"
integrity sha512-ApHQnl7a4avRa89CmDA+3C01MIxavV4HPtEmgXMvc8zg5AbFlmb+bu2VPQMtqfm4u4UgY0J/oO8SLjBABF5VCw==
dependencies:
"@tenbin/core" "0.5.0"
glob "^11.0.0"
picocolors "^1.1.0"

"@testcontainers/postgresql@^10.16.0":
version "10.16.0"
resolved "https://registry.yarnpkg.com/@testcontainers/postgresql/-/postgresql-10.16.0.tgz#0437a9b426d64ea958e745a0e2ae19462b786f81"
Expand Down Expand Up @@ -3546,13 +3569,14 @@

"@vector-im/matrix-wysiwyg-wasm@link:../../.cache/yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.0-af862ffd231dc0a6b8d6f2cb3601e68456c0ff24-integrity/node_modules/bindings/wysiwyg-wasm":
version "0.0.0"
uid ""

"@vector-im/matrix-wysiwyg@2.38.0":
version "2.38.0"
resolved "https://registry.yarnpkg.com/@vector-im/matrix-wysiwyg/-/matrix-wysiwyg-2.38.0.tgz#af862ffd231dc0a6b8d6f2cb3601e68456c0ff24"
integrity sha512-cMEVicFYVzFxuSyWON0aVGjAJMcgJZ+LxuLTEp8EGuu8cRacuh0RN5rapb11YVZygzFvE7X1cMedJ/fKd5vRLA==
dependencies:
"@vector-im/matrix-wysiwyg-wasm" "link:../../.cache/yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.0-af862ffd231dc0a6b8d6f2cb3601e68456c0ff24-integrity/node_modules/bindings/wysiwyg-wasm"
"@vector-im/matrix-wysiwyg-wasm" "link:../../Library/Caches/Yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.0-af862ffd231dc0a6b8d6f2cb3601e68456c0ff24-integrity/node_modules/bindings/wysiwyg-wasm"

"@webassemblyjs/ast@1.14.1", "@webassemblyjs/ast@^1.14.1":
version "1.14.1"
Expand Down
Loading