From 139d6bf4111a56ae8a5410dbf9f732bb17ea041b Mon Sep 17 00:00:00 2001 From: Adam Trzcinski Date: Tue, 24 Oct 2023 19:26:38 +0200 Subject: [PATCH] feat: adroid gradle wrapper update --- .../src/commands/buildAndroid/index.ts | 3 + .../commands/runAndroid/checkGradleWrapper.ts | 101 ++++++++++++++++++ .../src/commands/runAndroid/index.ts | 3 + 3 files changed, 107 insertions(+) create mode 100644 packages/cli-platform-android/src/commands/runAndroid/checkGradleWrapper.ts diff --git a/packages/cli-platform-android/src/commands/buildAndroid/index.ts b/packages/cli-platform-android/src/commands/buildAndroid/index.ts index 2732b84d3..ff8d30fd8 100644 --- a/packages/cli-platform-android/src/commands/buildAndroid/index.ts +++ b/packages/cli-platform-android/src/commands/buildAndroid/index.ts @@ -10,6 +10,7 @@ import adb from '../runAndroid/adb'; import getAdbPath from '../runAndroid/getAdbPath'; import {getTaskNames} from '../runAndroid/getTaskNames'; import {promptForTaskSelection} from '../runAndroid/listAndroidTasks'; +import {checkGradleWrapper} from '../runAndroid/checkGradleWrapper'; export interface BuildFlags { mode?: string; @@ -26,6 +27,8 @@ async function buildAndroid( ) { const androidProject = getAndroidProject(config); + await checkGradleWrapper(config.root); + if (args.tasks && args.mode) { logger.warn( 'Both "tasks" and "mode" parameters were passed to "build" command. Using "tasks" for building the app.', diff --git a/packages/cli-platform-android/src/commands/runAndroid/checkGradleWrapper.ts b/packages/cli-platform-android/src/commands/runAndroid/checkGradleWrapper.ts new file mode 100644 index 000000000..9ae49473a --- /dev/null +++ b/packages/cli-platform-android/src/commands/runAndroid/checkGradleWrapper.ts @@ -0,0 +1,101 @@ +import path from 'path'; +import fs from 'fs'; +import {logger, prompt, version} from '@react-native-community/cli-tools'; +import chalk from 'chalk'; +import execa from 'execa'; + +// TODO: Fetch it from somewhere? +const gradleWrapperVersionsMap: Record = { + 68: '7.3', + 69: '7.3', + 70: '7.5', + 71: '7.5', + 72: '8.0', +}; + +const findGradlewWrapperVersion = (root: string) => { + // TODO: In upgrade helper we should have ifno warning users not to upgrade this file manually or this would fail... + const gradlePropertiesFilePath = path.join( + root, + 'android/gradle/wrapper/gradle-wrapper.properties', + ); + let propertiesContent = ''; + if (fs.existsSync(gradlePropertiesFilePath)) { + propertiesContent = fs.readFileSync(gradlePropertiesFilePath, 'utf-8'); + } + const match = propertiesContent.match(/\d+(\.\d+)+/); + if (match) { + return match[0]; + } + return undefined; +}; + +const askForGradleUpdate = async ( + gradleVersionForCurrent: string, + gradlewWrapperVersion: string, +) => { + logger.info(`We have detected that you have outdated Gradle Wrapper in your Android project. + Current version is ${chalk.bold( + gradlewWrapperVersion, + )} while recommended version is ${chalk.bold( + gradleVersionForCurrent, + )}. Would you like to run automatic update?`); + return await prompt({ + name: 'update', + type: 'select', + message: `Upgrade Gradle Wrapper to ${gradleVersionForCurrent}?`, + choices: [ + {title: 'Yes', value: true}, + {title: 'No', value: false}, + ], + }); +}; + +const runGradleWrapperUpdateTwice = (gradleVersionForCurrent: string) => { + logger.info('Upgrading gradle wrapper files'); + try { + const cmd = process.platform.startsWith('win') + ? 'gradlew.bat' + : './gradlew'; + const gradleArgs = [ + 'wrapper', + `--gradle-version=${gradleVersionForCurrent}`, + '--distribution-type=all', + ]; + logger.debug( + `Running command "cd android && ${cmd} ${gradleArgs.join(' ')}"`, + ); + execa.sync(cmd, gradleArgs, {stdio: 'inherit', cwd: 'android'}); + execa.sync(cmd, gradleArgs, {stdio: 'inherit', cwd: 'android'}); + } catch (error) { + return; + } +}; + +export const checkGradleWrapper = async (projectRoot: string) => { + if (process.env.CI) { + return; + } + const semver = version.current(projectRoot); + const minor = semver?.minor; + if (!minor) { + return; + } + const gradleVersionForCurrent = gradleWrapperVersionsMap[minor]; + const gradlewWrapperVersion = findGradlewWrapperVersion(projectRoot); + if (!gradlewWrapperVersion) { + return; + } + // TODO: Do we care about minor and patch or only major version? + if ( + gradleVersionForCurrent.slice(0, 2) !== gradlewWrapperVersion.slice(0, 2) + ) { + const {update} = await askForGradleUpdate( + gradleVersionForCurrent, + gradlewWrapperVersion, + ); + if (update) { + runGradleWrapperUpdateTwice(gradleVersionForCurrent); + } + } +}; diff --git a/packages/cli-platform-android/src/commands/runAndroid/index.ts b/packages/cli-platform-android/src/commands/runAndroid/index.ts index 63636d64b..ce6f05a2a 100644 --- a/packages/cli-platform-android/src/commands/runAndroid/index.ts +++ b/packages/cli-platform-android/src/commands/runAndroid/index.ts @@ -30,6 +30,7 @@ import {build, BuildFlags, options} from '../buildAndroid'; import {promptForTaskSelection} from './listAndroidTasks'; import {getTaskNames} from './getTaskNames'; import {checkUsers, promptForUser} from './listAndroidUsers'; +import {checkGradleWrapper} from './checkGradleWrapper'; export interface Flags extends BuildFlags { appId: string; @@ -74,6 +75,8 @@ async function runAndroid(_argv: Array, config: Config, args: Flags) { link.setVersion(config.reactNativeVersion); } + await checkGradleWrapper(config.root); + if (args.binaryPath) { if (args.tasks) { throw new CLIError(