Skip to content

Commit 0c67608

Browse files
Merge commit 'c99d96b7a1a4dc905ce642966633b4d3c78bd3c9' into main
Co-authored-by: Alicia Drummond <[email protected]>
2 parents 67a4a0f + c99d96b commit 0c67608

File tree

2,539 files changed

+152554
-113831
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

2,539 files changed

+152554
-113831
lines changed

.ado/templates/apple-steps-publish.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ steps:
4343
displayName: Run publish-npm.js
4444
inputs:
4545
script: |
46-
node ./scripts/publish-npm.js -t ${{ parameters.build_type }}
46+
node ./scripts/releases-ci/publish-npm.js -t ${{ parameters.build_type }}
4747
env:
4848
# Map the corresponding CircleCI variable since `publish-npm.js` depends on it.
4949
CIRCLE_TAG: $(RNM_PACKAGE_VERSION)

.buckconfig

Lines changed: 0 additions & 20 deletions
This file was deleted.

.buckjavaargs

Lines changed: 0 additions & 1 deletion
This file was deleted.

.circleci/README.md

Lines changed: 168 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,172 @@
11
# Circle CI
22

3-
This directory is home to the Circle CI configuration file. Circle is our continuous integration service provider. You can see the overall status of React Native's builds at https://circleci.com/gh/facebook/react-native
3+
This directory is home to the Circle CI configuration files. Circle is our continuous integration service provider. You can see the overall status of React Native's builds at https://circleci.com/gh/facebook/react-native
44

