From 0e180141bf9b859efdbe067cf1eb850e22048bf8 Mon Sep 17 00:00:00 2001 From: lauren Date: Tue, 6 Jan 2026 17:23:40 -0800 Subject: [PATCH 1/3] [ci] Separate DevTools test-build into dedicated job with fewer shards (#35457) DevTools has ~45 test files which don't distribute well across 10 shards, causing shard 3 to run 2x slower than others (104s vs ~50s). This moves DevTools build tests to a separate job with 3 shards for better load balancing. --- .github/workflows/runtime_build_and_test.yml | 45 ++++++++++++++++++-- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/.github/workflows/runtime_build_and_test.yml b/.github/workflows/runtime_build_and_test.yml index c1cc8df2eb7..735ac6edb18 100644 --- a/.github/workflows/runtime_build_and_test.yml +++ b/.github/workflows/runtime_build_and_test.yml @@ -382,9 +382,6 @@ jobs: -r=experimental --env=development, -r=experimental --env=production, - # Dev Tools - --project=devtools -r=experimental, - # TODO: Update test config to support www build tests # - "-r=www-classic --env=development --variant=false" # - "-r=www-classic --env=production --variant=false" @@ -450,6 +447,48 @@ jobs: run: ls -R build - run: yarn test --build ${{ matrix.test_params }} --shard=${{ matrix.shard }} --ci + test_build_devtools: + name: yarn test-build (devtools) + needs: [build_and_lint, runtime_node_modules_cache] + strategy: + fail-fast: false + matrix: + shard: + - 1/3 + - 2/3 + - 3/3 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.inputs.commit_sha != '' && github.event.inputs.commit_sha || github.event.pull_request.head.sha || github.sha }} + - uses: actions/setup-node@v4 + with: + node-version-file: '.nvmrc' + cache: yarn + cache-dependency-path: yarn.lock + - name: Restore cached node_modules + uses: actions/cache/restore@v4 + id: node_modules + with: + path: | + **/node_modules + key: runtime-node_modules-v7-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }} + # Don't use restore-keys here. Otherwise the cache grows indefinitely. + - name: Ensure clean build directory + run: rm -rf build + - run: yarn install --frozen-lockfile + if: steps.node_modules.outputs.cache-hit != 'true' + - name: Restore archived build + uses: actions/download-artifact@v4 + with: + pattern: _build_* + path: build + merge-multiple: true + - name: Display structure of build + run: ls -R build + - run: yarn test --build --project=devtools -r=experimental --shard=${{ matrix.shard }} --ci + process_artifacts_combined: name: Process artifacts combined needs: [build_and_lint, runtime_node_modules_cache] From 00908be9ff2d033ab5340e2a250b6288909d41a0 Mon Sep 17 00:00:00 2001 From: lauren Date: Tue, 6 Jan 2026 18:23:05 -0800 Subject: [PATCH 2/3] [ci] Increase DevTools test shards and bump timeout (#35459) [ci] Increase DevTools test shards and bump timeout - Increase DevTools test shards from 3 to 5 - Bump timeout to 20s --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/35459). * #35458 * __->__ #35459 --- .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 d6cae440e34c6250928e18bed4a16480f83ae18a Mon Sep 17 00:00:00 2001 From: lauren Date: Tue, 6 Jan 2026 18:29:22 -0800 Subject: [PATCH 3/3] [ci] Add size-balanced test sequencer for better shard distribution (#35458) 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. --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/35458). * __->__ #35458 * #35459 --- 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;