From f6c4694636bf95ff2f3852c68edb5b32bf55c0a9 Mon Sep 17 00:00:00 2001 From: Lauren Tan Date: Tue, 6 Jan 2026 18:07:47 -0800 Subject: [PATCH 1/2] [ci] Increase DevTools test shards and bump timeout [ci] Increase DevTools test shards and bump timeout - Increase DevTools test shards from 3 to 5 - Bump timeout to 20s --- .github/workflows/runtime_build_and_test.yml | 8 +++++--- .../src/__tests__/profilerContext-test.js | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/runtime_build_and_test.yml b/.github/workflows/runtime_build_and_test.yml index 735ac6edb18..25282e8400a 100644 --- a/.github/workflows/runtime_build_and_test.yml +++ b/.github/workflows/runtime_build_and_test.yml @@ -454,9 +454,11 @@ jobs: fail-fast: false matrix: shard: - - 1/3 - - 2/3 - - 3/3 + - 1/5 + - 2/5 + - 3/5 + - 4/5 + - 5/5 runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 diff --git a/packages/react-devtools-shared/src/__tests__/profilerContext-test.js b/packages/react-devtools-shared/src/__tests__/profilerContext-test.js index 7864f9703ea..a1e47defa2a 100644 --- a/packages/react-devtools-shared/src/__tests__/profilerContext-test.js +++ b/packages/react-devtools-shared/src/__tests__/profilerContext-test.js @@ -654,7 +654,7 @@ describe('ProfilerContext', () => { expect(store.profilerStore.isProfilingBasedOnUserInput).toBe(false); document.body.removeChild(profilerContainer); - }); + }, 20000); it('should navigate between commits when the keyboard shortcut is pressed', async () => { const Parent = () => ; From 85773456e715cd68ca8b5080bed58f6175f482ba Mon Sep 17 00:00:00 2001 From: Lauren Tan Date: Tue, 6 Jan 2026 18:07:47 -0800 Subject: [PATCH 2/2] [ci] Add size-balanced test sequencer for better shard distribution Jest's default test sequencer sorts alphabetically, causing large test files (eg ReactDOMFloat-test.js at 9k lines, ReactHooksWithNoopRenderer-test.js at 4k lines) to cluster in shard 3/5. This made shard 3/5 average 117s vs 77s for other shards, a 52% slowdown. I'm using filesize as a rough proxy for number of tests. This custom sequencer sorts tests by file size and distributes large files evenly across all shards instead of clustering them together. --- scripts/jest/config.base.js | 1 + scripts/jest/sizeBalancedSequencer.js | 28 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 scripts/jest/sizeBalancedSequencer.js diff --git a/scripts/jest/config.base.js b/scripts/jest/config.base.js index ba001e165ee..12b5fc45cd4 100644 --- a/scripts/jest/config.base.js +++ b/scripts/jest/config.base.js @@ -2,6 +2,7 @@ module.exports = { globalSetup: require.resolve('./setupGlobal.js'), + testSequencer: require.resolve('./sizeBalancedSequencer.js'), modulePathIgnorePatterns: [ '/scripts/rollup/shims/', '/scripts/bench/', diff --git a/scripts/jest/sizeBalancedSequencer.js b/scripts/jest/sizeBalancedSequencer.js new file mode 100644 index 00000000000..318cd136be4 --- /dev/null +++ b/scripts/jest/sizeBalancedSequencer.js @@ -0,0 +1,28 @@ +'use strict'; + +const Sequencer = require('@jest/test-sequencer').default; +const fs = require('fs'); + +class SizeBalancedSequencer extends Sequencer { + shard(tests, {shardIndex, shardCount}) { + const shards = Array.from({length: shardCount}, () => ({ + tests: [], + size: 0, + })); + const sorted = [...tests].sort( + (a, b) => fs.statSync(b.path).size - fs.statSync(a.path).size + ); + + for (let i = 0; i < sorted.length; i++) { + const test = sorted[i]; + const size = fs.statSync(test.path).size; + const smallest = shards.reduce((min, s) => (s.size < min.size ? s : min)); + smallest.tests.push(test); + smallest.size += size; + } + + return shards[shardIndex - 1].tests; + } +} + +module.exports = SizeBalancedSequencer;