Skip to content

Commit 5f150d3

Browse files
test(e2e): determinism cleanup + e2e performance (workers, 8-core, Chromium cache) (#2655)
Combines the E2E/test-infra determinism work with the e2e performance work — they both tune `playwright.config.ts` and the e2e pipeline, so they ship as one PR. ## What changed **Determinism** - Removed the three blind `waitForTimeout` sleeps (replaced with awaited conditions) and resolved the permanently-skipped tests (deleted the dead navigation block, fixed + un-skipped the Kubernetes restarts-sort test, deleted `timeQuery.test.tsx` which can't run without a `nuqs` major upgrade; a genuinely-conditional skip in `sources.spec.ts` stays). Deleting `timeQuery.test.tsx` orphaned `src/fixtures.ts`, the `@jedmao/location` dev dep, and the `getLiveTailTimeRange` export — all removed as verified-dead code. - Added env-overridable retry counts: `E2E_RETRIES` (Playwright) and `JEST_RETRY_TIMES` (API Jest), for the nightly zero-retry flake hunt. **Performance** - Playwright `workers` raised to 4 on CI (via `E2E_WORKERS`), and the e2e shards moved to `8-core-playwright` GitHub-managed larger runners so 4 workers have CPU headroom (4 workers on the old 4-vCPU runner over-subscribed and timed out — validated the 8-core run halves shard time). - The Chromium binary is cached (`~/.cache/ms-playwright`, keyed on the Playwright version) so it isn't re-downloaded each shard. - e2e-setup uses `yarn install --immutable`. ## Key decisions - Both retry knobs and `E2E_WORKERS` parse to a validated integer (retries ≥ 0 honouring an explicit 0 for the flake hunt; workers ≥ 1), falling back to the default on blank/negative/non-numeric input rather than silently coercing to 0/NaN. - Retries stay on for PRs (pragmatic); the nightly zero-retry hunt is what enforces "a flaky test is a defect". ## Impact - Faster, less-flaky e2e; retry/worker behaviour tunable via env without code changes. - Test-infra + CI only — no changeset. <details> <summary>Implementation detail</summary> - Kubernetes test made deterministic via the seed (`restarts = podIdx % 7`) + default `restarts` desc sort. Dashboard save-wait uses the same success-toast locator as sibling tests. - 8-core-playwright confirmed a GitHub-managed larger runner (ephemeral/isolated — no fork-PR self-hosted RCE surface). </details>
1 parent d667ede commit 5f150d3

13 files changed

Lines changed: 71 additions & 474 deletions

File tree

‎.github/actions/e2e-setup/action.yml‎

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,32 @@ runs:
3636

3737
- name: Install dependencies
3838
shell: bash
39-
run: yarn install
39+
run: yarn install --immutable
4040

4141
- name: Build dependencies
4242
shell: bash
4343
run: npx nx run-many -t ci:build
4444

45+
# Cache the Chromium binary (~120MB) keyed on the resolved Playwright
46+
# version, so it isn't re-downloaded every shard/run. Browser versions are
47+
# pinned to the Playwright package version, so the version is the correct
48+
# cache key. On a hit, `playwright install` finds the browser present and
49+
# only installs OS deps.
50+
- name: Resolve Playwright version
51+
id: playwright-version
52+
shell: bash
53+
run:
54+
echo "version=$(cd packages/app && node -p
55+
"require('@playwright/test/package.json').version")" >> "$GITHUB_OUTPUT"
56+
57+
- name: Cache Playwright browsers
58+
uses: actions/cache@v4
59+
with:
60+
path: ~/.cache/ms-playwright
61+
key:
62+
${{ runner.os }}-playwright-${{
63+
steps.playwright-version.outputs.version }}
64+
4565
- name: Install Playwright browsers
4666
shell: bash
4767
run: cd packages/app && npx playwright install --with-deps chromium

‎.github/workflows/e2e-tests.yml‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ on:
55
jobs:
66
e2e-tests:
77
name: E2E Tests - Shard ${{ matrix.shard }}
8-
runs-on: ubuntu-24.04
8+
# 8-core runner so the 4 Playwright workers (see playwright.config.ts) have
9+
# CPU headroom alongside the app + ClickHouse + MongoDB — 4 workers
10+
# over-subscribed the 4-vCPU ubuntu-24.04 runner and caused timeouts.
11+
runs-on: 8-core-playwright
912
timeout-minutes: 15
1013
permissions:
1114
contents: read

‎packages/api/jest.setup.ts‎

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
1-
jest.retryTimes(1, { logErrorsBeforeRetry: true });
1+
// Overridable via JEST_RETRY_TIMES (e.g. the nightly zero-retry flake hunt).
2+
// Honours an explicit 0 so retries can be forced off; an unset/blank/negative/
3+
// non-integer value falls back to the default of 1 rather than coercing to 0.
4+
const rawJestRetries = process.env.JEST_RETRY_TIMES;
5+
const parsedJestRetries = rawJestRetries ? Number(rawJestRetries) : NaN;
6+
jest.retryTimes(
7+
Number.isInteger(parsedJestRetries) && parsedJestRetries >= 0
8+
? parsedJestRetries
9+
: 1,
10+
{ logErrorsBeforeRetry: true },
11+
);
212

313
// http-proxy-middleware v4 is ESM-only and Jest's CJS module loader cannot
414
// load ESM packages. Auto-mock since no test exercises the proxy directly.

‎packages/app/package.json‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@
104104
"@chromatic-com/storybook": "^4.1.3",
105105
"@eslint-react/eslint-plugin": "^3.0.0",
106106
"@eslint/compat": "^2.0.0",
107-
"@jedmao/location": "^3.0.0",
108107
"@next/eslint-plugin-next": "^16.0.10",
109108
"@playwright/test": "^1.57.0",
110109
"@storybook/addon-docs": "^10.1.4",

‎packages/app/playwright.config.ts‎

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,25 @@ export default defineConfig({
3030
fullyParallel: true,
3131
/* Fail the build on CI if you accidentally left test.only in the source code. */
3232
forbidOnly: !!process.env.CI,
33-
/* Retry on CI only */
34-
retries: process.env.CI ? 2 : 1,
35-
/* Use multiple workers on CI for faster execution */
36-
workers: process.env.CI ? 2 : undefined,
33+
/* Retry on CI only. Overridable via E2E_RETRIES (e.g. the nightly zero-retry
34+
* flake hunt). Honours an explicit 0; an unset/blank/negative/non-integer
35+
* value falls back to the default rather than silently coercing to 0. */
36+
retries: (() => {
37+
const raw = process.env.E2E_RETRIES;
38+
const parsed = raw ? Number(raw) : NaN;
39+
if (Number.isInteger(parsed) && parsed >= 0) return parsed;
40+
return process.env.CI ? 2 : 1;
41+
})(),
42+
/* Use multiple workers on CI for faster execution. CI e2e shards run on
43+
* 8-core runners (see .github/workflows/e2e-tests.yml), so 4 workers leave
44+
* headroom for the app + ClickHouse + Mongo. Override with E2E_WORKERS
45+
* (a positive integer); anything else falls back to the default. */
46+
workers: (() => {
47+
const raw = process.env.E2E_WORKERS;
48+
const parsed = raw ? Number(raw) : NaN;
49+
if (Number.isInteger(parsed) && parsed >= 1) return parsed;
50+
return process.env.CI ? 4 : undefined;
51+
})(),
3752
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
3853
reporter: [
3954
['html'],

0 commit comments

Comments
 (0)