Skip to content

Commit c540ff7

Browse files
kelsetfacebook-github-bot
authored andcommitted
fix(local-e2e-script): add logic to handle maven local for iOS and Android accordingly (facebook#35104)
Summary: This PR is a follow up of facebook#35075 and facebook@1546666 to ensure that even in the local e2e testing scenario the new maven approach is followed - without this, RNTestProject on Android won't work, like so: <img width="1905" alt="Screenshot 2022-10-27 at 12 15 38" src="https://user-images.githubusercontent.com/16104054/198334105-30fb2037-4e7c-4814-8c3f-2412ba0bd49f.png"> And iOS will always build everything from source every time. This PR addresses both by generating the artifacts locally, and passing them to RNTestProject as if they were coming from a url (mimicking as closely as possible the behaviour for the final user) In doing so, there's been some refactoring to prep the ground for follow up work. * refactor CI to rely less on scripts directly in the CircleCI config, but invoke .js ones * we should be able to trigger more the "manual" artifacts generation so that it will only happen once between RNTester and RNTestProject, and we can pass existing artifacts to the other flows. * once all of this in place, a very good improvement would be to be able to download the maven artifacts kind of like nightlies and stables do. This will only be viable by checking that there's no local changes, after which there needs to be logic to pull down from CircleCI the artifacts based on git commit <-> circleCI job references. --- While at it, I've also fixed the hermes-engine podspec logic for detecting if it's on CI: basically the local e2e script needs to align with the changes done here: facebook@4b51207 but as you can see there, the condition was actually inconsistent across the various files, so realigned to `CI === 'true'`. We probably didn't catch that so far 'cause the other condition in the hermes podspect (existence of `hermestag_file`) is only true on release branches and this new logic has not been in any release branches yet. ## Changelog <!-- Help reviewers and the release process by writing your own changelog entry. For an example, see: https://reactnative.dev/contributing/changelogs-in-pull-requests --> [Internal] [Fixed] - add logic to local e2e script to handle maven local for iOS and Android accordingly Pull Request resolved: facebook#35104 Test Plan: Run ` yarn test-e2e-local -t RNTestProject -p Android` successfully. Run ` yarn test-e2e-local -t RNTestProject -p iOS` successfully. On the pod install stage, you will see `[Hermes] Using pre-built Hermes binaries from local path.` Reviewed By: dmytrorykun Differential Revision: D40893239 Pulled By: cipolleschi fbshipit-source-id: a31217ec4f177383c62292d00fabc4cbe4391cfd
1 parent 0fd282f commit c540ff7

File tree

7 files changed

+119
-35
lines changed

7 files changed

+119
-35
lines changed

scripts/release-utils.js

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@
99

1010
'use strict';
1111

12-
const {exec, echo, exit, test, env} = require('shelljs');
12+
const {exec, echo, exit, test, env, pushd, popd} = require('shelljs');
1313
const {saveFiles} = require('./scm-utils');
14+
const {createHermesPrebuiltArtifactsTarball} = require('./hermes/hermes-utils');
1415

16+
// TODO: we should probably remove this because of this? https://github.com/facebook/react-native/pull/34846
1517
function saveFilesToRestore(tmpPublishingFolder) {
1618
const filesToSaveAndRestore = [
1719
'template/Gemfile',
@@ -94,8 +96,45 @@ function publishAndroidArtifactsToMaven(releaseVersion, isNightly) {
9496
echo('Published artifacts to Maven Central');
9597
}
9698

99+
function generateiOSArtifacts(
100+
jsiFolder,
101+
hermesCoreSourceFolder,
102+
buildType,
103+
releaseVersion,
104+
targetFolder,
105+
) {
106+
pushd(`${hermesCoreSourceFolder}`);
107+
108+
//Need to generate hermesc
109+
exec(
110+
`${hermesCoreSourceFolder}/utils/build-hermesc-xcode.sh ${hermesCoreSourceFolder}/build_host_hermesc`,
111+
);
112+
113+
//Generating iOS Artifacts
114+
exec(
115+
`JSI_PATH=${jsiFolder} BUILD_TYPE=${buildType} ${hermesCoreSourceFolder}/utils/build-mac-framework.sh`,
116+
);
117+
118+
exec(
119+
`JSI_PATH=${jsiFolder} BUILD_TYPE=${buildType} ${hermesCoreSourceFolder}/utils/build-ios-framework.sh`,
120+
);
121+
122+
popd();
123+
124+
const tarballOutputPath = createHermesPrebuiltArtifactsTarball(
125+
hermesCoreSourceFolder,
126+
buildType,
127+
releaseVersion,
128+
targetFolder,
129+
true, // this is excludeDebugSymbols, we keep it as the default
130+
);
131+
132+
return tarballOutputPath;
133+
}
134+
97135
module.exports = {
98136
generateAndroidArtifacts,
137+
generateiOSArtifacts,
99138
publishAndroidArtifactsToMaven,
100139
saveFilesToRestore,
101140
};

scripts/test-e2e-local-clean.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ if (isPackagerRunning() === 'running') {
4343
// Android
4444
console.info('\n** Cleaning Gradle build artifacts **\n');
4545
exec('./gradlew cleanAll');
46+
exec('rm -rf /tmp/maven-local');
4647

4748
// iOS
4849
console.info('\n** Nuking the derived data folder **\n');

scripts/test-e2e-local.js

Lines changed: 76 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
* and to make it more accessible for other devs to play around with.
1717
*/
1818

19-
const {exec, exit, pushd, popd, pwd, cd} = require('shelljs');
19+
const {exec, exit, pushd, popd, pwd, cd, cp} = require('shelljs');
2020
const yargs = require('yargs');
2121
const fs = require('fs');
2222
const path = require('path');
@@ -31,8 +31,14 @@ const {
3131
const {
3232
generateAndroidArtifacts,
3333
saveFilesToRestore,
34+
generateiOSArtifacts,
3435
} = require('./release-utils');
3536

37+
const {
38+
downloadHermesSourceTarball,
39+
expandHermesSourceTarball,
40+
} = require('./hermes/hermes-utils');
41+
3642
const argv = yargs
3743
.option('t', {
3844
alias: 'target',
@@ -65,6 +71,12 @@ if (isPackagerRunning() === 'running') {
6571
exec("lsof -i :8081 | grep LISTEN | /usr/bin/awk '{print $2}' | xargs kill");
6672
}
6773

74+
const onReleaseBranch = exec('git rev-parse --abbrev-ref HEAD', {
75+
silent: true,
76+
})
77+
.stdout.trim()
78+
.endsWith('-stable');
79+
6880
if (argv.target === 'RNTester') {
6981
// FIXME: make sure that the commands retains colors
7082
// (--ansi) doesn't always work
@@ -76,10 +88,15 @@ if (argv.target === 'RNTester') {
7688
argv.hermes ? 'Hermes' : 'JSC'
7789
} version of RNTester iOS with the new Architecture enabled`,
7890
);
91+
92+
// remember that for this to be successful
93+
// you should have run bundle install once
94+
// in your local setup - also: if I'm on release branch, I pick the
95+
// hermes ref from the hermes ref file (see hermes-engine.podspec)
7996
exec(
8097
`cd packages/rn-tester && USE_HERMES=${
8198
argv.hermes ? 1 : 0
82-
} RCT_NEW_ARCH_ENABLED=1 bundle exec pod install --ansi`,
99+
} CI=${onReleaseBranch} RCT_NEW_ARCH_ENABLED=1 bundle exec pod install --ansi`,
83100
);
84101

85102
// if everything succeeded so far, we can launch Metro and the app
@@ -113,12 +130,14 @@ if (argv.target === 'RNTester') {
113130
// if everything succeeded so far, we can launch Metro and the app
114131
// start the Metro server in a separate window
115132
launchPackagerInSeparateWindow();
116-
// just to make sure that the Android up won't have troubles finding the Metro server
117-
exec('adb reverse tcp:8081 tcp:8081');
133+
118134
// launch the app
119135
exec(
120136
'adb shell am start -n com.facebook.react.uiapp/com.facebook.react.uiapp.RNTesterActivity',
121137
);
138+
139+
// just to make sure that the Android up won't have troubles finding the Metro server
140+
exec('adb reverse tcp:8081 tcp:8081');
122141
}
123142
} else {
124143
console.info("We're going to test a fresh new RN project");
@@ -147,50 +166,75 @@ if (argv.target === 'RNTester') {
147166
// this is needed to generate the Android artifacts correctly
148167
exec(`node scripts/set-rn-version.js --to-version ${releaseVersion}`).code;
149168

150-
// Generate native files (Android only for now)
169+
// Generate native files for Android
151170
generateAndroidArtifacts(releaseVersion, tmpPublishingFolder);
152171

172+
// Setting up generating native iOS (will be done later)
173+
const repoRoot = pwd();
174+
const jsiFolder = `${repoRoot}/ReactCommon/jsi`;
175+
const hermesCoreSourceFolder = `${repoRoot}/sdks/hermes`;
176+
177+
if (!fs.existsSync(hermesCoreSourceFolder)) {
178+
console.info('The Hermes source folder is missing. Downloading...');
179+
downloadHermesSourceTarball();
180+
expandHermesSourceTarball();
181+
}
182+
183+
// need to move the scripts inside the local hermes cloned folder
184+
// cp sdks/hermes-engine/utils/*.sh <your_hermes_checkout>/utils/.
185+
cp(
186+
`${repoRoot}/sdks/hermes-engine/utils/*.sh`,
187+
`${repoRoot}/sdks/hermes/utils/.`,
188+
);
189+
190+
// for this scenario, we only need to create the debug build
191+
// (env variable PRODUCTION defines that podspec side)
192+
const buildType = 'Debug';
193+
194+
// the android ones get set into /private/tmp/maven-local
195+
const localMavenPath = '/private/tmp/maven-local';
196+
197+
// Generate native files for iOS
198+
const tarballOutputPath = generateiOSArtifacts(
199+
jsiFolder,
200+
hermesCoreSourceFolder,
201+
buildType,
202+
releaseVersion,
203+
localMavenPath,
204+
);
205+
153206
// create locally the node module
154207
exec('npm pack');
155208

156-
const localNodeTGZPath = `${pwd()}/react-native-${releaseVersion}.tgz`;
209+
const localNodeTGZPath = `${repoRoot}/react-native-${releaseVersion}.tgz`;
157210
exec(`node scripts/set-rn-template-version.js "file:${localNodeTGZPath}"`);
158211

159-
const repoRoot = pwd();
160-
161212
pushd('/tmp/');
162-
// need to avoid the pod install step because it will fail! (see above)
213+
// need to avoid the pod install step - we'll do it later
163214
exec(
164215
`node ${repoRoot}/cli.js init RNTestProject --template ${repoRoot} --skip-install`,
165216
);
166217

167218
cd('RNTestProject');
168219
exec('yarn install');
169220

221+
// need to do this here so that Android will be properly setup either way
222+
exec(
223+
'echo "REACT_NATIVE_MAVEN_LOCAL_REPO=/private/tmp/maven-local" >> android/gradle.properties',
224+
);
225+
226+
// doing the pod install here so that it's easier to play around RNTestProject
227+
cd('ios');
228+
exec('bundle install');
229+
exec(
230+
`HERMES_ENGINE_TARBALL_PATH=${tarballOutputPath} USE_HERMES=${
231+
argv.hermes ? 1 : 0
232+
} bundle exec pod install --ansi`,
233+
);
234+
235+
cd('..');
236+
170237
if (argv.platform === 'iOS') {
171-
// if we want iOS, we need to do pod install - but with a trick
172-
cd('ios');
173-
exec('bundle install');
174-
175-
// TODO: we should be able to also use HERMES_ENGINE_TARBALL_PATH
176-
// if we can make RNTester step generate it already so that it gets reused
177-
178-
// need to discern if it's main branch or release branch
179-
if (baseVersion === '1000.0.0') {
180-
// main branch
181-
exec(`USE_HERMES=${argv.hermes ? 1 : 0} bundle exec pod install --ansi`);
182-
} else {
183-
// TODO: to test this, I need to apply changes on top of a release branch
184-
// a release branch
185-
// copy over the .hermesversion file from react-native core into the RNTestProject
186-
exec(`cp -f ${repoRoot}/sdks/.hermesversion .`);
187-
exec(
188-
`CI=true USE_HERMES=${
189-
argv.hermes ? 1 : 0
190-
} bundle exec pod install --ansi`,
191-
);
192-
}
193-
cd('..');
194238
exec('yarn ios');
195239
} else {
196240
// android

sdks/hermes-engine/hermes-engine.podspec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ version = package['version']
1717

1818
# sdks/.hermesversion
1919
hermestag_file = File.join(react_native_path, "sdks", ".hermesversion")
20-
isInCI = ENV['CI'] == true
20+
isInCI = ENV['CI'] === 'true'
2121

2222
source = {}
2323
git = "https://github.com/facebook/hermes.git"
@@ -38,7 +38,7 @@ elsif isNightly
3838
# set tarball as hermes engine
3939
source[:http] = "file://#{destination_path}"
4040
elsif File.exists?(hermestag_file) && isInCI
41-
Pod::UI.puts '[Hermes] Detected that you are on a React Native release branch, building Hermes from source...'.yellow if Object.const_defined?("Pod::UI")
41+
Pod::UI.puts '[Hermes] Detected that you are on a React Native release branch, building Hermes from source but fetched from tag...'.yellow if Object.const_defined?("Pod::UI")
4242
hermestag = File.read(hermestag_file).strip
4343
source[:git] = git
4444
source[:tag] = hermestag

sdks/hermes-engine/utils/build-hermes-xcode.sh

100644100755
File mode changed.

sdks/hermes-engine/utils/build-hermesc-xcode.sh

100644100755
File mode changed.

sdks/hermes-engine/utils/copy-hermes-xcode.sh

100644100755
File mode changed.

0 commit comments

Comments
 (0)