Skip to content
This repository was archived by the owner on May 20, 2025. It is now read-only.

Commit 3bb71ea

Browse files
authored
Update create app.js (#1760)
1 parent 14810b7 commit 3bb71ea

File tree

2 files changed

+149
-62
lines changed

2 files changed

+149
-62
lines changed

.github/ISSUE_TEMPLATE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ What actually happens?
1616

1717
### Reproducible Demo
1818

19-
* Download https://github.com/Microsoft/react-native-code-push/archive/master.zip and unzip. From `Examples` folder run `node create-app.js appName react-native@0.47.1 react-native-code-push@5.0.0-beta` command to generate plain CodePushified React Native app. Please see description on top of `create-app.js` file content if needed
19+
* Download https://github.com/Microsoft/react-native-code-push/archive/master.zip and unzip. From `Examples` folder run `node create-app.js appName react-native@0.61.5 react-native-code-push@6.0.0` command to generate plain CodePushified React Native app. Please see description on top of `create-app.js` file content if needed
2020
* If you can't reproduce the bug on it, provide us as much info as possible about your project
2121

2222
### Environment

Examples/create-app.js

Lines changed: 148 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@ The script serves to generate CodePushified React Native app to reproduce issues
33
44
Requirements:
55
1. npm i -g react-native-cli
6-
2. npm i -g code-push-cli
7-
3. code-push register
6+
2. npm i -g appcenter-cli
7+
3. appcenter login
8+
(If you use this script on macOS for react-native v0.60+ then you need to have CocoaPods installed)
89
910
Usage: node create-app.js <appName> <reactNativeVersion> <reactNativeCodePushVersion>
1011
1. node create-app.js
1112
2. node create-app.js myapp
12-
3. node create-app.js myapp react-native@0.47.1 react-native-code-push@5.0.0-beta
13+
3. node create-app.js myapp react-native@0.61.5 react-native-code-push@6.0.0
1314
4. node create-app.js myapp react-native@latest Microsoft/react-native-code-push
1415
1516
Parameters:
@@ -18,14 +19,14 @@ Parameters:
1819
3. <reactNativeCodePushVersion> - react-native-code-push@latest
1920
*/
2021

21-
let fs = require('fs');
22-
let path = require('path');
23-
let nexpect = require('./nexpect');
24-
let child_proces = require('child_process');
25-
let execSync = child_proces.execSync;
22+
const fs = require('fs');
23+
const path = require('path');
24+
const nexpect = require('./nexpect');
25+
const child_process = require('child_process');
26+
const execSync = child_process.execSync;
2627

27-
let args = process.argv.slice(2);
28-
let appName = args[0] || 'CodePushDemoAppTest';
28+
const args = process.argv.slice(2);
29+
const appName = args[0] || 'CodePushDemoAppTest';
2930

3031
if (fs.existsSync(appName)) {
3132
console.error(`Folder with name "${appName}" already exists! Please delete`);
@@ -34,17 +35,18 @@ if (fs.existsSync(appName)) {
3435

3536
// Checking if yarn is installed
3637
try {
37-
execSync('yarn bin');
38+
execCommand('yarn bin');
3839
} catch (err) {
3940
console.error(`You must install 'yarn' to use this script!`);
4041
process.exit();
4142
}
4243

43-
let appNameAndroid = `${appName}-android`;
44-
let appNameIOS = `${appName}-ios`;
45-
let reactNativeVersion = args[1] || `react-native@${execSync('npm view react-native version')}`.trim();
46-
let reactNativeVersionIsLowerThanV049 = isReactNativeVesionLowerThan(49);
47-
let reactNativeCodePushVersion = args[2] || `react-native-code-push@${execSync('npm view react-native-code-push version')}`.trim();
44+
const appNameAndroid = `${appName}-android`;
45+
const appNameIOS = `${appName}-ios`;
46+
let owner = null;
47+
const reactNativeVersion = args[1] || `react-native@${execCommand('npm view react-native version')}`.trim();
48+
const reactNativeVersionIsLowerThanV049 = isReactNativeVersionLowerThan(49);
49+
const reactNativeCodePushVersion = args[2] || `react-native-code-push@${execCommand('npm view react-native-code-push version')}`.trim();
4850

4951
console.log(`App name: ${appName}`);
5052
console.log(`React Native version: ${reactNativeVersion}`);
@@ -56,8 +58,8 @@ let iosStagingDeploymentKey = null;
5658

5759

5860
//GENERATE START
59-
createCodePushApp(appNameAndroid, 'android');
60-
createCodePushApp(appNameIOS, 'ios');
61+
createCodePushApp(appNameAndroid, 'Android');
62+
createCodePushApp(appNameIOS, 'iOS');
6163

6264
generatePlainReactNativeApp(appName, reactNativeVersion);
6365
process.chdir(appName);
@@ -67,57 +69,72 @@ linkCodePush(androidStagingDeploymentKey, iosStagingDeploymentKey);
6769

6870

6971

70-
function createCodePushApp(name, platform) {
72+
function createCodePushApp(name, os) {
7173
try {
72-
console.log(`Creating CodePush app "${name}" to release updates for ${platform}...`);
73-
execSync(`code-push app add ${name} ${platform} react-native`);
74+
console.log(`Creating CodePush app "${name}" to release updates for ${os}...`);
75+
const appResult = execCommand(`appcenter apps create -d ${name} -n ${name} -o ${os} -p React-Native --output json`);
76+
const app = JSON.parse(appResult);
77+
owner = app.owner.name;
7478
console.log(`App "${name}" has been created \n`);
79+
execCommand(`appcenter codepush deployment add -a ${owner}/${name} Staging`);
7580
} catch (e) {
7681
console.log(`App "${name}" already exists \n`);
7782
}
78-
let deploymentKeys = JSON.parse(execSync(`code-push deployment ls ${name} -k --format json`));
79-
let stagingDeploymentKey = deploymentKeys[1].key;
80-
console.log(`Deployment key for ${platform}: ${stagingDeploymentKey}`);
81-
console.log(`Use "code-push release-react ${name} ${platform}" command to release updates for ${platform} \n`);
82-
83-
switch (platform) {
84-
case 'android':
83+
const deploymentKeysResult = execCommand(`appcenter codepush deployment list -a ${owner}/${name} -k --output json`);
84+
const deploymentKeys = JSON.parse(deploymentKeysResult);
85+
const stagingDeploymentKey = deploymentKeys[0][1];
86+
console.log(`Deployment key for ${os}: ${stagingDeploymentKey}`);
87+
console.log(`Use "appcenter codepush release-react ${owner}/${name}" command to release updates for ${os} \n`);
88+
89+
switch (os) {
90+
case 'Android':
8591
androidStagingDeploymentKey = stagingDeploymentKey;
8692
break;
87-
case 'ios':
93+
case 'iOS':
8894
iosStagingDeploymentKey = stagingDeploymentKey;
8995
break;
9096
}
9197
}
9298

9399
function generatePlainReactNativeApp(appName, reactNativeVersion) {
94100
console.log(`Installing React Native...`);
95-
execSync(`react-native init ${appName} --version ${reactNativeVersion}`);
101+
execCommand(`react-native init ${appName} --version ${reactNativeVersion}`);
96102
console.log(`React Native has been installed \n`);
97103
}
98104

99105
function installCodePush(reactNativeCodePushVersion) {
100106
console.log(`Installing React Native Module for CodePush...`);
101-
execSync(`yarn add ${reactNativeCodePushVersion}`);
107+
execCommand(`yarn add ${reactNativeCodePushVersion}`);
102108
console.log(`React Native Module for CodePush has been installed \n`);
103109
}
104110

105111
function linkCodePush(androidStagingDeploymentKey, iosStagingDeploymentKey) {
106112
console.log(`Linking React Native Module for CodePush...`);
107-
nexpect.spawn(`react-native link react-native-code-push`)
108-
.wait("What is your CodePush deployment key for Android (hit <ENTER> to ignore)")
109-
.sendline(androidStagingDeploymentKey)
110-
.wait("What is your CodePush deployment key for iOS (hit <ENTER> to ignore)")
111-
.sendline(iosStagingDeploymentKey)
112-
.run(function (err) {
113-
if (!err) {
114-
console.log(`React Native Module for CodePush has been linked \n`);
115-
setupAssets();
116-
}
117-
else {
118-
console.log(err);
119-
}
120-
});
113+
if (isReactNativeVersionLowerThan(60)) {
114+
nexpect.spawn(`react-native link react-native-code-push`)
115+
.wait("What is your CodePush deployment key for Android (hit <ENTER> to ignore)")
116+
.sendline(androidStagingDeploymentKey)
117+
.wait("What is your CodePush deployment key for iOS (hit <ENTER> to ignore)")
118+
.sendline(iosStagingDeploymentKey)
119+
.run(function (err) {
120+
if (!err) {
121+
console.log(`React Native Module for CodePush has been linked \n`);
122+
setupAssets();
123+
}
124+
else {
125+
console.log(err);
126+
}
127+
});
128+
} else {
129+
androidSetup();
130+
if (process.platform === 'darwin') {
131+
iosSetup();
132+
} else {
133+
console.log('Your OS is not "Mac OS" so the iOS application will not be configured')
134+
}
135+
setupAssets();
136+
console.log(`React Native Module for CodePush has been linked \n`);
137+
}
121138
}
122139

123140
function setupAssets() {
@@ -142,7 +159,7 @@ function setupAssets() {
142159
if (err) {
143160
return console.error(err);
144161
}
145-
var result = data.replace(/CodePushDemoApp/g, appName);
162+
const result = data.replace(/CodePushDemoApp/g, appName);
146163

147164
fs.writeFile(fileToEdit, result, 'utf8', function (err) {
148165
if (err) return console.error(err);
@@ -159,31 +176,31 @@ function setupAssets() {
159176
}
160177

161178
function optimizeToTestInDebugMode() {
162-
let rnXcodeShLocationFolder = 'scripts';
179+
const rnXcodeShLocationFolder = 'scripts';
163180
try {
164-
let rnVersions = JSON.parse(execSync(`npm view react-native versions --json`));
165-
let currentRNversion = JSON.parse(fs.readFileSync('./package.json'))['dependencies']['react-native'];
181+
const rnVersions = JSON.parse(execCommand(`npm view react-native versions --json`));
182+
const currentRNversion = JSON.parse(fs.readFileSync('./package.json'))['dependencies']['react-native'];
166183
if (rnVersions.indexOf(currentRNversion) > -1 &&
167184
rnVersions.indexOf(currentRNversion) < rnVersions.indexOf("0.46.0-rc.0")) {
168185
rnXcodeShLocationFolder = 'packager';
169186
}
170-
} catch(e) {}
187+
} catch (e) { }
171188

172-
let rnXcodeShPath = `node_modules/react-native/${rnXcodeShLocationFolder}/react-native-xcode.sh`;
189+
const rnXcodeShPath = `node_modules/react-native/${rnXcodeShLocationFolder}/react-native-xcode.sh`;
173190
// Replace "if [[ "$PLATFORM_NAME" == *simulator ]]; then" with "if false; then" to force bundling
174-
execSync(`sed -ie 's/if \\[\\[ "\$PLATFORM_NAME" == \\*simulator \\]\\]; then/if false; then/' ${rnXcodeShPath}`);
175-
execSync(`perl -i -p0e 's/#ifdef DEBUG.*?#endif/jsCodeLocation = [CodePush bundleURL];/s' ios/${appName}/AppDelegate.m`);
176-
execSync(`sed -ie 's/targetName.toLowerCase().contains("release")/true/' node_modules/react-native/react.gradle`);
191+
execCommand(`sed -ie 's/if \\[\\[ "\$PLATFORM_NAME" == \\*simulator \\]\\]; then/if false; then/' ${rnXcodeShPath}`);
192+
execCommand(`perl -i -p0e 's/#ifdef DEBUG.*?#endif/jsCodeLocation = [CodePush bundleURL];/s' ios/${appName}/AppDelegate.m`);
193+
execCommand(`sed -ie 's/targetName.toLowerCase().contains("release")/true/' node_modules/react-native/react.gradle`);
177194
}
178195

179196
function grantAccess(folderPath) {
180-
execSync('chown -R `whoami` ' + folderPath);
197+
execCommand('chown -R `whoami` ' + folderPath);
181198
}
182199

183200
function copyRecursiveSync(src, dest) {
184-
var exists = fs.existsSync(src);
185-
var stats = exists && fs.statSync(src);
186-
var isDirectory = exists && stats.isDirectory();
201+
const exists = fs.existsSync(src);
202+
const stats = exists && fs.statSync(src);
203+
const isDirectory = exists && stats.isDirectory();
187204
if (exists && isDirectory) {
188205
fs.mkdirSync(dest);
189206
fs.readdirSync(src).forEach(function (childItemName) {
@@ -195,12 +212,82 @@ function copyRecursiveSync(src, dest) {
195212
}
196213
}
197214

198-
function isReactNativeVesionLowerThan(version) {
215+
function isReactNativeVersionLowerThan(version) {
199216
if (!reactNativeVersion ||
200217
reactNativeVersion == "react-native@latest" ||
201218
reactNativeVersion == "react-native@next")
202219
return false;
203220

204-
let reactNativeVersionNumberString = reactNativeVersion.split("@")[1];
221+
const reactNativeVersionNumberString = reactNativeVersion.split("@")[1];
205222
return reactNativeVersionNumberString.split('.')[1] < version;
206-
}
223+
}
224+
225+
// Configuring android applications for react-native version higher than 0.60
226+
function androidSetup() {
227+
const buildGradlePath = path.join('android', 'app', 'build.gradle');
228+
const mainApplicationPath = path.join('android', 'app', 'src', 'main', 'java', 'com', appName, 'MainApplication.java');
229+
const stringsResourcesPath = path.join('android', 'app', 'src', 'main', 'res', 'values', 'strings.xml');
230+
231+
let stringsResourcesContent = fs.readFileSync(stringsResourcesPath, "utf8");
232+
const insertAfterString = "<resources>";
233+
const deploymentKeyString = `\t<string moduleConfig="true" name="CodePushDeploymentKey">${androidStagingDeploymentKey || "deployment-key-here"}</string>`;
234+
stringsResourcesContent = stringsResourcesContent.replace(insertAfterString, `${insertAfterString}\n${deploymentKeyString}`);
235+
fs.writeFileSync(stringsResourcesPath, stringsResourcesContent);
236+
237+
let buildGradleContents = fs.readFileSync(buildGradlePath, "utf8");
238+
const reactGradleLink = buildGradleContents.match(/\napply from: ["'].*?react\.gradle["']/)[0];
239+
const codePushGradleLink = `\napply from: "../../node_modules/react-native-code-push/android/codepush.gradle"`;
240+
buildGradleContents = buildGradleContents.replace(reactGradleLink,
241+
`${reactGradleLink}${codePushGradleLink}`);
242+
fs.writeFileSync(buildGradlePath, buildGradleContents);
243+
244+
const getJSBundleFileOverride = `
245+
@Override
246+
protected String getJSBundleFile(){
247+
return CodePush.getJSBundleFile();
248+
}
249+
`;
250+
let mainApplicationContents = fs.readFileSync(mainApplicationPath, "utf8");
251+
const reactNativeHostInstantiation = "new ReactNativeHost(this) {";
252+
mainApplicationContents = mainApplicationContents.replace(reactNativeHostInstantiation,
253+
`${reactNativeHostInstantiation}${getJSBundleFileOverride}`);
254+
255+
const importCodePush = `\nimport com.microsoft.codepush.react.CodePush;`;
256+
const reactNativeHostInstantiationImport = "import android.app.Application;";
257+
mainApplicationContents = mainApplicationContents.replace(reactNativeHostInstantiationImport,
258+
`${reactNativeHostInstantiationImport}${importCodePush}`);
259+
fs.writeFileSync(mainApplicationPath, mainApplicationContents);
260+
}
261+
262+
// Configuring ios applications for react-native version higher than 0.60
263+
function iosSetup() {
264+
const plistPath = path.join('ios', appName, 'Info.plist');
265+
const appDelegatePath = path.join('ios', appName, 'AppDelegate.m');
266+
267+
let plistContents = fs.readFileSync(plistPath, "utf8");
268+
const falseInfoPlist = `<false/>`;
269+
const codePushDeploymentKey = iosStagingDeploymentKey || 'deployment-key-here';
270+
plistContents = plistContents.replace(falseInfoPlist,
271+
`${falseInfoPlist}\n\t<key>CodePushDeploymentKey</key>\n\t<string>${codePushDeploymentKey}</string>`);
272+
fs.writeFileSync(plistPath, plistContents);
273+
274+
let appDelegateContents = fs.readFileSync(appDelegatePath, "utf8");
275+
const appDelegateHeaderImportStatement = `#import "AppDelegate.h"`;
276+
const codePushHeaderImportStatementFormatted = `\n#import <CodePush/CodePush.h>`;
277+
appDelegateContents = appDelegateContents.replace(appDelegateHeaderImportStatement,
278+
`${appDelegateHeaderImportStatement}${codePushHeaderImportStatementFormatted}`);
279+
280+
281+
const oldBundleUrl = "[[NSBundle mainBundle] URLForResource:@\"main\" withExtension:@\"jsbundle\"]";
282+
const codePushBundleUrl = "[CodePush bundleURL]";
283+
appDelegateContents = appDelegateContents.replace(oldBundleUrl, codePushBundleUrl);
284+
fs.writeFileSync(appDelegatePath, appDelegateContents);
285+
286+
execCommand(`cd ios && pod install && cd ..`);
287+
}
288+
289+
function execCommand(command) {
290+
console.log(`\n\x1b[2m${command}\x1b[0m\n`);
291+
const result = execSync(command).toString();
292+
return result;
293+
}

0 commit comments

Comments
 (0)