Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix script for creating demo code push apps #2739

Merged
merged 3 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ What actually happens?

### Reproducible Demo

* 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
* 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.71.19 react-native-code-push@8.3.1` command to generate plain CodePushified React Native app. Please see description on top of `create-app.js` file content if needed
* If you can't reproduce the bug on it, provide us as much info as possible about your project

### Environment
Expand Down
93 changes: 60 additions & 33 deletions Examples/create-app.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
/*
The script serves to generate CodePushified React Native app to reproduce issues or for testing purposes.

NOTE: Use CodePushDemoApp and CodePushDemoAppCpp as reference how to implement CodePush in your app. For creating a working demo app
follow steps bellow.

Requirements:
1. npm i -g react-native-cli
2. npm i -g appcenter-cli
Expand Down Expand Up @@ -28,27 +31,19 @@ const execSync = child_process.execSync;

const args = process.argv.slice(2);
const appName = args[0] || 'CodePushDemoAppTest';

if (fs.existsSync(appName)) {
console.error(`Folder with name "${appName}" already exists! Please delete`);
process.exit();
}

// Checking if yarn is installed
try {
execCommand('yarn bin');
} catch (err) {
console.error(`You must install 'yarn' to use this script!`);
process.exit();
}

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

const reactNativeVersionIsLowerThanV073 = isReactNativeVersionLowerThan(73)
if (!isReactNativeVersionLowerThan(60) && process.platform === "darwin") {
try {
console.log("Verify that CocoaPods installed");
Expand Down Expand Up @@ -89,8 +84,8 @@ function createCodePushApp(name, os) {
const app = JSON.parse(appResult);
owner = app.owner.name;
console.log(`App "${name}" has been created \n`);
} catch(e) {
console.error(`Error: Unable to create CodePush app. Please check that you haven't application with "${name}" name on portal.`, );
} catch (e) {
console.error(`Error: Unable to create CodePush app. Please check that you haven't application with "${name}" name on portal.`,);
console.error("Error: ", e.toString());
}
execCommand(`appcenter codepush deployment add -a ${owner}/${name} Staging`);
Expand Down Expand Up @@ -128,7 +123,7 @@ function generatePlainReactNativeApp(appName, reactNativeVersion) {

function installCodePush(reactNativeCodePushVersion) {
console.log(`Installing React Native Module for CodePush...`);
execCommand(`yarn add ${reactNativeCodePushVersion}`);
execCommand(`npm i ${reactNativeCodePushVersion}`);
console.log(`React Native Module for CodePush has been installed \n`);
}

Expand Down Expand Up @@ -213,8 +208,8 @@ function optimizeToTestInDebugMode() {
const rnXcodeShPath = `node_modules/react-native/${rnXcodeShLocationFolder}/react-native-xcode.sh`;
// Replace "if [[ "$PLATFORM_NAME" == *simulator ]]; then" with "if false; then" to force bundling
execCommand(`sed -ie 's/if \\[\\[ "\$PLATFORM_NAME" == \\*simulator \\]\\]; then/if false; then/' ${rnXcodeShPath}`);
execCommand(`perl -i -p0e 's/#ifdef DEBUG.*?#endif/jsCodeLocation = [CodePush bundleURL];/s' ios/${appName}/AppDelegate.m`);
execCommand(`sed -ie 's/targetName.toLowerCase().contains("release")/true/' node_modules/react-native/react.gradle`);
execCommand(`perl -i -p0e 's/#ifdef DEBUG.*?#endif/jsCodeLocation = [CodePush bundleURL];/s' ios/${appName}/${getAppDelegateName()}`);
reactNativeVersionIsLowerThanV073 && execCommand(`sed -ie 's/targetName.toLowerCase().contains("release")/true/' node_modules/react-native/react.gradle`);
}

function grantAccess(folderPath) {
Expand Down Expand Up @@ -250,7 +245,8 @@ function isReactNativeVersionLowerThan(version) {
function androidSetup() {
const buildGradlePath = path.join('android', 'app', 'build.gradle');
const settingsGradlePath = path.join('android', 'settings.gradle');
const mainApplicationPath = path.join('android', 'app', 'src', 'main', 'java', 'com', appName, 'MainApplication.java');
const mainApplicationType = reactNativeVersionIsLowerThanV073 ? 'java' : 'kt';
const mainApplicationPath = path.join('android', 'app', 'src', 'main', 'java', 'com', appName, `MainApplication.${mainApplicationType}`);
const stringsResourcesPath = path.join('android', 'app', 'src', 'main', 'res', 'values', 'strings.xml');

let stringsResourcesContent = fs.readFileSync(stringsResourcesPath, "utf8");
Expand All @@ -260,47 +256,78 @@ function androidSetup() {
fs.writeFileSync(stringsResourcesPath, stringsResourcesContent);

let buildGradleContents = fs.readFileSync(buildGradlePath, "utf8");
const reactGradleLink = buildGradleContents.match(/\napply from: ["'].*?react\.gradle["']/)[0];
const reactGradleLink = buildGradleContents.match(/\napply from: ["'].*?react\.gradle["']/);
const codePushGradleLink = `\napply from: "../../node_modules/react-native-code-push/android/codepush.gradle"`;
buildGradleContents = buildGradleContents.replace(reactGradleLink,
`${reactGradleLink}${codePushGradleLink}`);
fs.writeFileSync(buildGradlePath, buildGradleContents);
if (reactGradleLink != null) {
buildGradleContents = buildGradleContents.replace(reactGradleLink[0],
`${reactGradleLink[0]}${codePushGradleLink}`);
fs.writeFileSync(buildGradlePath, buildGradleContents);
}
// react.gradle script removed from 0.71 thus this workaround
else {
const appPluginLastLine = buildGradleContents.match(/apply plugin: "com.facebook.react"/)[0];
buildGradleContents = buildGradleContents.replace(appPluginLastLine, `${appPluginLastLine}${codePushGradleLink}`)
fs.writeFileSync(buildGradlePath, buildGradleContents);
}

let settingsGradleContents = fs.readFileSync(settingsGradlePath, "utf8");
const settingsGradleInclude = "include \':app\'";
const codePushProjectImport= `':react-native-code-push'\nproject(':react-native-code-push').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-code-push/android/app')`;
const codePushProjectImport = `':react-native-code-push'\nproject(':react-native-code-push').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-code-push/android/app')`;
settingsGradleContents = settingsGradleContents.replace(settingsGradleInclude,
`${settingsGradleInclude}, ${codePushProjectImport}`);
fs.writeFileSync(settingsGradlePath, settingsGradleContents);

const getJSBundleFileOverride = `
@Override
protected String getJSBundleFile(){
return CodePush.getJSBundleFile();
}
`;
let importCodePush = `\nimport com.microsoft.codepush.react.CodePush;`;
let reactNativeHostInstantiationImport = "import android.app.Application;";
let mainApplicationContents = fs.readFileSync(mainApplicationPath, "utf8");
const reactNativeHostInstantiation = "new ReactNativeHost(this) {";
let getJSBundleFileOverride = "";
let reactNativeHostInstantiation = "";

// handle react-native version with java
if (reactNativeVersionIsLowerThanV073) {
reactNativeHostInstantiation = "new ReactNativeHost(this) {";

getJSBundleFileOverride = `
@Override
protected String getJSBundleFile(){
return CodePush.getJSBundleFile();
}
`;
}
// handle react-native version with kotlin
else {
reactNativeHostInstantiation = "object : DefaultReactNativeHost(this) {"
getJSBundleFileOverride = `
override fun getJSBundleFile(): String {
return CodePush.getJSBundleFile()
}
`;
importCodePush = importCodePush.replace(';', '');
reactNativeHostInstantiationImport = reactNativeHostInstantiationImport.replace(';', '');
}
mainApplicationContents = mainApplicationContents.replace(reactNativeHostInstantiation,
`${reactNativeHostInstantiation}${getJSBundleFileOverride}`);

const importCodePush = `\nimport com.microsoft.codepush.react.CodePush;`;
const reactNativeHostInstantiationImport = "import android.app.Application;";
mainApplicationContents = mainApplicationContents.replace(reactNativeHostInstantiationImport,
`${reactNativeHostInstantiationImport}${importCodePush}`);
fs.writeFileSync(mainApplicationPath, mainApplicationContents);
}

function getAppDelegateName() { return fs.readdirSync(path.join('ios', appName)).find(file => file.endsWith('mm') || file.endsWith('m')) };

// Configuring ios applications for react-native version higher than 0.60
function iosSetup() {
const plistPath = path.join('ios', appName, 'Info.plist');
const appDelegatePath = path.join('ios', appName, 'AppDelegate.m');

const appDelegatePath = path.join('ios', appName, getAppDelegateName());

let plistContents = fs.readFileSync(plistPath, "utf8");
const falseInfoPlist = `<false/>`;

const dictPlistTag = `</dict>\n</plist>`;

const codePushDeploymentKey = iosStagingDeploymentKey || 'deployment-key-here';
plistContents = plistContents.replace(falseInfoPlist,
`${falseInfoPlist}\n\t<key>CodePushDeploymentKey</key>\n\t<string>${codePushDeploymentKey}</string>`);
plistContents = plistContents.replace(dictPlistTag,
`\t<key>CodePushDeploymentKey</key>\n\t<string>${codePushDeploymentKey}</string>${dictPlistTag}`);
fs.writeFileSync(plistPath, plistContents);

let appDelegateContents = fs.readFileSync(appDelegatePath, "utf8");
Expand Down