main
yml 1,065 lines 41.9 KB
Raw
1 # Keep this name in sync with the `workflow_run.workflows` list in
2 # runtime_sizebot_comment.yml, which matches on this exact string rather than on
3 # the file name. Renaming it here alone stops sizebot from ever commenting again,
4 # and nothing fails: the comment workflow simply never triggers.
5 name: (Runtime) Build and Test
6
7 on:
8 push:
9 branches:
10 # release branches (keep in sync with branches that receive artifact attestations)
11 - main
12 - releases/**
13 pull_request:
14 paths-ignore:
15 - compiler/**
16 # Manual re-runs are allowed. The workflow always runs on the SHA it was
17 # dispatched from (github.sha); no user-supplied ref is accepted, because
18 # downstream workflows (e.g. runtime_release_from_ci) consume this
19 # workflow's artifacts under a protected environment.
20 workflow_dispatch:
21
22 permissions: {}
23
24 concurrency:
25 group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.run_id }}
26 cancel-in-progress: true
27
28 env:
29 TZ: /usr/share/zoneinfo/America/Los_Angeles
30 # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout
31 SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1
32
33 jobs:
34 # ----- NODE_MODULES CACHE -----
35 # Centralize the node_modules cache so it is saved once and each subsequent job only needs to
36 # restore the cache. Prevents race conditions where multiple workflows try to write to the cache.
37 runtime_node_modules_cache:
38 name: Cache Runtime node_modules
39 runs-on: ubuntu-latest
40 steps:
41 - uses: actions/checkout@v4
42 with:
43 ref: ${{ github.event.pull_request.head.sha || github.sha }}
44
45 - name: Prepare cache
46 id: node_modules
47 uses: actions/cache@v4
48 with:
49 path: |
50 **/node_modules
51 key: runtime-node_modules-v10-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
52 # Don't use restore-keys here. Otherwise the cache grows indefinitely.
53
54 - uses: actions/setup-node@v4
55 if: steps.node_modules.outputs.cache-hit != 'true'
56 with:
57 node-version-file: '.nvmrc'
58
59 - run: yarn install --frozen-lockfile
60 if: steps.node_modules.outputs.cache-hit != 'true'
61
62 runtime_compiler_node_modules_cache:
63 name: Cache Runtime, Compiler node_modules
64 runs-on: ubuntu-latest
65 steps:
66 - uses: actions/checkout@v4
67 with:
68 ref: ${{ github.event.pull_request.head.sha || github.sha }}
69 - uses: actions/setup-node@v4
70 with:
71 node-version-file: '.nvmrc'
72 - name: Prepare cache
73 id: node_modules
74 uses: actions/cache@v4
75 with:
76 path: |
77 **/node_modules
78 key: runtime-and-compiler-node_modules-v10-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'compiler/yarn.lock') }}
79 # Don't use restore-keys here. Otherwise the cache grows indefinitely.
80 - run: yarn install --frozen-lockfile
81 if: steps.node_modules.outputs.cache-hit != 'true'
82 - run: yarn --cwd compiler install --frozen-lockfile
83 if: steps.node_modules.outputs.cache-hit != 'true'
84
85 # ----- BUILD WEIGHTS -----
86 # Pins one weights snapshot for the whole run. A cache restore with
87 # restore-keys returns the newest entry at call time, so 50 workers
88 # restoring individually can disagree when another run saves a new entry
89 # mid-fan-out, which scrambles the shard assignment and drops bundles from
90 # the build.
91 resolve_build_weights:
92 name: Resolve build shard weights
93 runs-on: ubuntu-latest
94 outputs:
95 available: ${{ steps.available.outputs.available }}
96 steps:
97 - name: Restore latest build shard weights
98 id: weights
99 uses: actions/cache/restore@v4
100 with:
101 # Must match the save step's path in process_artifacts_combined
102 # exactly: the cache version is a hash of the path, so a different
103 # path never matches the key.
104 path: build-weights.json
105 key: build-weights-v1-${{ github.run_id }}
106 restore-keys: build-weights-v1-
107 - id: available
108 run: echo "available=${{ steps.weights.outputs.cache-matched-key != '' }}" >> "$GITHUB_OUTPUT"
109 - name: Publish build shard weights for this run
110 if: steps.available.outputs.available == 'true'
111 uses: actions/upload-artifact@v4
112 with:
113 name: build-weights
114 path: build-weights.json
115 if-no-files-found: error
116
117 # ----- FLOW -----
118 discover_flow_inline_configs:
119 name: Discover flow inline configs
120 runs-on: ubuntu-latest
121 outputs:
122 matrix: ${{ steps.set-matrix.outputs.result }}
123 steps:
124 - uses: actions/checkout@v4
125 with:
126 ref: ${{ github.event.pull_request.head.sha || github.sha }}
127 - uses: actions/github-script@v7
128 id: set-matrix
129 with:
130 script: |
131 const inlinedHostConfigs = require('./scripts/shared/inlinedHostConfigs.js');
132 return inlinedHostConfigs.map(config => config.shortName);
133
134 flow:
135 name: Flow check ${{ matrix.flow_inline_config_shortname }}
136 needs: [discover_flow_inline_configs, runtime_node_modules_cache]
137 runs-on: ubuntu-latest
138 strategy:
139 fail-fast: false
140 matrix:
141 flow_inline_config_shortname: ${{ fromJSON(needs.discover_flow_inline_configs.outputs.matrix) }}
142 steps:
143 - uses: actions/checkout@v4
144 with:
145 ref: ${{ github.event.pull_request.head.sha || github.sha }}
146 - uses: actions/setup-node@v4
147 with:
148 node-version-file: '.nvmrc'
149 - name: Restore cached node_modules
150 uses: actions/cache/restore@v4
151 id: node_modules
152 with:
153 path: |
154 **/node_modules
155 key: runtime-node_modules-v10-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
156 # Don't use restore-keys here. Otherwise the cache grows indefinitely.
157 - name: Ensure clean build directory
158 run: rm -rf build
159 - run: yarn install --frozen-lockfile
160 if: steps.node_modules.outputs.cache-hit != 'true'
161 - run: node ./scripts/tasks/flow-ci ${{ matrix.flow_inline_config_shortname }}
162
163 # ----- FIZZ -----
164 check_generated_fizz_runtime:
165 name: Confirm generated inline Fizz runtime is up to date
166 needs: [runtime_node_modules_cache]
167 runs-on: ubuntu-latest
168 steps:
169 - uses: actions/checkout@v4
170 with:
171 ref: ${{ github.event.pull_request.head.sha || github.sha }}
172 - uses: actions/setup-node@v4
173 with:
174 node-version-file: '.nvmrc'
175 - name: Restore cached node_modules
176 uses: actions/cache/restore@v4
177 id: node_modules
178 with:
179 path: |
180 **/node_modules
181 key: runtime-node_modules-v10-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
182 # Don't use restore-keys here. Otherwise the cache grows indefinitely.
183 - name: Ensure clean build directory
184 run: rm -rf build
185 - run: yarn install --frozen-lockfile
186 if: steps.node_modules.outputs.cache-hit != 'true'
187 - run: |
188 yarn generate-inline-fizz-runtime
189 git diff --exit-code || (echo "There was a change to the Fizz runtime. Run \`yarn generate-inline-fizz-runtime\` and check in the result." && false)
190
191 # ----- FEATURE FLAGS -----
192 flags:
193 name: Check flags
194 needs: [runtime_node_modules_cache]
195 runs-on: ubuntu-latest
196 steps:
197 - uses: actions/checkout@v4
198 with:
199 ref: ${{ github.event.pull_request.head.sha || github.sha }}
200 - uses: actions/setup-node@v4
201 with:
202 node-version-file: '.nvmrc'
203 - name: Restore cached node_modules
204 uses: actions/cache/restore@v4
205 id: node_modules
206 with:
207 path: |
208 **/node_modules
209 key: runtime-node_modules-v10-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
210 - name: Ensure clean build directory
211 run: rm -rf build
212 - run: yarn install --frozen-lockfile
213 if: steps.node_modules.outputs.cache-hit != 'true'
214 - run: yarn flags
215
216 # ----- TESTS -----
217 test:
218 name: yarn test ${{ matrix.params }} (Shard ${{ matrix.shard }})
219 needs: [runtime_compiler_node_modules_cache]
220 runs-on: ubuntu-latest
221 strategy:
222 fail-fast: false
223 matrix:
224 params:
225 - "-r=stable --env=development"
226 - "-r=stable --env=production"
227 - "-r=experimental --env=development"
228 - "-r=experimental --env=production"
229 - "-r=www-classic --env=development --variant=false"
230 - "-r=www-classic --env=production --variant=false"
231 - "-r=www-classic --env=development --variant=true"
232 - "-r=www-classic --env=production --variant=true"
233 - "-r=www-modern --env=development --variant=false"
234 - "-r=www-modern --env=production --variant=false"
235 - "-r=www-modern --env=development --variant=true"
236 - "-r=www-modern --env=production --variant=true"
237 - "-r=xplat --env=development --variant=false"
238 - "-r=xplat --env=development --variant=true"
239 - "-r=xplat --env=production --variant=false"
240 - "-r=xplat --env=production --variant=true"
241 # TODO: Test more persistent configurations?
242 - "-r=stable --env=development --persistent"
243 - "-r=experimental --env=development --persistent"
244 shard:
245 - 1/5
246 - 2/5
247 - 3/5
248 - 4/5
249 - 5/5
250 steps:
251 - uses: actions/checkout@v4
252 with:
253 ref: ${{ github.event.pull_request.head.sha || github.sha }}
254 - uses: actions/setup-node@v4
255 with:
256 node-version-file: '.nvmrc'
257 - name: Restore cached node_modules
258 uses: actions/cache/restore@v4
259 id: node_modules
260 with:
261 path: |
262 **/node_modules
263 key: runtime-and-compiler-node_modules-v10-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'compiler/yarn.lock') }}
264 # Don't use restore-keys here. Otherwise the cache grows indefinitely.
265 - name: Ensure clean build directory
266 run: rm -rf build
267 - run: yarn install --frozen-lockfile
268 if: steps.node_modules.outputs.cache-hit != 'true'
269 - run: yarn --cwd compiler install --frozen-lockfile
270 if: steps.node_modules.outputs.cache-hit != 'true'
271 - run: node --version
272 - run: yarn test ${{ matrix.params }} --ci --shard=${{ matrix.shard }}
273
274 # Hardcoded to improve parallelism
275 test-linter:
276 name: Test eslint-plugin-react-hooks
277 needs: [runtime_compiler_node_modules_cache]
278 runs-on: ubuntu-latest
279 steps:
280 - uses: actions/checkout@v4
281 - uses: actions/setup-node@v4
282 with:
283 node-version-file: '.nvmrc'
284 - name: Restore cached node_modules
285 uses: actions/cache/restore@v4
286 id: node_modules
287 with:
288 path: |
289 **/node_modules
290 key: runtime-and-compiler-node_modules-v10-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'compiler/yarn.lock') }}
291 - name: Install runtime dependencies
292 run: yarn install --frozen-lockfile
293 if: steps.node_modules.outputs.cache-hit != 'true'
294 - name: Install compiler dependencies
295 run: yarn install --frozen-lockfile
296 working-directory: compiler
297 if: steps.node_modules.outputs.cache-hit != 'true'
298 - run: ./scripts/react-compiler/build-compiler.sh && ./scripts/react-compiler/link-compiler.sh
299 - run: yarn workspace eslint-plugin-react-hooks test
300
301 # ----- BUILD -----
302 build_and_lint:
303 name: yarn build and lint
304 needs: [runtime_compiler_node_modules_cache, resolve_build_weights]
305 runs-on: ubuntu-latest
306 strategy:
307 fail-fast: false
308 matrix:
309 # yml is dumb. update the --total arg to yarn build if you change the number of workers
310 worker_id: [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]
311 release_channel: [stable, experimental]
312 steps:
313 - uses: actions/checkout@v4
314 with:
315 ref: ${{ github.event.pull_request.head.sha || github.sha }}
316 # Java is only needed by `yarn build` (Closure Compiler), so its setup
317 # runs in the background while Node and node_modules are set up.
318 - name: Set up Java
319 id: setup_java
320 uses: actions/setup-java@v4
321 background: true
322 with:
323 distribution: temurin
324 java-version: 11.0.22
325 - uses: actions/setup-node@v4
326 with:
327 node-version-file: '.nvmrc'
328 - name: Restore cached node_modules
329 uses: actions/cache/restore@v4
330 id: node_modules
331 with:
332 path: |
333 **/node_modules
334 key: runtime-and-compiler-node_modules-v10-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'compiler/yarn.lock') }}
335 # Don't use restore-keys here. Otherwise the cache grows indefinitely.
336 - name: Ensure clean build directory
337 run: rm -rf build
338 - run: yarn install --frozen-lockfile
339 if: steps.node_modules.outputs.cache-hit != 'true'
340 - run: yarn --cwd compiler install --frozen-lockfile
341 if: steps.node_modules.outputs.cache-hit != 'true'
342 # Pinned once per run by resolve_build_weights so every worker computes
343 # the same shard assignment. Absent on a cold start; the build then
344 # falls back to round-robin sharding.
345 - name: Download build shard weights
346 if: needs.resolve_build_weights.outputs.available == 'true'
347 uses: actions/download-artifact@v4
348 with:
349 name: build-weights
350 # setup-java's exports (e.g. JAVA_HOME) only apply to steps after this wait.
351 - name: Wait for Java setup
352 wait: setup_java
353 - run: yarn build --index=${{ matrix.worker_id }} --total=25 --r=${{ matrix.release_channel }} --ci
354 env:
355 CI: github
356 RELEASE_CHANNEL: ${{ matrix.release_channel }}
357 NODE_INDEX: ${{ matrix.worker_id }}
358 BUILD_SHARD_WEIGHTS: build-weights.json
359 - name: Lint build
360 run: yarn lint-build
361 - name: Display structure of build
362 run: ls -R build
363 - name: Archive build
364 uses: actions/upload-artifact@v4
365 with:
366 name: _build_${{ matrix.worker_id }}_${{ matrix.release_channel }}
367 path: build
368 if-no-files-found: error
369
370 test_build:
371 name: yarn test-build
372 needs: [build_and_lint, runtime_compiler_node_modules_cache]
373 strategy:
374 fail-fast: false
375 matrix:
376 test_params: [
377 # Intentionally passing these as strings instead of creating a
378 # separate parameter per CLI argument, since it's easier to
379 # control/see which combinations we want to run.
380 -r=stable --env=development,
381 -r=stable --env=production,
382 -r=experimental --env=development,
383 -r=experimental --env=production,
384
385 # TODO: Update test config to support www build tests
386 # - "-r=www-classic --env=development --variant=false"
387 # - "-r=www-classic --env=production --variant=false"
388 # - "-r=www-classic --env=development --variant=true"
389 # - "-r=www-classic --env=production --variant=true"
390 # - "-r=www-modern --env=development --variant=false"
391 # - "-r=www-modern --env=production --variant=false"
392 # - "-r=www-modern --env=development --variant=true"
393 # - "-r=www-modern --env=production --variant=true"
394
395 # TODO: Update test config to support xplat build tests
396 # - "-r=xplat --env=development --variant=false"
397 # - "-r=xplat --env=development --variant=true"
398 # - "-r=xplat --env=production --variant=false"
399 # - "-r=xplat --env=production --variant=true"
400
401 # TODO: Test more persistent configurations?
402 ]
403 shard:
404 - 1/10
405 - 2/10
406 - 3/10
407 - 4/10
408 - 5/10
409 - 6/10
410 - 7/10
411 - 8/10
412 - 9/10
413 - 10/10
414 runs-on: ubuntu-latest
415 steps:
416 - uses: actions/checkout@v4
417 with:
418 ref: ${{ github.event.pull_request.head.sha || github.sha }}
419 - name: Ensure clean build directory
420 run: rm -rf build
421 # The build download runs in the background while Node is set up and
422 # node_modules is restored. The `wait` step below synchronizes on it.
423 # It must start after checkout, whose git clean would wipe `build/`.
424 - name: Restore archived build
425 id: download_build
426 uses: actions/download-artifact@v4
427 background: true
428 with:
429 pattern: _build_*
430 path: build
431 merge-multiple: true
432 - uses: actions/setup-node@v4
433 with:
434 node-version-file: '.nvmrc'
435 - name: Restore cached node_modules
436 uses: actions/cache/restore@v4
437 id: node_modules
438 with:
439 path: |
440 **/node_modules
441 key: runtime-and-compiler-node_modules-v10-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'compiler/yarn.lock') }}
442 # Don't use restore-keys here. Otherwise the cache grows indefinitely.
443 - run: yarn install --frozen-lockfile
444 if: steps.node_modules.outputs.cache-hit != 'true'
445 - run: yarn --cwd compiler install --frozen-lockfile
446 if: steps.node_modules.outputs.cache-hit != 'true'
447 - name: Wait for archived build
448 wait: download_build
449 - name: Display structure of build
450 run: ls -R build
451 - run: node --version
452 - run: yarn test --build ${{ matrix.test_params }} --shard=${{ matrix.shard }} --ci
453
454 test_build_devtools:
455 name: yarn test-build (devtools)
456 needs: [build_and_lint, runtime_node_modules_cache]
457 strategy:
458 fail-fast: false
459 matrix:
460 shard:
461 - 1/5
462 - 2/5
463 - 3/5
464 - 4/5
465 - 5/5
466 runs-on: ubuntu-latest
467 steps:
468 - uses: actions/checkout@v4
469 with:
470 ref: ${{ github.event.pull_request.head.sha || github.sha }}
471 - name: Ensure clean build directory
472 run: rm -rf build
473 - name: Restore archived build
474 id: download_build
475 uses: actions/download-artifact@v4
476 background: true
477 with:
478 pattern: _build_*
479 path: build
480 merge-multiple: true
481 - uses: actions/setup-node@v4
482 with:
483 node-version-file: '.nvmrc'
484 - name: Restore cached node_modules
485 uses: actions/cache/restore@v4
486 id: node_modules
487 with:
488 path: |
489 **/node_modules
490 key: runtime-node_modules-v10-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
491 # Don't use restore-keys here. Otherwise the cache grows indefinitely.
492 - run: yarn install --frozen-lockfile
493 if: steps.node_modules.outputs.cache-hit != 'true'
494 - name: Wait for archived build
495 wait: download_build
496 - name: Display structure of build
497 run: ls -R build
498 - run: node --version
499 - run: yarn test --build --project=devtools -r=experimental --shard=${{ matrix.shard }} --ci
500
501 process_artifacts_combined:
502 name: Process artifacts combined
503 needs: [build_and_lint, runtime_node_modules_cache, resolve_build_weights]
504 permissions:
505 # https://github.com/actions/attest-build-provenance
506 id-token: write
507 attestations: write
508 runs-on: ubuntu-latest
509 steps:
510 - uses: actions/checkout@v4
511 with:
512 ref: ${{ github.event.pull_request.head.sha || github.sha }}
513 - name: Ensure clean build directory
514 run: rm -rf build
515 - name: Restore archived build
516 id: download_build
517 uses: actions/download-artifact@v4
518 background: true
519 with:
520 pattern: _build_*
521 path: build
522 merge-multiple: true
523 - uses: actions/setup-node@v4
524 with:
525 node-version-file: '.nvmrc'
526 - name: Restore cached node_modules
527 uses: actions/cache/restore@v4
528 id: node_modules
529 with:
530 path: |
531 **/node_modules
532 key: runtime-node_modules-v10-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
533 # Don't use restore-keys here. Otherwise the cache grows indefinitely.
534 - run: yarn install --frozen-lockfile
535 if: steps.node_modules.outputs.cache-hit != 'true'
536 - name: Wait for archived build
537 wait: download_build
538 # Only used to log weight variance; the new measurement is what gets
539 # saved, so removed bundles drop out instead of accumulating. Downloads
540 # the run's pinned snapshot so the diff compares against the weights
541 # that actually drove this run's assignment.
542 - name: Download previous build shard weights
543 if: needs.resolve_build_weights.outputs.available == 'true'
544 uses: actions/download-artifact@v4
545 with:
546 name: build-weights
547 - name: Update build shard weights
548 run: node scripts/ci/merge-build-weights.js
549 - name: Save build shard weights
550 # Pull request saves land in the pull request's own merge-ref cache
551 # scope, which only that pull request can read; fork pull requests
552 # have a read-only cache token, so their save degrades to a warning.
553 # A re-run of this same workflow run reuses the cache key, and cache
554 # entries are immutable. Weights are an optimization, so a failed
555 # save must not break artifact processing.
556 continue-on-error: true
557 uses: actions/cache/save@v4
558 with:
559 path: build-weights.json
560 key: build-weights-v1-${{ github.run_id }}
561 # Keep the shard timings out of the released tarball.
562 - run: rm -rf build/__shard_timings__
563 - name: Display structure of build
564 run: ls -R build
565 - run: echo ${{ github.event.pull_request.head.sha || github.sha }} >> build/COMMIT_SHA
566 - name: Scrape warning messages
567 run: |
568 mkdir -p ./build/__test_utils__
569 node ./scripts/print-warnings/print-warnings.js > build/__test_utils__/ReactAllWarnings.js
570 # Compress build directory into a single tarball for easy download
571 - run: tar -zcvf ./build.tgz ./build
572 # TODO: Migrate scripts to use `build` directory instead of `build2`
573 - run: cp ./build.tgz ./build2.tgz
574 - name: Archive build artifacts
575 id: upload_artifacts_combined
576 uses: actions/upload-artifact@v4
577 with:
578 name: artifacts_combined
579 path: |
580 ./build.tgz
581 ./build2.tgz
582 if-no-files-found: error
583 - uses: actions/attest-build-provenance@v2
584 # We don't verify builds generated from pull requests not originating from react/react.
585 # However, if the PR lands, the run on release branches will generate the attestation which can then
586 # be used to download a build via scripts/release/download-experimental-build.js.
587 #
588 # Note that this means that scripts/release/download-experimental-build.js must be run with
589 # --no-verify when downloading a build from a fork.
590 if: github.event_name == 'push' && (github.ref_name == 'main' || startsWith(github.ref_name, 'releases/')) || github.event.pull_request.head.repo.full_name == github.repository
591 with:
592 subject-name: artifacts_combined.zip
593 subject-digest: sha256:${{ steps.upload_artifacts_combined.outputs.artifact-digest }}
594
595 check_error_codes:
596 name: Search build artifacts for unminified errors
597 needs: [build_and_lint, runtime_node_modules_cache]
598 runs-on: ubuntu-latest
599 steps:
600 - uses: actions/checkout@v4
601 with:
602 ref: ${{ github.event.pull_request.head.sha || github.sha }}
603 - name: Ensure clean build directory
604 run: rm -rf build
605 - name: Restore archived build
606 id: download_build
607 uses: actions/download-artifact@v4
608 background: true
609 with:
610 pattern: _build_*
611 path: build
612 merge-multiple: true
613 - uses: actions/setup-node@v4
614 with:
615 node-version-file: '.nvmrc'
616 - name: Restore cached node_modules
617 uses: actions/cache/restore@v4
618 id: node_modules
619 with:
620 path: |
621 **/node_modules
622 key: runtime-node_modules-v10-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
623 # Don't use restore-keys here. Otherwise the cache grows indefinitely.
624 - run: yarn install --frozen-lockfile
625 if: steps.node_modules.outputs.cache-hit != 'true'
626 - name: Wait for archived build
627 wait: download_build
628 - name: Display structure of build
629 run: ls -R build
630 - name: Search build artifacts for unminified errors
631 run: |
632 yarn extract-errors
633 git diff --exit-code || (echo "Found unminified errors. Either update the error codes map or disable error minification for the affected build, if appropriate." && false)
634
635 check_release_dependencies:
636 name: Check release dependencies
637 needs: [build_and_lint, runtime_node_modules_cache]
638 runs-on: ubuntu-latest
639 steps:
640 - uses: actions/checkout@v4
641 with:
642 ref: ${{ github.event.pull_request.head.sha || github.sha }}
643 - name: Ensure clean build directory
644 run: rm -rf build
645 - name: Restore archived build
646 id: download_build
647 uses: actions/download-artifact@v4
648 background: true
649 with:
650 pattern: _build_*
651 path: build
652 merge-multiple: true
653 - uses: actions/setup-node@v4
654 with:
655 node-version-file: '.nvmrc'
656 - name: Restore cached node_modules
657 uses: actions/cache/restore@v4
658 id: node_modules
659 with:
660 path: |
661 **/node_modules
662 key: runtime-node_modules-v10-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
663 # Don't use restore-keys here. Otherwise the cache grows indefinitely.
664 - run: yarn install --frozen-lockfile
665 if: steps.node_modules.outputs.cache-hit != 'true'
666 - name: Wait for archived build
667 wait: download_build
668 - name: Display structure of build
669 run: ls -R build
670 - run: yarn check-release-dependencies
671
672 RELEASE_CHANNEL_stable_yarn_test_dom_fixtures:
673 name: Check fixtures DOM (stable)
674 needs: build_and_lint
675 runs-on: ubuntu-latest
676 steps:
677 - uses: actions/checkout@v4
678 with:
679 ref: ${{ github.event.pull_request.head.sha || github.sha }}
680 - name: Ensure clean build directory
681 run: rm -rf build
682 - name: Restore archived build
683 id: download_build
684 uses: actions/download-artifact@v4
685 background: true
686 with:
687 pattern: _build_*
688 path: build
689 merge-multiple: true
690 - uses: actions/setup-node@v4
691 with:
692 node-version-file: '.nvmrc'
693 - name: Restore cached node_modules
694 uses: actions/cache@v4 # note: this does not reuse centralized cache since it has unique cache key
695 id: node_modules
696 with:
697 path: |
698 **/node_modules
699 key: fixtures_dom-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'fixtures/dom/yarn.lock') }}
700 - run: yarn --cwd fixtures/dom install --frozen-lockfile
701 if: steps.node_modules.outputs.cache-hit != 'true'
702 - name: Wait for archived build
703 wait: download_build
704 - name: Display structure of build
705 run: ls -R build
706 - name: Run DOM fixture tests
707 run: |
708 yarn predev
709 yarn test
710 working-directory: fixtures/dom
711 env:
712 RELEASE_CHANNEL: stable
713
714 # ----- FLIGHT -----
715 run_fixtures_flight_tests:
716 name: Run fixtures Flight tests
717 needs: build_and_lint
718 runs-on: ubuntu-latest
719 steps:
720 - uses: actions/checkout@v4
721 with:
722 ref: ${{ github.event.pull_request.head.sha || github.sha }}
723 - name: Ensure clean build directory
724 run: rm -rf build
725 - name: Restore archived build
726 id: download_build
727 uses: actions/download-artifact@v4
728 background: true
729 with:
730 pattern: _build_*
731 path: build
732 merge-multiple: true
733 - uses: actions/setup-node@v4
734 with:
735 node-version-file: '.nvmrc'
736 # Fixture copies some built packages from the workroot after install.
737 # That means dependencies of the built packages are not installed.
738 # We need to install dependencies of the workroot to fulfill all dependency constraints
739 - name: Restore cached node_modules
740 uses: actions/cache@v4 # note: this does not reuse centralized cache since it has unique cache key
741 id: node_modules
742 with:
743 path: |
744 **/node_modules
745 key: fixtures_flight-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'fixtures/flight/yarn.lock') }}
746 - run: yarn install --frozen-lockfile
747 if: steps.node_modules.outputs.cache-hit != 'true'
748 - run: yarn --cwd fixtures/flight install --frozen-lockfile
749 if: steps.node_modules.outputs.cache-hit != 'true'
750 - name: Check Playwright version
751 id: playwright_version
752 run: echo "playwright_version=$(npm ls @playwright/test | grep @playwright | sed 's/.*@//' | head -1)" >> "$GITHUB_OUTPUT"
753 - name: Cache Playwright Browsers for version ${{ steps.playwright_version.outputs.playwright_version }}
754 id: cache_playwright_browsers
755 uses: actions/cache@v4
756 with:
757 path: ~/.cache/ms-playwright
758 key: playwright-browsers-v6-${{ runner.arch }}-${{ runner.os }}-${{ steps.playwright_version.outputs.playwright_version }}
759 - name: Playwright install deps
760 if: steps.cache_playwright_browsers.outputs.cache-hit != 'true'
761 working-directory: fixtures/flight
762 run: npx playwright install --with-deps chromium
763 - name: Wait for archived build
764 wait: download_build
765 - name: Display structure of build
766 run: ls -R build
767 - name: Run tests
768 working-directory: fixtures/flight
769 run: yarn test
770 env:
771 # Otherwise the webserver is a blackbox
772 DEBUG: pw:webserver
773 - name: Archive Flight fixture artifacts
774 uses: actions/upload-artifact@v4
775 with:
776 name: flight-playwright-report
777 path: fixtures/flight/playwright-report
778 if-no-files-found: warn
779 - name: Archive Flight fixture artifacts
780 uses: actions/upload-artifact@v4
781 with:
782 name: flight-test-results
783 path: fixtures/flight/test-results
784 if-no-files-found: ignore
785
786 # ----- DEVTOOLS -----
787 build_devtools_and_process_artifacts:
788 name: Build DevTools and process artifacts
789 needs: [build_and_lint, runtime_node_modules_cache]
790 runs-on: ubuntu-latest
791 strategy:
792 fail-fast: false
793 matrix:
794 browser: [chrome, firefox, edge]
795 steps:
796 - uses: actions/checkout@v4
797 with:
798 ref: ${{ github.event.pull_request.head.sha || github.sha }}
799 - name: Ensure clean build directory
800 run: rm -rf build
801 - name: Restore archived build
802 id: download_build
803 uses: actions/download-artifact@v4
804 background: true
805 with:
806 pattern: _build_*
807 path: build
808 merge-multiple: true
809 - uses: actions/setup-node@v4
810 with:
811 node-version-file: '.nvmrc'
812 - name: Restore cached node_modules
813 uses: actions/cache/restore@v4
814 id: node_modules
815 with:
816 path: |
817 **/node_modules
818 key: runtime-node_modules-v10-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
819 # Don't use restore-keys here. Otherwise the cache grows indefinitely.
820 - run: yarn install --frozen-lockfile
821 if: steps.node_modules.outputs.cache-hit != 'true'
822 - name: Wait for archived build
823 wait: download_build
824 - run: ./scripts/ci/pack_and_store_devtools_artifacts.sh ${{ matrix.browser }}
825 env:
826 RELEASE_CHANNEL: experimental
827 - name: Display structure of build
828 run: ls -R build
829 # Simplifies getting the extension for local testing
830 - name: Archive ${{ matrix.browser }} extension
831 uses: actions/upload-artifact@v4
832 with:
833 name: react-devtools-${{ matrix.browser }}-extension
834 path: build/devtools/${{ matrix.browser }}-extension.zip
835 if-no-files-found: error
836 - name: Archive ${{ matrix.browser }} metadata
837 uses: actions/upload-artifact@v4
838 with:
839 name: react-devtools-${{ matrix.browser }}-metadata
840 path: build/devtools/webpack-stats.*.json
841
842 merge_devtools_artifacts:
843 name: Merge DevTools artifacts
844 needs: build_devtools_and_process_artifacts
845 runs-on: ubuntu-latest
846 steps:
847 - name: Merge artifacts
848 uses: actions/upload-artifact/merge@v4
849 with:
850 name: react-devtools
851 pattern: react-devtools-*
852
853 runtime_playwright_chromium_cache:
854 name: Cache Runtime Playwright Chromium
855 needs: runtime_node_modules_cache
856 runs-on: ubuntu-latest
857 outputs:
858 playwright_version: ${{ steps.playwright_version.outputs.playwright_version }}
859 steps:
860 - uses: actions/checkout@v4
861 with:
862 ref: ${{ github.event.pull_request.head.sha || github.sha }}
863 - uses: actions/setup-node@v4
864 with:
865 node-version-file: '.nvmrc'
866 - name: Restore cached node_modules
867 uses: actions/cache/restore@v4
868 id: node_modules
869 with:
870 path: |
871 **/node_modules
872 key: runtime-node_modules-v10-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
873 # Don't use restore-keys here. Otherwise the cache grows indefinitely.
874 - run: yarn install --frozen-lockfile
875 if: steps.node_modules.outputs.cache-hit != 'true'
876 - name: Check Playwright version
877 id: playwright_version
878 run: echo "playwright_version=$(npm ls @playwright/test | grep @playwright | sed 's/.*@//' | head -1)" >> "$GITHUB_OUTPUT"
879 - name: Cache Playwright Browsers for version ${{ steps.playwright_version.outputs.playwright_version }}
880 id: cache_playwright_browsers
881 uses: actions/cache@v4
882 with:
883 path: ~/.cache/ms-playwright
884 key: playwright-browsers-v6-${{ runner.arch }}-${{ runner.os }}-${{ steps.playwright_version.outputs.playwright_version }}
885 - name: Install Playwright Chromium
886 if: steps.cache_playwright_browsers.outputs.cache-hit != 'true'
887 run: npx playwright install chromium
888
889 run_devtools_e2e_tests:
890 name: Run React DevTools browser extension e2e tests
891 needs: [build_and_lint, runtime_playwright_chromium_cache]
892 runs-on: ubuntu-latest
893 steps:
894 - uses: actions/checkout@v4
895 with:
896 ref: ${{ github.event.pull_request.head.sha || github.sha }}
897 - name: Ensure clean build directory
898 run: rm -rf build
899 - name: Restore archived build
900 id: download_build
901 uses: actions/download-artifact@v4
902 background: true
903 with:
904 pattern: _build_*
905 path: build
906 merge-multiple: true
907 - uses: actions/setup-node@v4
908 with:
909 node-version-file: '.nvmrc'
910 - name: Restore cached node_modules
911 uses: actions/cache/restore@v4
912 id: node_modules
913 with:
914 path: |
915 **/node_modules
916 key: runtime-node_modules-v10-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
917 # Don't use restore-keys here. Otherwise the cache grows indefinitely.
918 - run: yarn install --frozen-lockfile
919 if: steps.node_modules.outputs.cache-hit != 'true'
920 - name: Restore Playwright Chromium
921 uses: actions/cache/restore@v4
922 with:
923 path: ~/.cache/ms-playwright
924 key: playwright-browsers-v6-${{ runner.arch }}-${{ runner.os }}-${{ needs.runtime_playwright_chromium_cache.outputs.playwright_version }}
925 fail-on-cache-miss: true
926 - name: Wait for archived build
927 wait: download_build
928 - run: ./scripts/ci/run_devtools_e2e_tests.js
929 env:
930 RELEASE_CHANNEL: experimental
931 - name: Archive Playwright report
932 uses: actions/upload-artifact@v4
933 with:
934 name: devtools-playwright-artifacts
935 path: tmp/playwright-artifacts
936 if-no-files-found: warn
937
938 run_react_devtools_cdt_mcp_e2e_tests:
939 name: Run react-devtools-cdt-mcp e2e tests
940 needs: [build_and_lint, runtime_playwright_chromium_cache]
941 runs-on: ubuntu-latest
942 steps:
943 - uses: actions/checkout@v4
944 with:
945 ref: ${{ github.event.pull_request.head.sha || github.sha }}
946 - name: Ensure clean build directory
947 run: rm -rf build
948 - name: Restore archived build
949 id: download_build
950 uses: actions/download-artifact@v4
951 background: true
952 with:
953 pattern: _build_*
954 path: build
955 merge-multiple: true
956 - uses: actions/setup-node@v4
957 with:
958 node-version-file: '.nvmrc'
959 - name: Restore cached node_modules
960 uses: actions/cache/restore@v4
961 id: node_modules
962 with:
963 path: |
964 **/node_modules
965 key: runtime-node_modules-v10-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
966 # Don't use restore-keys here. Otherwise the cache grows indefinitely.
967 - run: yarn install --frozen-lockfile
968 if: steps.node_modules.outputs.cache-hit != 'true'
969 - name: Restore Playwright Chromium
970 uses: actions/cache/restore@v4
971 with:
972 path: ~/.cache/ms-playwright
973 key: playwright-browsers-v6-${{ runner.arch }}-${{ runner.os }}-${{ needs.runtime_playwright_chromium_cache.outputs.playwright_version }}
974 fail-on-cache-miss: true
975 - name: Check Playwright Chromium version
976 id: playwright_chromium
977 run: |
978 echo "executable_path=$(node -e 'process.stdout.write(require("playwright").chromium.executablePath())')" >> "$GITHUB_OUTPUT"
979 "$(node -e 'process.stdout.write(require("playwright").chromium.executablePath())')" --version
980 - name: Wait for archived build
981 wait: download_build
982 - name: Run React DevTools CDT MCP e2e tests
983 run: yarn --cwd packages/react-devtools-cdt-mcp test:e2e:ci
984 env:
985 CHROME_EXECUTABLE_PATH: ${{ steps.playwright_chromium.outputs.executable_path }}
986 - name: Archive React DevTools CDT MCP e2e logs
987 if: failure()
988 uses: actions/upload-artifact@v4
989 with:
990 name: react-devtools-cdt-mcp-e2e-logs
991 path: tmp/react-devtools-cdt-mcp-e2e
992 if-no-files-found: warn
993
994 # ----- SIZEBOT -----
995 sizebot:
996 if: ${{ github.event_name == 'pull_request' && github.ref_name != 'main' && github.event.pull_request.base.ref == 'main' }}
997 name: Run sizebot
998 needs: [build_and_lint]
999 permissions:
1000 # We use github.token to download the build artifact from a previous runtime_build_and_test.yml run
1001 actions: read
1002 runs-on: ubuntu-latest
1003 steps:
1004 - uses: actions/checkout@v4
1005 with:
1006 ref: ${{ github.event.pull_request.head.sha || github.sha }}
1007 - uses: actions/setup-node@v4
1008 with:
1009 node-version-file: '.nvmrc'
1010 - name: Restore cached node_modules
1011 uses: actions/cache@v4 # note: this does not reuse centralized cache since it has unique cache key
1012 id: node_modules
1013 with:
1014 path: |
1015 **/node_modules
1016 key: runtime-release-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'scripts/release/yarn.lock') }}
1017 - name: Ensure clean build directory
1018 run: rm -rf build
1019 - run: yarn install --frozen-lockfile
1020 if: steps.node_modules.outputs.cache-hit != 'true'
1021 - run: yarn --cwd scripts/release install --frozen-lockfile
1022 if: steps.node_modules.outputs.cache-hit != 'true'
1023 - name: Download artifacts for base revision
1024 # The build could have been generated from a fork, so we must download the build without
1025 # any verification. This is safe since we only use this for sizebot calculation and the
1026 # unverified artifact is not used. Additionally this workflow runs in the pull_request
1027 # trigger so only restricted permissions are available.
1028 run: |
1029 GH_TOKEN=${{ github.token }} scripts/release/download-experimental-build.js --commit=$(git rev-parse ${{ github.event.pull_request.base.sha }}) ${{ (github.event.pull_request.head.repo.full_name != github.repository && '--noVerify') || ''}}
1030 mv ./build ./base-build
1031 - name: Delete extraneous files
1032 # TODO: The `download-experimental-build` script copies the npm
1033 # packages into the `node_modules` directory. This is a historical
1034 # quirk of how the release script works. Let's pretend they
1035 # don't exist.
1036 run: rm -rf ./base-build/node_modules
1037 - name: Display structure of base-build from origin/main
1038 run: ls -R base-build
1039 - name: Ensure clean build directory
1040 run: rm -rf build
1041 - name: Restore archived build for PR
1042 uses: actions/download-artifact@v4
1043 with:
1044 pattern: _build_*
1045 path: build
1046 merge-multiple: true
1047 - name: Scrape warning messages
1048 run: |
1049 mkdir -p ./build/__test_utils__
1050 node ./scripts/print-warnings/print-warnings.js > build/__test_utils__/ReactAllWarnings.js
1051 - name: Display structure of build for PR
1052 run: ls -R build
1053 - run: echo ${{ github.event.pull_request.head.sha || github.sha }} >> build/COMMIT_SHA
1054 - name: Measure size changes
1055 # Only measures and records the numbers. The comment is rendered and
1056 # posted by runtime_sizebot_comment.yml, which runs on the workflow_run
1057 # trigger because this job's token is read-only for pull requests from
1058 # forks and so cannot comment.
1059 run: node ./scripts/sizebot/compare-sizes.js
1060 - name: Archive sizebot results
1061 uses: actions/upload-artifact@v4
1062 with:
1063 name: sizebot-results
1064 path: sizebot-results.json
1065 if-no-files-found: error