55
You may also see an individual PR's build status by scrolling down to the Checks section in the PR.
6+
7+
## Purposes
8+
9+
We use CircleCI for mainly 3 purposes:
10+
11+
1. Testing changes
12+
2. Release Nightlies
13+
3. Release Stable Versions of React Native
14+
15+
When testing changes, we run all the tests on commits that lands on `main`. For commits in PR, we try to understand which kind of changes the PR is about and we try to selectively run only the relevant tests. so, for example, if a PR only touches iOS files, we are going to run only iOS tests.
16+
17+
A Nighly job runs every day at around 9:00 PM, GMT. They run from `main` and they publish a version of React Native using the current state of the codebase, creating a version number that follows the format: `0.<current-version+1>.0-nightly-<YYYYMMDD>-<short-commit-hash>`.
18+
The nightly job also publish all the monorepo packages, taking care of updating the transitive dependencies of those packages.
19+
20+
Stable versions are released manually by the Release Crew and they run from a stable branch. Stable branches have the shape of `0.<version>-stable`.
21+
22+
## How It Works?
23+
24+
CircleCI execution is now split in two steps:
25+
- Setup
26+
- Testing
27+
28+
The setup step takes care of analyzing the changes in the PR and of deciding which jobs needs to run.
29+
30+
The testing flow is a set of workflows that executes the required tests.
31+
32+
### Setup
33+
34+
The code of the setup workflow lives in the root [`config.yml`](https://github.com/facebook/react-native/blob/main/.circleci/config.yml) file.
35+
It uses the `Continuation orb` from CircleCI to start a CI flow that depends on the changes present in the PR.
36+
37+
If the changes are not coming from a PR (either a simple commit or if the CI is running on main) **we always run all the tests** as a cautionary measure.
38+
39+
The setup job has also to expose all the pipeline parameters that we would need to pass to the actual workflow. Those parameters are **automatically forwarded** to the workflows that are started as a result of the setup.
40+
41+
The setup job uses a JS script to carry on its logic. The [`pipeline_selection.js`](https://github.com/facebook/react-native/blob/main/scripts/circleci/pipeline_selection.js) script can be invoked with two commands:
42+
- `filter-jobs`
43+
- `create-configs`
44+
45+
The **`filter-jobs`** command takes care of creating a JSON representation of the tests we need to run based on the changes in the PR.
46+
47+
The **`create-configs`** command consumes the JSON representation to create a CircleCI configuration that can then executes all the required tests.
48+
49+
#### Creating a Configuration
50+
51+
To create a configuration, the `pipeline-selection` scripts collates together various pieces of `YML` files that lives in the [`Configurations` folder](https://github.com/facebook/react-native/tree/main/.circleci/configurations).
52+
53+
The order in which these files are appended is **important** and it always contains the following.:
54+
55+
1. `top_level.yml`: this file contains some high level directives for CircleCI, like the version, the list of orbs, the cache-keys, and the pipeline parameters that can be used by the workflows.
56+
2. `executors.yml`: this file contains the list of the executors used in our jobs and their configurations.
57+
3. `commands.yml`: this file contains all the commands that can be used by jobs to executes. Commands are reusable functions that are shared by multiple jobs.
58+
4. `jobs.yml`: this file contains the jobs that are used by workflows to carry on some specific tasks. They are composed of sequential commands.
59+
5. `workflows.yml`: this file contains the shared workflows that needs to (or can) be always executed, no matter which kind of changes are pushed to CI. An example of these workflows is `analysis` (which is always executed) or `nightly` (which can be executed if a specific pipeline parameter is passed to the CI).
60+
61+
Then, the `pipeline_selection create-configs` attach some specific test workflows, depending on the changes that are present in the PR. These change-dependent workflows live in the [`test_workflows`](https://github.com/facebook/react-native/tree/main/.circleci/configurations/test_workflows) folder.
62+
These workflows are:
63+
* `testAll.yml` => runs all the possible tests. This workflow is executed on main and on PRs which change set touches both iOS and Android
64+
* `testAndroid.yml` => runs all the build steps and Android tests. This is used on changes that happens on the Android codebase and infra (`ReactAndroid` folder)
65+
* `testIOS.yml` => runs all the build steps and iOS tests. This is used on changes that happens on the iOS codebase and infra (`React` folder)
66+
* `testE2E.yml` => runs the E2E tests. As of today, E2E tests can be triggered if the commit message contains the `#run-e2e-tests` tag.
67+
* `testJS.yml` => For all the changes that do not touch native/platform code, we only run JS tests.
68+
69+
Notice that if there are changes on files that do not represents code (for example `.md` files like this one or the `Changelog`) we don't run any CI.
70+
71+
## Test workflows
72+
73+
The test workflows for native code are composed of 2 parts:
74+
- building React Native
75+
- testing
76+
77+
Building React Native requires us to build several parts of it:
78+
1. We need to build the Hermes JS engine
79+
2. We need to build Android to create prebuilds
80+
3. We need to package everything in an npm package that will mimic a React native release
81+
4. We need to create a local maven repository
82+
83+
### Building Hermes Engine
84+
85+
#### Android
86+
The `build_android` workflows takes care of building the Android version of Hermes and to put it properly in a local maven repository.
87+
See the [Build Android](#build_android) section below.
88+
89+
#### iOS
90+
Hermes is a very complicated item to build for iOS.
91+
It is composed of the Hermes compiler (HermesC) and of the actual engine.
92+
93+
Hermes is shipped as a universal XCFramework. This means that we need to build all the architecture slices and then put them together in the XCFramework archive.
94+
We also need to build 2 configurations: Debug and Release.
95+
96+
In order to be efficient and to save costs, we parallelize the process as much as possible:
97+
98+
1. We prepare the environment for building Hermes.
99+
2. We build HermesC which is required by all the slices.
100+
3. We start 8 jobs to build all the required slices in parallel:
101+
1. `iphone` slice, Debug mode
102+
1. `iphonesimulator` slice, Debug mode
103+
1. `macos` slice, Debug mode
104+
1. `catalyst` slice, Debug mode
105+
1. `iphone` slice, Release mode
106+
1. `iphonesimulator` slice, Release mode
107+
1. `macos` slice, Release mode
108+
1. `catalyst` slice, Release mode
109+
4. We then have 2 jobs to create the Debug and Release tarballs in parallel.
110+
1. The Debug job receives the 4 Debug slices
111+
1. The Release job receives the 4 Release slices
112+
113+
The `Debug` and `Release` tarball are then uploaded as artifacts. Notice that these we use these artifacts to **test the release** of React Native.
114+
115+
While building Hermes, we take also care of building the dSYMs. A dSYM (Debug Symbols) is an archive that contains the Debug Symbols that users can load to de-symbolicate the Hermes Stack traces. These symbols are published when we create a React Native release.
116+
117+
A lot of these build steps are automated by some shell scripts that lives in the [`react-native/packages/react-native/sdks/hermes-engine/utils` folder](https://github.com/facebook/react-native/tree/main/packages/react-native/sdks/hermes-engine/utils).
118+
119+
### Build Android
120+
121+
The android build is all managed by Gradle, so building android should be as easy as calling a [`gradle` command](https://github.com/facebook/react-native/blob/main/.circleci/configurations/jobs.yml#L268-L274).
122+
123+
The relevant part here is that the build android generates a `maven-local` repository that is passed to the [`build_npm_package`](https://github.com/facebook/react-native/blob/main/.circleci/configurations/jobs.yml#L1182) and that we use to test the releases.
124+
125+
### Build NPM package
126+
127+
This job is the responsible to create an NPM package that is suitable to be released or tested in CI.
128+
If we are in a release flow (for example the Nightly workflow), it also proceed with the publication.
129+
130+
The job can be invoked with different parameters:
131+
- `dry-run` => it does not publish anything, but prepare the artifacts to be used for testing
132+
- `nightly` => it creates the artifacts and publish a nightly version of React Native.
133+
- `release` => it creates the artifacts and publish a stable version of React Native.
134+
135+
The build NPM package takes all the artifacts produced in the previous steps (iOS' Hermes, iOS' Hermes dSYMs, Android's `maven-local`) and creates an npm package packing all the code.
136+
137+
If in a release mode, it also proceed publishing the NPM package to NPM, and the artifacts to Maven central, which we use to distribute all the artifacts.
138+
139+
This job also uploads the `maven-local` repository and a zipped version of the npm package to CircleCI's artifacts. We use these artifacts to **test the release** of React Native.
140+
141+
## Testing React Native
142+
React Native tests runs in two different scenarios:
143+
- RNTester
144+
- A New App
145+
146+
### RNTester
147+
RNTester is our internal testing app. It is a fully working React Native app that lives in the [`react-native/packages/rn-tester` folder](https://github.com/facebook/react-native/tree/main/packages/rn-tester) of the repository.
148+
RNTester is an app which contains code that exercise most part of the React Native frameworks.
149+
It also has the feature of building React Native **from source**. For that reason, it does not have to wait for the NPM package to be ready, but RNTester's tests can start as soon as the `build_android` step and the step that builds Hermes for iOS are done.
150+
151+
Notice the Tests on RNTester for iOS consumes the Hermes engine that is built in the previous steps.
152+
153+
For Android, these tests creates an APK that is uploaded as an artifact in CircleCI. We use these artifacts to **test the releases** of React Native..
154+
155+
### A New App
156+
The React Native repo contains a template app in the [`react-native/packages/react-native/template` folder]() that is used to spin up a new application that is preconfigured with React Native.
157+
158+
We have several tests that we run starting from the template, testing various configurations:
159+
- Debug/Release
160+
- JSC/Hermes (two different JS engine we support)
161+
- New/Old Architecture (two different Architectures for React Native)
162+
163+
We want to test all the React Native changes against the template, but we can't publish a React native version on each change that is merged. Therefore, to run tests on the template we use a NPM registry proxy called [Verdaccio](https://verdaccio.org/).
164+
165+
When running a Template test our CI follows roughly these steps:
166+
1. Prepare the executor
167+
2. Start a Verdaccio server
168+
3. Publish on Verdaccio all the monorepo [packages](https://github.com/facebook/react-native/tree/main/packages) on which React Native depends on.
169+
4. Publish on Verdaccio the react-native NPM package that has been created in the NPM step
170+
5. Spin up a new React native apps from the template, downloading react-native from Verdaccio.
171+
172+
In this way, we are sure that we can test all the changes that happen in React Native on a new React Native app.

.circleci/config.yml

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,16 @@ jobs:
3535
command: |
3636
apt update
3737
apt install -y wget git curl jq
38-
curl -sL https://deb.nodesource.com/setup_18.x | bash -
38+
39+
apt-get update
40+
apt-get install -y ca-certificates curl gnupg
41+
mkdir -p /etc/apt/keyrings
42+
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
43+
44+
NODE_MAJOR=18
45+
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list
46+
apt-get update
47+
3948
apt install -y nodejs
4049
npm install --global yarn
4150
- checkout
@@ -51,7 +60,7 @@ jobs:
5160
value: << pipeline.git.branch >>
5261
steps:
5362
- run:
54-
name: "[Main or Stable] Create input fo config to test everything"
63+
name: "[Main or Stable] Create input for config to test everything"
5564
command: |
5665
mkdir -p /tmp/circleci/
5766
echo '{ "run_all": true }' > /tmp/circleci/pipeline_config.json
@@ -69,9 +78,9 @@ jobs:
6978
command: |
7079
if [[ -z "$CIRCLE_PULL_REQUEST" ]]; then
7180
echo "Not in a PR. Can't filter properly outside a PR. Please open a PR so that we can run the proper CI tests."
72-
echo "Skipping!"
81+
echo "For safety, we run all the tests!"
7382
mkdir -p /tmp/circleci/
74-
echo '{}' > /tmp/circleci/pipeline_config.json
83+
echo '{ "run_all": true }' > /tmp/circleci/pipeline_config.json
7584
else
7685
PR_NUMBER="${CIRCLE_PULL_REQUEST##*/}"
7786
node ./scripts/circleci/pipeline_selection.js filter-jobs

.circleci/configurations/commands.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,6 @@ commands:
4646
echo "rbenv found; Skipping installation"
4747
fi
4848
49-
brew reinstall libyaml
50-
gem install psych -- --with-libyaml-dir=$(brew --prefix libyaml)
51-
export RUBY_CONFIGURE_OPTS=--with-libyaml-dir=$(brew --prefix libyaml)
52-
5349
# Install the right version of ruby
5450
if [[ -z "$(rbenv versions | grep << parameters.ruby_version >>)" ]]; then
5551
# ensure that `ruby-build` can see all the available versions of Ruby
@@ -61,7 +57,11 @@ commands:
6157
6258
# Set ruby dependencies
6359
rbenv global << parameters.ruby_version >>
64-
gem install bundler
60+
if [[ << parameters.ruby_version >> == "2.6.10" ]]; then
61+
gem install bundler -v 2.4.22
62+
else
63+
gem install bundler
64+
fi
6565
bundle check || bundle install --path vendor/bundle --clean
6666
- save_cache:
6767
key: *rbenv_cache_key
@@ -167,7 +167,7 @@ commands:
167167
steps:
168168
- run:
169169
name: "Run Tests: << parameters.platform >> End-to-End Tests"
170-
command: node ./scripts/run-ci-e2e-tests.js --<< parameters.platform >> --retries << parameters.retries >>
170+
command: node ./scripts/e2e/run-ci-e2e-tests.js --<< parameters.platform >> --retries << parameters.retries >>
171171

172172
report_bundle_size:
173173
parameters:

.circleci/configurations/executors.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,10 @@ executors:
3636
resource_class: macos.x86.medium.gen2
3737
environment:
3838
- BUILD_FROM_SOURCE: true
39+
reactnativeios-lts:
40+
<<: *defaults
41+
macos:
42+
xcode: '14.3.1'
43+
resource_class: macos.x86.medium.gen2
44+
environment:
45+
- BUILD_FROM_SOURCE: true

0 commit comments

Comments
 (0)