diff --git a/azure/templates/system-tests.yml b/azure/templates/system-tests.yml index edd9aaf89..184868ed9 100644 --- a/azure/templates/system-tests.yml +++ b/azure/templates/system-tests.yml @@ -1,7 +1,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: '18.x' + versionSpec: '20.x' displayName: 'Install Node.js' - script: | git config --global user.email "electrodenative@gmail.com" diff --git a/azure/templates/unit-tests.yml b/azure/templates/unit-tests.yml index 166e886cd..13b347a50 100644 --- a/azure/templates/unit-tests.yml +++ b/azure/templates/unit-tests.yml @@ -1,7 +1,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: '18.x' + versionSpec: '20.x' displayName: 'Install Node.js' - script: | yarn --frozen-lockfile diff --git a/ern-composite-gen/src/addRNDepToPjson.ts b/ern-composite-gen/src/addRNDepToPjson.ts index d3fa544a0..313cc07be 100644 --- a/ern-composite-gen/src/addRNDepToPjson.ts +++ b/ern-composite-gen/src/addRNDepToPjson.ts @@ -7,7 +7,21 @@ export async function addRNDepToPjson(dir: string, version: string) { // For React Native 0.77+, also add required dependencies // This is required by the new Metro config format and CLI - if (semver.gte(version, '0.77.0')) { + if (semver.gte(version, '0.81.0')) { + compositePackageJson.dependencies['@react-native/metro-config'] = version; + compositePackageJson.dependencies['@react-native/babel-preset'] = version; + // RN 0.81+ uses @react-native/community-cli-plugin (internal to RN monorepo) + compositePackageJson.dependencies['@react-native/community-cli-plugin'] = + version; + // Add CLI packages to ensure android and ios platforms are available + compositePackageJson.dependencies['@react-native-community/cli'] = '15.1.3'; + compositePackageJson.dependencies[ + '@react-native-community/cli-platform-android' + ] = '15.1.3'; + compositePackageJson.dependencies[ + '@react-native-community/cli-platform-ios' + ] = '15.1.3'; + } else if (semver.gte(version, '0.77.0')) { compositePackageJson.dependencies['@react-native/metro-config'] = version; compositePackageJson.dependencies['@react-native/babel-preset'] = version; // Add CLI packages to ensure android and ios platforms are available diff --git a/ern-composite-gen/src/createMetroConfig.ts b/ern-composite-gen/src/createMetroConfig.ts index 2bdf5f13b..e2da774e3 100644 --- a/ern-composite-gen/src/createMetroConfig.ts +++ b/ern-composite-gen/src/createMetroConfig.ts @@ -2,6 +2,8 @@ import fs from 'fs-extra'; import path from 'path'; import beautify from 'js-beautify'; import os from 'os'; +import semver from 'semver'; +import { getMetroBlacklistPath } from 'ern-core'; export async function createMetroConfig({ cwd, @@ -9,15 +11,52 @@ export async function createMetroConfig({ blacklistRe, extraNodeModules, watchFolders, + reactNativeVersion, }: { cwd?: string; projectRoot?: string; blacklistRe?: RegExp[]; extraNodeModules?: { [pkg: string]: string }; watchFolders?: string[]; + reactNativeVersion?: string; }) { - // Metro config format for React Native 0.73+ - const metroConfigContent = `const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config'); + const useModernConfig = + reactNativeVersion && semver.gte(reactNativeVersion, '0.73.0'); + + const metroConfigContent = useModernConfig + ? createModernMetroConfig({ + projectRoot, + blacklistRe, + extraNodeModules, + watchFolders, + }) + : createLegacyMetroConfig({ + projectRoot, + blacklistRe, + extraNodeModules, + watchFolders, + reactNativeVersion: reactNativeVersion || '0.60.0', + }); + + return fs.writeFile( + path.join(cwd ?? path.resolve(), 'metro.config.js'), + beautify.js(metroConfigContent), + ); +} + +// Metro config format for React Native 0.73+ +function createModernMetroConfig({ + projectRoot, + blacklistRe, + extraNodeModules, + watchFolders, +}: { + projectRoot?: string; + blacklistRe?: RegExp[]; + extraNodeModules?: { [pkg: string]: string }; + watchFolders?: string[]; +}): string { + return `const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config'); const defaultConfig = getDefaultConfig(__dirname); const config = { @@ -45,7 +84,7 @@ const config = { ], sourceExts: [ ...defaultConfig.resolver.sourceExts, - "svg", + "svg", "mjs" ], blockList: [ @@ -72,9 +111,95 @@ const config = { }; module.exports = mergeConfig(defaultConfig, config);`; +} - return fs.writeFile( - path.join(cwd ?? path.resolve(), 'metro.config.js'), - beautify.js(metroConfigContent), - ); +// Legacy Metro config format for React Native < 0.73 +function createLegacyMetroConfig({ + projectRoot, + blacklistRe, + extraNodeModules, + watchFolders, + reactNativeVersion, +}: { + projectRoot?: string; + blacklistRe?: RegExp[]; + extraNodeModules?: { [pkg: string]: string }; + watchFolders?: string[]; + reactNativeVersion: string; +}): string { + return `const blacklist = require('${getMetroBlacklistPath( + reactNativeVersion, + )}'); +module.exports = { + ${projectRoot ? `projectRoot: "${projectRoot}",` : ''} + ${ + watchFolders + ? `watchFolders: [ + ${watchFolders + .map((x) => `"${x.replace(/\\/g, '\\\\')}"`) + .join(`,${os.EOL}`)} + ],` + : '' + } + resolver: { + blacklistRE: blacklist([ + // Ignore IntelliJ directories + /.*\\.idea\\/.*/, + // ignore git directories + /.*\\.git\\/.*/, + // Ignore android directories + /.*\\/app\\/build\\/.*/, + ${blacklistRe ? blacklistRe.join(`,${os.EOL}`) : ''} + ]), + ${ + extraNodeModules + ? `extraNodeModules: ${JSON.stringify(extraNodeModules, null, 2)},` + : '' + } + assetExts: [ + // Image formats + "bmp", + "gif", + "jpg", + "jpeg", + "png", + "psd", + "webp", + // Video formats + "m4v", + "mov", + "mp4", + "mpeg", + "mpg", + "webm", + // Audio formats + "aac", + "aiff", + "caf", + "m4a", + "mp3", + "wav", + // Document formats + "html", + "pdf", + // Font formats + "otf", + "ttf", + // Archives (virtual files) + "zip" + ], + sourceExts: ["js", "json", "ts", "tsx", "svg", "mjs"], + }, + transformer: { + getTransformOptions: async () => ({ + transform: { + experimentalImportSupport: false, + inlineRequires: false, + }, + }), + assetPlugins: ['ern-bundle-store-metro-asset-plugin'], + babelTransformerPath: require.resolve("react-native-svg-transformer"), + }, +}; +`; } diff --git a/ern-composite-gen/src/generateComposite.ts b/ern-composite-gen/src/generateComposite.ts index 41a9dd7d0..4c5cc84ef 100644 --- a/ern-composite-gen/src/generateComposite.ts +++ b/ern-composite-gen/src/generateComposite.ts @@ -330,6 +330,7 @@ You should resolve the following version mismatches prior to retrying.${os.EOL}` blacklistRe, cwd: outDir, extraNodeModules, + reactNativeVersion: rnVersion, watchFolders: localMiniAppsPaths, }); if (semver.gte(rnVersion, '0.57.0')) { diff --git a/ern-container-gen-android/src/AndroidGenerator.ts b/ern-container-gen-android/src/AndroidGenerator.ts index 0328a6357..2aee67617 100644 --- a/ern-container-gen-android/src/AndroidGenerator.ts +++ b/ern-container-gen-android/src/AndroidGenerator.ts @@ -388,7 +388,12 @@ You should replace "${annotationProcessorPrefix}:${dependency}" with "annotation log.debug('Patching hull'); const files = readDir( config.outDir, - (f) => !f.endsWith('.jar') && !f.endsWith('.aar') && !f.endsWith('.git'), + (f) => + !f.endsWith('.jar') && + !f.endsWith('.aar') && + !f.endsWith('.git') && + f !== '.gradle' && + f !== 'build', ); const pathLibSrcMain = path.normalize('lib/src/main'); const pathLibSrcMainJniLibs = path.normalize('lib/src/main/jniLibs'); diff --git a/ern-container-gen-android/src/hull/build.gradle b/ern-container-gen-android/src/hull/build.gradle index 65f3fbe31..b2aa52a7f 100644 --- a/ern-container-gen-android/src/hull/build.gradle +++ b/ern-container-gen-android/src/hull/build.gradle @@ -5,9 +5,7 @@ buildscript { } dependencies { classpath 'com.android.tools.build:gradle:{{{androidGradlePlugin}}}' -{{#isKotlinEnabled}} classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:{{{kotlinVersion}}}' -{{/isKotlinEnabled}} } } diff --git a/ern-container-gen-android/src/hull/gradle/wrapper/gradle-wrapper.properties b/ern-container-gen-android/src/hull/gradle/wrapper/gradle-wrapper.properties index bc60d1fcf..37a6725dd 100644 --- a/ern-container-gen-android/src/hull/gradle/wrapper/gradle-wrapper.properties +++ b/ern-container-gen-android/src/hull/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-all.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/ern-container-gen-android/src/hull/lib/build.gradle b/ern-container-gen-android/src/hull/lib/build.gradle index 0b3378708..5a42f1612 100644 --- a/ern-container-gen-android/src/hull/lib/build.gradle +++ b/ern-container-gen-android/src/hull/lib/build.gradle @@ -1,7 +1,5 @@ apply plugin: 'com.android.library' -{{#isKotlinEnabled}} apply plugin: 'kotlin-android' -{{/isKotlinEnabled}} android { namespace "com.walmartlabs.ern.container" diff --git a/ern-container-gen/src/reactNativeBundleAndroid.ts b/ern-container-gen/src/reactNativeBundleAndroid.ts index 084dc565d..1b86cfacd 100644 --- a/ern-container-gen/src/reactNativeBundleAndroid.ts +++ b/ern-container-gen/src/reactNativeBundleAndroid.ts @@ -43,6 +43,7 @@ export async function reactNativeBundleAndroid({ platform: 'android', resetCache, sourceMapOutput, + workingDir: cwd, }); return result; } finally { diff --git a/ern-container-gen/src/reactNativeBundleIos.ts b/ern-container-gen/src/reactNativeBundleIos.ts index 65a547108..ebb422544 100644 --- a/ern-container-gen/src/reactNativeBundleIos.ts +++ b/ern-container-gen/src/reactNativeBundleIos.ts @@ -56,6 +56,7 @@ export async function reactNativeBundleIos({ platform: 'ios', resetCache, sourceMapOutput, + workingDir: cwd, }); return result; } finally { diff --git a/ern-core/src/ReactNativeCli.ts b/ern-core/src/ReactNativeCli.ts index 050c8a42b..202a246ff 100644 --- a/ern-core/src/ReactNativeCli.ts +++ b/ern-core/src/ReactNativeCli.ts @@ -9,7 +9,6 @@ import log from './log'; import kax from './kax'; import util from 'util'; import semver from 'semver'; -import os from 'os'; const ex = util.promisify(exec); const sp = util.promisify(spawn); @@ -89,7 +88,9 @@ export default class ReactNativeCli { } const initCmd = `init ${projectName} ${options.join(' ')}`; - if (semver.gte(rnVersion, '0.77.0')) { + if (semver.gte(rnVersion, '0.81.0')) { + return execp(`npx @react-native-community/cli@15.1.3 ${initCmd}`); + } else if (semver.gte(rnVersion, '0.77.0')) { return execp(`npx @react-native-community/cli@15.0.1 ${initCmd}`); } else if (semver.gte(rnVersion, '0.60.0')) { return execp( @@ -123,9 +124,7 @@ export default class ReactNativeCli { const shouldUseCommunityCliForProject = await this.shouldUseCommunityCliForProject(workingDir); - let bundleCommand: string; - if (shouldUseCommunityCliForProject) { - bundleCommand = `npx @react-native-community/cli bundle \ + const bundleArgs = `\ ${entryFile ? `--entry-file=${entryFile}` : ''} \ ${dev ? '--dev=true' : '--dev=false'} \ ${platform ? `--platform=${platform}` : ''} \ @@ -133,18 +132,28 @@ ${bundleOutput ? `--bundle-output=${bundleOutput}` : ''} \ ${assetsDest ? `--assets-dest=${assetsDest}` : ''} \ ${sourceMapOutput ? `--sourcemap-output=${sourceMapOutput}` : ''} \ ${resetCache ? '--reset-cache' : ''}`; + + let bundleCommand: string; + const execOptions: any = { cwd: workingDir }; + if (shouldUseCommunityCliForProject) { + // RN >= 0.77: Use npx @react-native-community/cli (ships metro plugin via RN itself) + bundleCommand = `npx @react-native-community/cli bundle ${bundleArgs}`; } else { - bundleCommand = `${this.binaryPath} bundle \ -${entryFile ? `--entry-file=${entryFile}` : ''} \ -${dev ? '--dev=true' : '--dev=false'} \ -${platform ? `--platform=${platform}` : ''} \ -${bundleOutput ? `--bundle-output=${bundleOutput}` : ''} \ -${assetsDest ? `--assets-dest=${assetsDest}` : ''} \ -${sourceMapOutput ? `--sourcemap-output=${sourceMapOutput}` : ''} \ -${resetCache ? '--reset-cache' : ''}`; + // RN < 0.77: Use the project-local react-native CLI from node_modules + // The composite project's react-native dependency ships its own CLI version + // that includes the bundle command (via cli-plugin-metro) + const localCliBin = workingDir + ? path.join(workingDir, 'node_modules', '.bin', 'react-native') + : 'react-native'; + bundleCommand = `${localCliBin} bundle ${bundleArgs}`; + // Older Metro versions use md4 hash which is unsupported in Node 17+ (OpenSSL 3) + execOptions.env = { + ...process.env, + NODE_OPTIONS: '--openssl-legacy-provider', + }; } - await execp(bundleCommand, { cwd: workingDir }); + await execp(bundleCommand, execOptions); if (!(await fs.pathExists(bundleOutput))) { // Under some circumstances, Metro bundler process might fail // with some logs, but exit the process with a non error status code. @@ -209,17 +218,19 @@ ${resetCache ? '--reset-cache' : ''}`; stdio: 'inherit', }); } else { - spawn( - path.join( - cwd, - `node_modules/.bin/rnc-cli${os.platform() === 'win32' ? '.cmd' : ''}`, - ), - ['start', ...args], - { - cwd, - stdio: 'inherit', - }, + // RN < 0.77: Use the project-local react-native CLI from node_modules + // The project's react-native dependency ships its own CLI version + // that includes the start command (via cli-plugin-metro) + const localCliBin = path.join( + cwd, + 'node_modules', + '.bin', + 'react-native', ); + spawn(localCliBin, ['start', ...args], { + cwd, + stdio: 'inherit', + }); } } @@ -329,22 +340,37 @@ ${resetCache ? '--reset-cache' : ''}`; const tmpDir = createTmpDir(); const tmpScriptPath = path.join(tmpDir, scriptFileName); - // Check if we should use @react-native-community/cli for RN 0.77+ - let command = `${this.binaryPath} start ${args.join(' ')}`; + // Determine which CLI to use based on RN version + let command: string; + let useCommunityCliLatest = false; try { const packageJsonPath = path.join(cwd, 'package.json'); if (await fs.pathExists(packageJsonPath)) { const packageJson = await fs.readJSON(packageJsonPath); const rnVersion = packageJson.dependencies?.['react-native'] || '0.60.0'; - if (semver.gte(rnVersion.replace(/[\^~]/, ''), '0.77.0')) { - command = `npx @react-native-community/cli start ${args.join(' ')}`; - } + useCommunityCliLatest = semver.gte( + rnVersion.replace(/[\^~]/, ''), + '0.77.0', + ); } } catch (e) { // If we can't determine version, use legacy approach } + if (useCommunityCliLatest) { + command = `npx @react-native-community/cli start ${args.join(' ')}`; + } else { + // RN < 0.77: Use the project-local react-native CLI from node_modules + const localCliBin = path.join( + cwd, + 'node_modules', + '.bin', + 'react-native', + ); + command = `${localCliBin} start ${args.join(' ')}`; + } + await fs.writeFile( tmpScriptPath, ` diff --git a/ern-core/src/android.ts b/ern-core/src/android.ts index f531cec3d..ac4f748e9 100644 --- a/ern-core/src/android.ts +++ b/ern-core/src/android.ts @@ -16,16 +16,16 @@ export const DEFAULT_ANDROID_GRADLE_PLUGIN_VERSION = '7.0.4'; export const DEFAULT_RN_GRADLE_PLUGIN_VERSION = '0.0.6'; export const DEFAULT_ANDROIDX_APPCOMPACT_VERSION = '1.1.0'; export const DEFAULT_ANDROIDX_LIFECYCLE_EXTENSIONS_VERSION = '2.1.0'; -export const DEFAULT_BUILD_TOOLS_VERSION = '35.0.0'; -export const DEFAULT_COMPILE_SDK_VERSION = '35'; -export const DEFAULT_GRADLE_DISTRIBUTION_VERSION = '8.11.1'; +export const DEFAULT_BUILD_TOOLS_VERSION = '36.0.0'; +export const DEFAULT_COMPILE_SDK_VERSION = '36'; +export const DEFAULT_GRADLE_DISTRIBUTION_VERSION = '8.14.3'; export const DEFAULT_JSC_VARIANT = 'android-jsc'; -export const DEFAULT_KOTLIN_VERSION = '2.0.21'; +export const DEFAULT_KOTLIN_VERSION = '2.1.20'; export const DEFAULT_MIN_SDK_VERSION_PRE_RN64 = '19'; export const DEFAULT_MIN_SDK_VERSION_POST_RN64 = '21'; export const DEFAULT_MIN_SDK_VERSION_POST_RN77 = '24'; export const DEFAULT_SUPPORT_LIBRARY_VERSION = '28.0.0'; -export const DEFAULT_TARGET_SDK_VERSION = '35'; +export const DEFAULT_TARGET_SDK_VERSION = '36'; export const DEFAULT_SOURCE_COMPATIBILITY = 'VERSION_17'; export const DEFAULT_TARGET_COMPATIBILITY = 'VERSION_17'; const ANDROID_DEVICE_INFO = ` @@ -54,16 +54,16 @@ export function resolveAndroidVersions({ androidGradlePlugin, androidxAppcompactVersion = DEFAULT_ANDROIDX_APPCOMPACT_VERSION, androidxLifecycleExtrnsionsVersion = DEFAULT_ANDROIDX_LIFECYCLE_EXTENSIONS_VERSION, - buildToolsVersion = DEFAULT_BUILD_TOOLS_VERSION, - compileSdkVersion = DEFAULT_COMPILE_SDK_VERSION, - gradleDistributionVersion = DEFAULT_GRADLE_DISTRIBUTION_VERSION, - kotlinVersion = DEFAULT_KOTLIN_VERSION, + buildToolsVersion, + compileSdkVersion, + gradleDistributionVersion, + kotlinVersion, minSdkVersion, reactNativeAarVersion, sourceCompatibility = DEFAULT_SOURCE_COMPATIBILITY, supportLibraryVersion = DEFAULT_SUPPORT_LIBRARY_VERSION, targetCompatibility = DEFAULT_TARGET_COMPATIBILITY, - targetSdkVersion = DEFAULT_TARGET_SDK_VERSION, + targetSdkVersion, reactNativeVersion, }: { rnGradlePlugin?: string; @@ -95,22 +95,33 @@ export function resolveAndroidVersions({ rnGradlePlugin ?? getReactNativeGradlePluginVersion(reactNativeVersion!); const resolvedAndroidGradlePlugin = androidGradlePlugin ?? getGradlePluginVersion(reactNativeVersion!); + const resolvedBuildToolsVersion = + buildToolsVersion ?? getDefaultBuildToolsVersion(reactNativeVersion!); + const resolvedCompileSdkVersion = + compileSdkVersion ?? getDefaultCompileSdkVersion(reactNativeVersion!); + const resolvedGradleDistributionVersion = + gradleDistributionVersion ?? + getDefaultGradleDistributionVersion(reactNativeVersion!); + const resolvedKotlinVersion = + kotlinVersion ?? getDefaultKotlinVersion(reactNativeVersion!); + const resolvedTargetSdkVersion = + targetSdkVersion ?? getDefaultTargetSdkVersion(reactNativeVersion!); return { rnGradlePlugin: resolvedRNGradlePlugin, androidGradlePlugin: resolvedAndroidGradlePlugin, androidxAppcompactVersion, androidxLifecycleExtrnsionsVersion, - buildToolsVersion, - compileSdkVersion, - gradleDistributionVersion, - kotlinVersion, + buildToolsVersion: resolvedBuildToolsVersion, + compileSdkVersion: resolvedCompileSdkVersion, + gradleDistributionVersion: resolvedGradleDistributionVersion, + kotlinVersion: resolvedKotlinVersion, minSdkVersion: resolvedMinSdkVersion, reactNativeAarVersion, sourceCompatibility, supportLibraryVersion, targetCompatibility, - targetSdkVersion, + targetSdkVersion: resolvedTargetSdkVersion, }; } @@ -470,9 +481,48 @@ export function androidEmulatorPath(): string { return 'emulator'; } +function getDefaultBuildToolsVersion(reactNativeVersion: string): string { + if (semver.gte(reactNativeVersion, '0.81.0')) { + return '36.0.0'; + } + return '35.0.0'; +} + +function getDefaultCompileSdkVersion(reactNativeVersion: string): string { + if (semver.gte(reactNativeVersion, '0.81.0')) { + return '36'; + } + return '35'; +} + +function getDefaultGradleDistributionVersion( + reactNativeVersion: string, +): string { + if (semver.gte(reactNativeVersion, '0.81.0')) { + return '8.14.3'; + } + return '8.11.1'; +} + +function getDefaultKotlinVersion(reactNativeVersion: string): string { + if (semver.gte(reactNativeVersion, '0.81.0')) { + return '2.1.20'; + } + return '2.0.21'; +} + +function getDefaultTargetSdkVersion(reactNativeVersion: string): string { + if (semver.gte(reactNativeVersion, '0.81.0')) { + return '36'; + } + return '35'; +} + // ERN Android plugins supports backward compatibility until react native version 68. function getGradlePluginVersion(reactNativeVersion: string): string | never { - if (semver.gte(reactNativeVersion, '0.77.0')) { + if (semver.gte(reactNativeVersion, '0.81.0')) { + return '8.11.0'; + } else if (semver.gte(reactNativeVersion, '0.77.0')) { return '8.7.2'; } else if (semver.gte(reactNativeVersion, '0.72.0')) { return '7.4.2'; @@ -490,7 +540,9 @@ function getGradlePluginVersion(reactNativeVersion: string): string | never { function getReactNativeGradlePluginVersion( reactNativeVersion: string, ): string | never { - if (semver.gte(reactNativeVersion, '0.77.0')) { + if (semver.gte(reactNativeVersion, '0.81.0')) { + return '0.81.5'; + } else if (semver.gte(reactNativeVersion, '0.77.0')) { return '0.77.2'; } else if (semver.gte(reactNativeVersion, '0.72.0')) { return '0.72.11'; diff --git a/ern-core/src/injectReactNativeVersionKeysInObject.ts b/ern-core/src/injectReactNativeVersionKeysInObject.ts index 09017c023..068a72a30 100644 --- a/ern-core/src/injectReactNativeVersionKeysInObject.ts +++ b/ern-core/src/injectReactNativeVersionKeysInObject.ts @@ -11,6 +11,7 @@ export function injectReactNativeVersionKeysInObject( RN_VERSION_GTE_60_1: semver.gte(reactNativeVersion, '0.60.1'), RN_VERSION_GTE_61: semver.gte(reactNativeVersion, '0.61.0'), RN_VERSION_GTE_77: semver.gte(reactNativeVersion, '0.77.0'), + RN_VERSION_GTE_81: semver.gte(reactNativeVersion, '0.81.0'), RN_VERSION_LT_54: semver.lt(reactNativeVersion, '0.54.0'), RN_VERSION_LT_58: semver.lt(reactNativeVersion, '0.58.0-rc.2'), RN_VERSION_LT_59: semver.lt(reactNativeVersion, '0.59.0'), diff --git a/ern-core/src/iosUtil.ts b/ern-core/src/iosUtil.ts index 129adea7c..720313b5a 100644 --- a/ern-core/src/iosUtil.ts +++ b/ern-core/src/iosUtil.ts @@ -582,7 +582,9 @@ export const getDefaultIosDeploymentTarget = (rnVersion: string): string => { export const getReactNativeCodegenVersion = ( rnVersion: string, ): string | null => { - if (semver.gte(rnVersion, '0.77.0')) { + if (semver.gte(rnVersion, '0.81.0')) { + return '0.81.5'; + } else if (semver.gte(rnVersion, '0.77.0')) { return '0.77.2'; } else if (semver.gte(rnVersion, '0.72.0')) { return '0.72.8'; diff --git a/ern-core/test/android-test.ts b/ern-core/test/android-test.ts index 314ddd18a..d2bdc319d 100644 --- a/ern-core/test/android-test.ts +++ b/ern-core/test/android-test.ts @@ -209,6 +209,28 @@ describe('android.js', () => { }); describe('resolveAndroidVersions', () => { + it('should return all default versions if no versions are provided [>= RN 0.81.0]', () => { + const versions = android.resolveAndroidVersions({ + reactNativeVersion: '0.81.0', + }); + expect(versions).deep.equal({ + androidGradlePlugin: '8.11.0', + rnGradlePlugin: '0.81.5', + androidxAppcompactVersion: '1.1.0', + androidxLifecycleExtrnsionsVersion: '2.1.0', + buildToolsVersion: '36.0.0', + compileSdkVersion: '36', + gradleDistributionVersion: '8.14.3', + kotlinVersion: '2.1.20', + minSdkVersion: '24', + reactNativeAarVersion: '0.81.0', + sourceCompatibility: 'VERSION_17', + supportLibraryVersion: '28.0.0', + targetCompatibility: 'VERSION_17', + targetSdkVersion: '36', + }); + }); + it('should return all default versions if no versions are provided [>= RN 0.77.0]', () => { const versions = android.resolveAndroidVersions({ reactNativeVersion: '0.77.0', @@ -216,19 +238,18 @@ describe('android.js', () => { expect(versions).deep.equal({ androidGradlePlugin: '8.7.2', rnGradlePlugin: '0.77.2', - androidxAppcompactVersion: android.DEFAULT_ANDROIDX_APPCOMPACT_VERSION, - androidxLifecycleExtrnsionsVersion: - android.DEFAULT_ANDROIDX_LIFECYCLE_EXTENSIONS_VERSION, - buildToolsVersion: android.DEFAULT_BUILD_TOOLS_VERSION, - compileSdkVersion: android.DEFAULT_COMPILE_SDK_VERSION, - gradleDistributionVersion: android.DEFAULT_GRADLE_DISTRIBUTION_VERSION, - kotlinVersion: android.DEFAULT_KOTLIN_VERSION, - minSdkVersion: android.DEFAULT_MIN_SDK_VERSION_POST_RN77, + androidxAppcompactVersion: '1.1.0', + androidxLifecycleExtrnsionsVersion: '2.1.0', + buildToolsVersion: '35.0.0', + compileSdkVersion: '35', + gradleDistributionVersion: '8.11.1', + kotlinVersion: '2.0.21', + minSdkVersion: '24', reactNativeAarVersion: '0.77.0', - sourceCompatibility: android.DEFAULT_SOURCE_COMPATIBILITY, - supportLibraryVersion: android.DEFAULT_SUPPORT_LIBRARY_VERSION, - targetCompatibility: android.DEFAULT_TARGET_COMPATIBILITY, - targetSdkVersion: android.DEFAULT_TARGET_SDK_VERSION, + sourceCompatibility: 'VERSION_17', + supportLibraryVersion: '28.0.0', + targetCompatibility: 'VERSION_17', + targetSdkVersion: '35', }); }); @@ -239,19 +260,18 @@ describe('android.js', () => { expect(versions).deep.equal({ androidGradlePlugin: '7.4.2', rnGradlePlugin: '0.72.11', - androidxAppcompactVersion: android.DEFAULT_ANDROIDX_APPCOMPACT_VERSION, - androidxLifecycleExtrnsionsVersion: - android.DEFAULT_ANDROIDX_LIFECYCLE_EXTENSIONS_VERSION, - buildToolsVersion: android.DEFAULT_BUILD_TOOLS_VERSION, - compileSdkVersion: android.DEFAULT_COMPILE_SDK_VERSION, - gradleDistributionVersion: android.DEFAULT_GRADLE_DISTRIBUTION_VERSION, - kotlinVersion: android.DEFAULT_KOTLIN_VERSION, - minSdkVersion: android.DEFAULT_MIN_SDK_VERSION_POST_RN64, + androidxAppcompactVersion: '1.1.0', + androidxLifecycleExtrnsionsVersion: '2.1.0', + buildToolsVersion: '35.0.0', + compileSdkVersion: '35', + gradleDistributionVersion: '8.11.1', + kotlinVersion: '2.0.21', + minSdkVersion: '21', reactNativeAarVersion: '0.72.0', - sourceCompatibility: android.DEFAULT_SOURCE_COMPATIBILITY, - supportLibraryVersion: android.DEFAULT_SUPPORT_LIBRARY_VERSION, - targetCompatibility: android.DEFAULT_TARGET_COMPATIBILITY, - targetSdkVersion: android.DEFAULT_TARGET_SDK_VERSION, + sourceCompatibility: 'VERSION_17', + supportLibraryVersion: '28.0.0', + targetCompatibility: 'VERSION_17', + targetSdkVersion: '35', }); }); @@ -260,21 +280,20 @@ describe('android.js', () => { reactNativeVersion: '0.64.0', }); expect(versions).deep.equal({ - androidGradlePlugin: android.DEFAULT_ANDROID_GRADLE_PLUGIN_VERSION, - rnGradlePlugin: android.DEFAULT_RN_GRADLE_PLUGIN_VERSION, - androidxAppcompactVersion: android.DEFAULT_ANDROIDX_APPCOMPACT_VERSION, - androidxLifecycleExtrnsionsVersion: - android.DEFAULT_ANDROIDX_LIFECYCLE_EXTENSIONS_VERSION, - buildToolsVersion: android.DEFAULT_BUILD_TOOLS_VERSION, - compileSdkVersion: android.DEFAULT_COMPILE_SDK_VERSION, - gradleDistributionVersion: android.DEFAULT_GRADLE_DISTRIBUTION_VERSION, - kotlinVersion: android.DEFAULT_KOTLIN_VERSION, - minSdkVersion: android.DEFAULT_MIN_SDK_VERSION_POST_RN64, + androidGradlePlugin: '7.0.4', + rnGradlePlugin: '0.0.6', + androidxAppcompactVersion: '1.1.0', + androidxLifecycleExtrnsionsVersion: '2.1.0', + buildToolsVersion: '35.0.0', + compileSdkVersion: '35', + gradleDistributionVersion: '8.11.1', + kotlinVersion: '2.0.21', + minSdkVersion: '21', reactNativeAarVersion: '0.64.0', - sourceCompatibility: android.DEFAULT_SOURCE_COMPATIBILITY, - supportLibraryVersion: android.DEFAULT_SUPPORT_LIBRARY_VERSION, - targetCompatibility: android.DEFAULT_TARGET_COMPATIBILITY, - targetSdkVersion: android.DEFAULT_TARGET_SDK_VERSION, + sourceCompatibility: 'VERSION_17', + supportLibraryVersion: '28.0.0', + targetCompatibility: 'VERSION_17', + targetSdkVersion: '35', }); }); @@ -283,21 +302,20 @@ describe('android.js', () => { reactNativeVersion: '0.63.0', }); expect(versions).deep.equal({ - androidGradlePlugin: android.DEFAULT_ANDROID_GRADLE_PLUGIN_VERSION, - rnGradlePlugin: android.DEFAULT_RN_GRADLE_PLUGIN_VERSION, - androidxAppcompactVersion: android.DEFAULT_ANDROIDX_APPCOMPACT_VERSION, - androidxLifecycleExtrnsionsVersion: - android.DEFAULT_ANDROIDX_LIFECYCLE_EXTENSIONS_VERSION, - buildToolsVersion: android.DEFAULT_BUILD_TOOLS_VERSION, - compileSdkVersion: android.DEFAULT_COMPILE_SDK_VERSION, - gradleDistributionVersion: android.DEFAULT_GRADLE_DISTRIBUTION_VERSION, - kotlinVersion: android.DEFAULT_KOTLIN_VERSION, - minSdkVersion: android.DEFAULT_MIN_SDK_VERSION_PRE_RN64, + androidGradlePlugin: '7.0.4', + rnGradlePlugin: '0.0.6', + androidxAppcompactVersion: '1.1.0', + androidxLifecycleExtrnsionsVersion: '2.1.0', + buildToolsVersion: '35.0.0', + compileSdkVersion: '35', + gradleDistributionVersion: '8.11.1', + kotlinVersion: '2.0.21', + minSdkVersion: '19', reactNativeAarVersion: '0.63.0', - sourceCompatibility: android.DEFAULT_SOURCE_COMPATIBILITY, - supportLibraryVersion: android.DEFAULT_SUPPORT_LIBRARY_VERSION, - targetCompatibility: android.DEFAULT_TARGET_COMPATIBILITY, - targetSdkVersion: android.DEFAULT_TARGET_SDK_VERSION, + sourceCompatibility: 'VERSION_17', + supportLibraryVersion: '28.0.0', + targetCompatibility: 'VERSION_17', + targetSdkVersion: '35', }); }); @@ -314,19 +332,18 @@ describe('android.js', () => { expect(versions).deep.equal({ androidGradlePlugin: '7.4.2', rnGradlePlugin: '0.72.11', - androidxAppcompactVersion: android.DEFAULT_ANDROIDX_APPCOMPACT_VERSION, - androidxLifecycleExtrnsionsVersion: - android.DEFAULT_ANDROIDX_LIFECYCLE_EXTENSIONS_VERSION, - buildToolsVersion: android.DEFAULT_BUILD_TOOLS_VERSION, - compileSdkVersion: android.DEFAULT_COMPILE_SDK_VERSION, - gradleDistributionVersion: android.DEFAULT_GRADLE_DISTRIBUTION_VERSION, + androidxAppcompactVersion: '1.1.0', + androidxLifecycleExtrnsionsVersion: '2.1.0', + buildToolsVersion: '35.0.0', + compileSdkVersion: '35', + gradleDistributionVersion: '8.11.1', kotlinVersion: '1.4.0', minSdkVersion: '15', reactNativeAarVersion: '0.72.0', sourceCompatibility: 'VERSION_1_9', - supportLibraryVersion: android.DEFAULT_SUPPORT_LIBRARY_VERSION, + supportLibraryVersion: '28.0.0', targetCompatibility: 'VERSION_1_9', - targetSdkVersion: android.DEFAULT_TARGET_SDK_VERSION, + targetSdkVersion: '35', }); }); diff --git a/ern-runner-gen-android/src/AndroidRunnerGenerator.ts b/ern-runner-gen-android/src/AndroidRunnerGenerator.ts index e9905605a..b5db0fcdd 100644 --- a/ern-runner-gen-android/src/AndroidRunnerGenerator.ts +++ b/ern-runner-gen-android/src/AndroidRunnerGenerator.ts @@ -59,6 +59,7 @@ export default class AndroidRunnerGenerator implements RunnerGenerator { getPackageFilePath(config), 'RunnerConfig.java', ); + shell.mkdir('-p', path.dirname(pathToRunnerConfig)); shell.cp(pathToRunnerConfigHull, pathToRunnerConfig); await mustacheUtils.mustacheRenderToOutputFileUsingTemplateFile( pathToRunnerConfig, diff --git a/ern-runner-gen-android/src/hull/app/build.gradle b/ern-runner-gen-android/src/hull/app/build.gradle index f29216550..941288be2 100644 --- a/ern-runner-gen-android/src/hull/app/build.gradle +++ b/ern-runner-gen-android/src/hull/app/build.gradle @@ -92,6 +92,15 @@ android { configurations.all { resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.0' } +{{#RN_VERSION_GTE_77}} + // For RN >= 0.77, the React Native Gradle Plugin automatically adds + // com.facebook.react:react-android. The electrode container already provides + // it via com.walmartlabs.ern:react-android, so exclude the com.facebook.react + // version to avoid duplicate classes. + configurations.all { + exclude group: 'com.facebook.react', module: 'react-android' + } +{{/RN_VERSION_GTE_77}} // Needs this for okio issue (should be more restrictive to only okio) lintOptions { disable 'InvalidPackage' @@ -102,6 +111,18 @@ dependencies { // Recompile this dependency on every build as it can be updated at any time (snapshot) implementation('{{{groupId}}}:{{{artifactId}}}:1.0.0') { changing = true } implementation "androidx.appcompat:appcompat:{{{androidxAppcompactVersion}}}" +{{#RN_VERSION_GTE_77}} + // For RN >= 0.77, hermes-android is still needed for the native libhermes.so, + // but we exclude react-android from it since the container already provides it. + if (hermesEnabled.toBoolean()) { + implementation("com.facebook.react:hermes-android") { + exclude group: 'com.facebook.react', module: 'react-android' + } + } else { + implementation jscFlavor + } +{{/RN_VERSION_GTE_77}} +{{^RN_VERSION_GTE_77}} // The version of react-native is set by the React Native Gradle Plugin implementation "com.facebook.react:react-android:{{{reactNativeVersion}}}" if (hermesEnabled.toBoolean()) { @@ -109,4 +130,5 @@ dependencies { } else { implementation jscFlavor } +{{/RN_VERSION_GTE_77}} } diff --git a/ern-runner-gen-android/test/AndroidRunnerGenerator-test.ts b/ern-runner-gen-android/test/AndroidRunnerGenerator-test.ts index be5cedebc..653224045 100644 --- a/ern-runner-gen-android/test/AndroidRunnerGenerator-test.ts +++ b/ern-runner-gen-android/test/AndroidRunnerGenerator-test.ts @@ -127,3 +127,44 @@ describe('Test AndroidRunnerGenerator for RN version 0.77.x', () => { ); }); }); + +describe('Test AndroidRunnerGenerator for RN version 0.81.x', () => { + const fixtureRunnerPath = path.join( + __dirname, + 'fixtures', + 'simple-android-runner-rn-81', + ); + const generatedRunnerPath = tmp.dirSync({ unsafeCleanup: true }).name; + process.chdir(generatedRunnerPath); + + const generatorConfig: RunnerGeneratorConfig = { + extra: { + androidConfig: { + artifactId: 'runner-ern-container-dummy', + groupId: 'com.walmartlabs.ern', + packageFilePath: 'com/walmartlabs/ern/dummy', + packageName: 'com.walmartlabs.ern.dummy', + }, + }, + mainMiniAppName: 'dummy', + outDir: generatedRunnerPath, + reactNativeVersion: '0.81.0', + targetPlatform: 'android', + }; + + it('should generate simple-android-runner fixture given same configuration', async () => { + await new AndroidRunnerGenerator().generate(generatorConfig); + assert( + sameDirContent(fixtureRunnerPath, generatedRunnerPath), + 'Generated Android Runner project differs from simple-android-runner fixture', + ); + }); + + it('should re-generate configuration of simple-android-runner fixture given same configuration', async () => { + await new AndroidRunnerGenerator().regenerateRunnerConfig(generatorConfig); + assert( + sameDirContent(fixtureRunnerPath, generatedRunnerPath), + 'Generated Android Runner project differs from simple-android-runner fixture', + ); + }); +}); diff --git a/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-77/app/build.gradle b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-77/app/build.gradle index e35d1bee3..b3d236cd8 100644 --- a/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-77/app/build.gradle +++ b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-77/app/build.gradle @@ -92,6 +92,13 @@ android { configurations.all { resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.0' } + // For RN >= 0.77, the React Native Gradle Plugin automatically adds + // com.facebook.react:react-android. The electrode container already provides + // it via com.walmartlabs.ern:react-android, so exclude the com.facebook.react + // version to avoid duplicate classes. + configurations.all { + exclude group: 'com.facebook.react', module: 'react-android' + } // Needs this for okio issue (should be more restrictive to only okio) lintOptions { disable 'InvalidPackage' @@ -102,10 +109,12 @@ dependencies { // Recompile this dependency on every build as it can be updated at any time (snapshot) implementation('com.walmartlabs.ern:runner-ern-container-dummy:1.0.0') { changing = true } implementation "androidx.appcompat:appcompat:1.1.0" - // The version of react-native is set by the React Native Gradle Plugin - implementation "com.facebook.react:react-android:0.77.0" + // For RN >= 0.77, hermes-android is still needed for the native libhermes.so, + // but we exclude react-android from it since the container already provides it. if (hermesEnabled.toBoolean()) { - implementation("com.facebook.react:hermes-android") + implementation("com.facebook.react:hermes-android") { + exclude group: 'com.facebook.react', module: 'react-android' + } } else { implementation jscFlavor } diff --git a/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/build.gradle b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/build.gradle new file mode 100644 index 000000000..1c8d4fdaa --- /dev/null +++ b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/build.gradle @@ -0,0 +1,121 @@ +apply plugin: 'com.android.application' +apply plugin: "org.jetbrains.kotlin.android" +apply plugin: "com.facebook.react" + +/** + * This is the configuration block to customize your React Native Android app. + * By default you don't need to apply any configuration, just uncomment the lines you need. + */ +react { + /* Folders */ + // The root of your project, i.e. where "package.json" lives. Default is '../..' + // root = file("../../") + // The folder where the react-native NPM package is. Default is ../../node_modules/react-native + // reactNativeDir = file("../../node_modules/react-native") + // The folder where the react-native Codegen package is. Default is ../../node_modules/@react-native/codegen + // codegenDir = file("../../node_modules/@react-native/codegen") + // The cli.js file which is the React Native CLI entrypoint. Default is ../../node_modules/react-native/cli.js + // cliFile = file("../../node_modules/react-native/cli.js") + + /* Variants */ + // The list of variants to that are debuggable. For those we're going to + // skip the bundling of the JS bundle and the assets. By default is just 'debug'. + // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants. + // debuggableVariants = ["liteDebug", "prodDebug"] + + /* Bundling */ + // A list containing the node command and its flags. Default is just 'node'. + // nodeExecutableAndArgs = ["node"] + // + // The command to run when bundling. By default is 'bundle' + // bundleCommand = "ram-bundle" + // + // The path to the CLI configuration file. Default is empty. + // bundleConfig = file(../rn-cli.config.js) + // + // The name of the generated asset file containing your JS bundle + // bundleAssetName = "MyApplication.android.bundle" + // + // The entry file for bundle generation. Default is 'index.android.js' or 'index.js' + // entryFile = file("../js/MyApplication.android.js") + // + // A list of extra flags to pass to the 'bundle' commands. + // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle + // extraPackagerArgs = [] + + /* Hermes Commands */ + // The hermes compiler command to run. By default it is 'hermesc' + // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc" + // + // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map" + // hermesFlags = ["-O", "-output-source-map"] + + /* Autolinking */ + autolinkLibrariesWithApp() +} + +/** + * The preferred build flavor of JavaScriptCore (JSC) + * + * For example, to use the international variant, you can use: + * `def jscFlavor = 'io.github.react-native-community:jsc-android-intl:2026004.+'` + * + * The international variant includes ICU i18n library and necessary data + * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that + * give correct results when using with locales other than en-US. Note that + * this variant is about 6MiB larger per architecture than default. + */ +def jscFlavor = "io.github.react-native-community:jsc-android:2026004.+" + +android { + compileSdkVersion 36 + buildToolsVersion "36.0.0" + namespace "com.walmartlabs.ern.dummy" + defaultConfig { + applicationId "com.walmartlabs.ern.dummy" + minSdkVersion 24 + targetSdkVersion 36 + versionCode 1 + versionName "1.0" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + // Need this to avoid build conflict with jsr version which comes with react-native + configurations.all { + resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.0' + } + // For RN >= 0.77, the React Native Gradle Plugin automatically adds + // com.facebook.react:react-android. The electrode container already provides + // it via com.walmartlabs.ern:react-android, so exclude the com.facebook.react + // version to avoid duplicate classes. + configurations.all { + exclude group: 'com.facebook.react', module: 'react-android' + } + // Needs this for okio issue (should be more restrictive to only okio) + lintOptions { + disable 'InvalidPackage' + } +} + +dependencies { + // Recompile this dependency on every build as it can be updated at any time (snapshot) + implementation('com.walmartlabs.ern:runner-ern-container-dummy:1.0.0') { changing = true } + implementation "androidx.appcompat:appcompat:1.1.0" + // For RN >= 0.77, hermes-android is still needed for the native libhermes.so, + // but we exclude react-android from it since the container already provides it. + if (hermesEnabled.toBoolean()) { + implementation("com.facebook.react:hermes-android") { + exclude group: 'com.facebook.react', module: 'react-android' + } + } else { + implementation jscFlavor + } +} diff --git a/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/proguard-rules.pro b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/proguard-rules.pro new file mode 100644 index 000000000..f1b424510 --- /dev/null +++ b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/debug/AndroidManifest.xml b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/debug/AndroidManifest.xml new file mode 100644 index 000000000..e8f828b56 --- /dev/null +++ b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/debug/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/AndroidManifest.xml b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000..ce9ca54a5 --- /dev/null +++ b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/AndroidManifest.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + diff --git a/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/java/com/walmartlabs/ern/dummy/MainActivity.java b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/java/com/walmartlabs/ern/dummy/MainActivity.java new file mode 100644 index 000000000..2b58c7725 --- /dev/null +++ b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/java/com/walmartlabs/ern/dummy/MainActivity.java @@ -0,0 +1,27 @@ +package com.walmartlabs.ern.dummy; + +import androidx.annotation.NonNull; + +import com.ern.api.impl.navigation.ElectrodeBaseActivity; + +// This is the main activity that gets launched upon app start +// It just launches the activity containing the miniapp +// Feel free to modify it at your convenience. + +public class MainActivity extends ElectrodeBaseActivity { + @NonNull + @Override + public String getRootComponentName() { + return "dummy"; + } + + @Override + protected int mainLayout() { + return R.layout.activity_main; + } + + @Override + public int getFragmentContainerId() { + return R.id.fragment_container; + } +} diff --git a/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/java/com/walmartlabs/ern/dummy/MainApplication.java b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/java/com/walmartlabs/ern/dummy/MainApplication.java new file mode 100644 index 000000000..035c70206 --- /dev/null +++ b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/java/com/walmartlabs/ern/dummy/MainApplication.java @@ -0,0 +1,19 @@ +package com.walmartlabs.ern.dummy; + +import android.app.Application; + +import com.walmartlabs.ern.container.ElectrodeReactContainer; + +public class MainApplication extends Application { + @Override + public void onCreate() { + super.onCreate(); + + // Add additional plugin configuration below + ElectrodeReactContainer.initialize( + this, + new ElectrodeReactContainer.Config() + .isReactNativeDeveloperSupport(RunnerConfig.RN_DEV_SUPPORT_ENABLED) + ); + } +} diff --git a/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/java/com/walmartlabs/ern/dummy/RunnerConfig.java b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/java/com/walmartlabs/ern/dummy/RunnerConfig.java new file mode 100644 index 000000000..b20c045b6 --- /dev/null +++ b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/java/com/walmartlabs/ern/dummy/RunnerConfig.java @@ -0,0 +1,17 @@ +package com.walmartlabs.ern.dummy; + +import com.walmartlabs.ern.container.miniapps.DummyActivity; + +// +// GENERATED CODE: DO NOT MODIFY +// +// Do not modify the content of this file as it will be regenerated +// every time a run-android command is executed. +// See https://native.electrode.io/cli-commands/run-android + +final class RunnerConfig { + static final Class MAIN_MINIAPP_ACTIVITY_CLASS = DummyActivity.class; + static final boolean RN_DEV_SUPPORT_ENABLED = false; + static final String PACKAGER_HOST = "localhost"; + static final String PACKAGER_PORT = "8081"; +} diff --git a/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/layout/activity_main.xml b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/layout/activity_main.xml new file mode 100644 index 000000000..a098c03ae --- /dev/null +++ b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/mipmap-hdpi/ic_launcher.png b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..b8bf1a983 Binary files /dev/null and b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 000000000..0abb1a387 Binary files /dev/null and b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/mipmap-mdpi/ic_launcher.png b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..2f04b41cf Binary files /dev/null and b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 000000000..b0581ce91 Binary files /dev/null and b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..a163bc36d Binary files /dev/null and b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 000000000..69cd70eed Binary files /dev/null and b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..96b1207b2 Binary files /dev/null and b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 000000000..72d49dde5 Binary files /dev/null and b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..d41d94d09 Binary files /dev/null and b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 000000000..1e5ac49dc Binary files /dev/null and b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/values/colors.xml b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/values/colors.xml new file mode 100644 index 000000000..3ab3e9cbc --- /dev/null +++ b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/values/colors.xml @@ -0,0 +1,6 @@ + + + #3F51B5 + #303F9F + #FF4081 + diff --git a/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/values/strings.xml b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/values/strings.xml new file mode 100644 index 000000000..8e15e878d --- /dev/null +++ b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/values/strings.xml @@ -0,0 +1,5 @@ + + dummy + Welcome to dummy Runner App + Force close to reload ern mini-app bundle + diff --git a/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/values/styles.xml b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/values/styles.xml new file mode 100644 index 000000000..5885930df --- /dev/null +++ b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/app/src/main/res/values/styles.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/build.gradle b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/build.gradle new file mode 100644 index 000000000..377d5cae2 --- /dev/null +++ b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/build.gradle @@ -0,0 +1,26 @@ +buildscript { + repositories { + google() + mavenCentral() + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:8.11.0' + classpath 'com.facebook.react:react-native-gradle-plugin:0.81.5' + classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:2.1.20' + } +} + +allprojects { + repositories { + mavenLocal() + google() + mavenCentral() + jcenter() + maven { url 'https://jitpack.io' } + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/gradle.properties b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/gradle.properties new file mode 100644 index 000000000..a46a5b90f --- /dev/null +++ b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/gradle.properties @@ -0,0 +1,41 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +# Default value: -Xmx512m -XX:MaxMetaspaceSize=256m +org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true + +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Automatically convert third-party libraries to use AndroidX +android.enableJetifier=true + +# Use this property to specify which architecture you want to build. +# You can also override it from the CLI using +# ./gradlew -PreactNativeArchitectures=x86_64 +reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 + +# Use this property to enable support to the new architecture. +# This will allow you to use TurboModules and the Fabric render in +# your application. You should enable this flag either if you want +# to write custom TurboModules/Fabric components OR use libraries that +# are providing them. +newArchEnabled=false + +# Use this property to enable or disable the Hermes JS engine. +# If set to false, you will be using JSC instead. +hermesEnabled=true diff --git a/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/gradle/wrapper/gradle-wrapper.jar b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 000000000..943f0cbfa Binary files /dev/null and b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/gradle/wrapper/gradle-wrapper.jar differ diff --git a/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/gradle/wrapper/gradle-wrapper.properties b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..e69d0402a --- /dev/null +++ b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-all.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/gradlew b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/gradlew new file mode 100755 index 000000000..f5feea6d6 --- /dev/null +++ b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/gradlew @@ -0,0 +1,252 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/gradlew.bat b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/gradlew.bat new file mode 100644 index 000000000..9b42019c7 --- /dev/null +++ b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/settings.gradle b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/settings.gradle new file mode 100644 index 000000000..317cb7d21 --- /dev/null +++ b/ern-runner-gen-android/test/fixtures/simple-android-runner-rn-81/settings.gradle @@ -0,0 +1,5 @@ +pluginManagement { includeBuild("../node_modules/@react-native/gradle-plugin") } +plugins { id("com.facebook.react.settings") } +extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() } +include ':app' +includeBuild('../node_modules/@react-native/gradle-plugin') diff --git a/system-tests/fixtures/android-container/build.gradle b/system-tests/fixtures/android-container/build.gradle index e203a313e..57a28e86c 100644 --- a/system-tests/fixtures/android-container/build.gradle +++ b/system-tests/fixtures/android-container/build.gradle @@ -1,11 +1,11 @@ buildscript { repositories { google() - mavenCentral() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:7.0.4' + classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.21' } } diff --git a/system-tests/fixtures/android-container/gradle.properties b/system-tests/fixtures/android-container/gradle.properties index 0566c221d..a46a5b90f 100644 --- a/system-tests/fixtures/android-container/gradle.properties +++ b/system-tests/fixtures/android-container/gradle.properties @@ -9,7 +9,8 @@ # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xmx1536m +# Default value: -Xmx512m -XX:MaxMetaspaceSize=256m +org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit @@ -22,3 +23,19 @@ org.gradle.jvmargs=-Xmx1536m android.useAndroidX=true # Automatically convert third-party libraries to use AndroidX android.enableJetifier=true + +# Use this property to specify which architecture you want to build. +# You can also override it from the CLI using +# ./gradlew -PreactNativeArchitectures=x86_64 +reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 + +# Use this property to enable support to the new architecture. +# This will allow you to use TurboModules and the Fabric render in +# your application. You should enable this flag either if you want +# to write custom TurboModules/Fabric components OR use libraries that +# are providing them. +newArchEnabled=false + +# Use this property to enable or disable the Hermes JS engine. +# If set to false, you will be using JSC instead. +hermesEnabled=true diff --git a/system-tests/fixtures/android-container/gradle/wrapper/gradle-wrapper.jar b/system-tests/fixtures/android-container/gradle/wrapper/gradle-wrapper.jar index 7454180f2..943f0cbfa 100644 Binary files a/system-tests/fixtures/android-container/gradle/wrapper/gradle-wrapper.jar and b/system-tests/fixtures/android-container/gradle/wrapper/gradle-wrapper.jar differ diff --git a/system-tests/fixtures/android-container/gradle/wrapper/gradle-wrapper.properties b/system-tests/fixtures/android-container/gradle/wrapper/gradle-wrapper.properties index 669386b87..37a6725dd 100644 --- a/system-tests/fixtures/android-container/gradle/wrapper/gradle-wrapper.properties +++ b/system-tests/fixtures/android-container/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-all.zip +networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/system-tests/fixtures/android-container/gradlew b/system-tests/fixtures/android-container/gradlew index 1b6c78733..65dcd68d6 100755 --- a/system-tests/fixtures/android-container/gradlew +++ b/system-tests/fixtures/android-container/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,10 +80,10 @@ do esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" +# This is normally unused +# shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' @@ -143,12 +143,16 @@ fi if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -205,6 +209,12 @@ set -- \ org.gradle.wrapper.GradleWrapperMain \ "$@" +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/system-tests/fixtures/android-container/gradlew.bat b/system-tests/fixtures/android-container/gradlew.bat index ac1b06f93..6689b85be 100644 --- a/system-tests/fixtures/android-container/gradlew.bat +++ b/system-tests/fixtures/android-container/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,8 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/system-tests/fixtures/android-container/lib/build.gradle b/system-tests/fixtures/android-container/lib/build.gradle index d48a3e1ba..d5d3be533 100644 --- a/system-tests/fixtures/android-container/lib/build.gradle +++ b/system-tests/fixtures/android-container/lib/build.gradle @@ -1,11 +1,13 @@ apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' android { - compileSdkVersion 31 - buildToolsVersion "31.0.0" + namespace "com.walmartlabs.ern.container" + compileSdkVersion 35 + buildToolsVersion "35.0.0" defaultConfig { minSdkVersion 19 - targetSdkVersion 30 + targetSdkVersion 35 } buildTypes { release { @@ -13,8 +15,8 @@ android { } } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 } configurations.all { resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.0' @@ -25,10 +27,15 @@ android { lintOptions { abortOnError false } + publishing { + multipleVariants { + allVariants() + } + } } dependencies { - api 'com.walmartlabs.ern:react-native:0.63.4' + api 'com.walmartlabs.ern:react-android:0.63.4' } gradle.projectsEvaluated { diff --git a/system-tests/fixtures/android-container/lib/src/main/AndroidManifest.xml b/system-tests/fixtures/android-container/lib/src/main/AndroidManifest.xml index 28d3c0d07..4bf2ab5c1 100644 --- a/system-tests/fixtures/android-container/lib/src/main/AndroidManifest.xml +++ b/system-tests/fixtures/android-container/lib/src/main/AndroidManifest.xml @@ -1,5 +1,4 @@ - + diff --git a/system-tests/fixtures/android-container/lib/src/main/java/com/walmartlabs/ern/container/ElectrodeReactActivityDelegate.java b/system-tests/fixtures/android-container/lib/src/main/java/com/walmartlabs/ern/container/ElectrodeReactActivityDelegate.java index 6846a8267..e99c7403a 100644 --- a/system-tests/fixtures/android-container/lib/src/main/java/com/walmartlabs/ern/container/ElectrodeReactActivityDelegate.java +++ b/system-tests/fixtures/android-container/lib/src/main/java/com/walmartlabs/ern/container/ElectrodeReactActivityDelegate.java @@ -191,7 +191,7 @@ private ReactRootView getReactAppView( ReactRootViewHolder rootViewHolder = mReactRootViews.get(componentName); if (rootViewHolder == null || newInstance || rootViewHolder.size() > 1) { - ReactRootView rootView = createRootView(); + ReactRootView rootView = new ReactRootView(getContext()); rootView.startReactApplication( ElectrodeReactContainer.getReactInstanceManager(), componentName, props); if (rootViewHolder == null) { diff --git a/system-tests/fixtures/android-container/lib/src/main/java/com/walmartlabs/ern/container/plugins/BridgePlugin.java b/system-tests/fixtures/android-container/lib/src/main/java/com/walmartlabs/ern/container/plugins/BridgePlugin.java index bb7bdbd99..9c3fb2820 100644 --- a/system-tests/fixtures/android-container/lib/src/main/java/com/walmartlabs/ern/container/plugins/BridgePlugin.java +++ b/system-tests/fixtures/android-container/lib/src/main/java/com/walmartlabs/ern/container/plugins/BridgePlugin.java @@ -1,8 +1,8 @@ package com.walmartlabs.ern.container.plugins; import android.app.Application; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.facebook.react.ReactPackage; import com.walmartlabs.electrode.reactnative.bridge.ElectrodeBridgePackage; diff --git a/system-tests/fixtures/api-impl-native/ern-movie-api-impl/android/gradle/wrapper/gradle-wrapper.properties b/system-tests/fixtures/api-impl-native/ern-movie-api-impl/android/gradle/wrapper/gradle-wrapper.properties index a0f7639f7..e69d0402a 100644 --- a/system-tests/fixtures/api-impl-native/ern-movie-api-impl/android/gradle/wrapper/gradle-wrapper.properties +++ b/system-tests/fixtures/api-impl-native/ern-movie-api-impl/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/system-tests/fixtures/api-impl-native/ern-movie-api-impl/android/lib/build.gradle b/system-tests/fixtures/api-impl-native/ern-movie-api-impl/android/lib/build.gradle index a23784c8d..0b6f015c0 100644 --- a/system-tests/fixtures/api-impl-native/ern-movie-api-impl/android/lib/build.gradle +++ b/system-tests/fixtures/api-impl-native/ern-movie-api-impl/android/lib/build.gradle @@ -1,11 +1,12 @@ apply plugin: 'com.android.library' android { - compileSdkVersion 31 - buildToolsVersion "31.0.0" + namespace "com.walmartlabs.ern." + compileSdkVersion 36 + buildToolsVersion "36.0.0" defaultConfig { - minSdkVersion 21 - targetSdkVersion 30 + minSdkVersion 24 + targetSdkVersion 36 testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { @@ -15,8 +16,8 @@ android { } } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 } lintOptions { abortOnError false @@ -27,6 +28,6 @@ dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0' - implementation 'com.walmartlabs.ern:react-native:0.67.5' + implementation 'com.walmartlabs.ern:react-native:0.81.5' testImplementation 'junit:junit:4.12' } diff --git a/system-tests/fixtures/api-impl-native/ern-movie-api-impl/android/lib/src/main/AndroidManifest.xml b/system-tests/fixtures/api-impl-native/ern-movie-api-impl/android/lib/src/main/AndroidManifest.xml index 3511fd5b7..f2b369e3f 100644 --- a/system-tests/fixtures/api-impl-native/ern-movie-api-impl/android/lib/src/main/AndroidManifest.xml +++ b/system-tests/fixtures/api-impl-native/ern-movie-api-impl/android/lib/src/main/AndroidManifest.xml @@ -1,2 +1,2 @@ - + diff --git a/system-tests/fixtures/api-impl-native/ern-movie-api-impl/ios/Podfile b/system-tests/fixtures/api-impl-native/ern-movie-api-impl/ios/Podfile index fbb1a3e71..b81272d2a 100644 --- a/system-tests/fixtures/api-impl-native/ern-movie-api-impl/ios/Podfile +++ b/system-tests/fixtures/api-impl-native/ern-movie-api-impl/ios/Podfile @@ -1,33 +1,57 @@ -require_relative '../node_modules/react-native/scripts/react_native_pods' -require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' +ENV['RCT_NEW_ARCH_ENABLED'] = '0' +# Resolve react_native_pods.rb with node to allow for hoisting +require Pod::Executable.execute_command('node', ['-p', + 'require.resolve( + "react-native/scripts/react_native_pods.rb", + {paths: [process.argv[1]]}, + )', __dir__]).strip -platform :ios, '11.0' +platform :ios, '15.1' +prepare_react_native_project! +linkage = ENV['USE_FRAMEWORKS'] +if linkage != nil + Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green + use_frameworks! :linkage => linkage.to_sym +end + target 'ElectrodeApiImpl' do config = use_native_modules! use_react_native!( - :path => "../node_modules/react-native" + :path => config[:reactNativePath], + :fabric_enabled => false, + # An absolute path to your application root. + :app_path => "#{Pod::Config.instance.installation_root}" ) post_install do |installer| - react_native_post_install(installer) - - # Workaround for FBReactNativeSpec dependency cycle issue - # https://github.com/facebook/react-native/issues/31034#issuecomment-812564390 - # https://github.com/electrode-io/electrode-native-manifest/pull/217 + # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202 + react_native_post_install( + installer, + config[:reactNativePath], + :mac_catalyst_enabled => false, + # :ccache_enabled => true + ) + + # https://github.com/facebook/react-native/issues/35863#issuecomment-1414536814 + PLIST_BUDDY_PATH = '/usr/libexec/PlistBuddy' installer.pods_project.targets.each do |target| target.build_configurations.each do |config| - config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES' - end - - if (target.name&.eql?('FBReactNativeSpec')) - target.build_phases.each do |build_phase| - if (build_phase.respond_to?(:name) && build_phase.name.eql?('[CP-User] Generate Specs')) - target.build_phases.move(build_phase, 0) + if target.name == "hermes-engine" + installer.pods_project.files.each do |fileref| + if fileref.path.end_with? "hermes.xcframework" + hermes_plist_file = "#{fileref.real_path}/Info.plist" + # Patch Hermes to remove the debug symbols entry from the Info.plist (as it's not shipped with it) + # This might be removed once Hermes starts to ship with Debug symbols or we remove our + # direct dependency from the Main iOS target on "hermes.xcframework" + Open3.capture3(PLIST_BUDDY_PATH, '-c', 'Delete :AvailableLibraries:0:DebugSymbolsPath', hermes_plist_file) + Open3.capture3(PLIST_BUDDY_PATH, '-c', 'Delete :AvailableLibraries:1:DebugSymbolsPath', hermes_plist_file) + Open3.capture3(PLIST_BUDDY_PATH, '-c', 'Delete :AvailableLibraries:2:DebugSymbolsPath', hermes_plist_file) + end end end end