[Re-land] Enforce a policy on supported Gradle, Java, AGP, and KGP versions (#143132)

Re land of https://github.com/flutter/flutter/pull/142000. 
Differences:
1. Fixed the test that was failing in postsubmit. The reason was that the Flutter Gradle Plugin was being applied after KGP in that test, so we couldn't find the KGP version. This caused a log, and the test expects no logs. I moved FGP to after KGP
2. Added to the logs for when we can't find AGP. Change is from
>  "Warning: unable to detect project AGP version. Skipping version checking."

to 
> ~"Warning: unable to detect project AGP version. Skipping version checking. \nThis may be because you have applied the Flutter Gradle Plugin after AGP."~

update: the above is wrong, changed to 
> "Warning: unable to detect project KGP version. Skipping version checking. \nThis may be because you have applied AGP after the Flutter Gradle Plugin."

3. Added a note to the app-level build.gradle templates that FGP must go last
> // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugin.
This commit is contained in:
Gray Mackall 2024-02-08 14:10:58 -08:00 committed by GitHub
parent d1d690276d
commit 4b0abc7771
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 594 additions and 4 deletions

View file

@ -4,8 +4,8 @@
plugins {
id "com.android.application"
id "dev.flutter.flutter-gradle-plugin"
id "kotlin-android"
id "dev.flutter.flutter-gradle-plugin"
}
android {

View file

@ -28,8 +28,9 @@ gradlePlugin {
dependencies {
// When bumping, also update:
// * ndkVersion in FlutterExtension in packages/flutter_tools/gradle/src/main/flutter.groovy
// * ndkVersion in FlutterExtension in packages/flutter_tools/gradle/src/main/groovy/flutter.groovy
// * AGP version in the buildscript block in packages/flutter_tools/gradle/src/main/groovy/flutter.groovy
// * AGP version in the buildscript block in packages/flutter_tools/gradle/src/main/kotlin/dependency_version_checker.gradle.kts
// * AGP version constants in packages/flutter_tools/lib/src/android/gradle_utils.dart
// * AGP version in buildscript block in packages/flutter_tools/gradle/src/main/flutter.groovy
compileOnly("com.android.tools.build:gradle:7.3.0")
}

View file

@ -113,7 +113,8 @@ buildscript {
}
dependencies {
// When bumping, also update:
// * ndkVersion in FlutterExtension in packages/flutter_tools/gradle/src/main/flutter.groovy
// * ndkVersion in FlutterExtension in packages/flutter_tools/gradle/src/main/groovy/flutter.groovy
// * AGP version in the buildscript block in packages/flutter_tools/gradle/src/main/kotlin/dependency_version_checker.gradle.kts
// * AGP version constants in packages/flutter_tools/lib/src/android/gradle_utils.dart
// * AGP version in dependencies block in packages/flutter_tools/gradle/build.gradle.kts
classpath("com.android.tools.build:gradle:7.3.0")
@ -321,6 +322,28 @@ class FlutterPlugin implements Plugin<Project> {
String flutterExecutableName = Os.isFamily(Os.FAMILY_WINDOWS) ? "flutter.bat" : "flutter"
flutterExecutable = Paths.get(flutterRoot.absolutePath, "bin", flutterExecutableName).toFile()
// Validate that the provided Gradle, Java, AGP, and KGP versions are all within our
// supported range.
// TODO(gmackall) Dependency version checking is currently implemented as an additional
// Gradle plugin because we can't import it from Groovy code. As part of the Groovy
// -> Kotlin migration, we should remove this complexity and perform the checks inside
// of the main Flutter Gradle Plugin.
// See https://github.com/flutter/flutter/issues/121541#issuecomment-1920363687.
final Boolean shouldSkipDependencyChecks = project.hasProperty("skipDependencyChecks")
&& project.getProperty("skipDependencyChecks");
if (!shouldSkipDependencyChecks) {
try {
final String dependencyCheckerPluginPath = Paths.get(flutterRoot.absolutePath,
"packages", "flutter_tools", "gradle", "src", "main", "kotlin",
"dependency_version_checker.gradle.kts")
project.apply from: dependencyCheckerPluginPath
} catch (Exception ignored) {
project.logger.error("Warning: Flutter was unable to detect project Gradle, Java, " +
"AGP, and KGP versions. Skipping dependency version checking. Error was: "
+ ignored)
}
}
// Use Kotlin DSL to handle baseApplicationName logic due to Groovy dynamic dispatch bug.
project.apply from: Paths.get(flutterRoot.absolutePath, "packages", "flutter_tools", "gradle", "src", "main", "kotlin", "flutter.gradle.kts")
@ -1515,6 +1538,8 @@ abstract class BaseFlutterTask extends DefaultTask {
@Optional @Input
Boolean validateDeferredComponents
@Optional @Input
Boolean skipDependencyChecks
@Optional @Input
String flavor

View file

@ -0,0 +1,330 @@
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import org.gradle.api.JavaVersion
import org.jetbrains.kotlin.gradle.plugin.KotlinAndroidPluginWrapper
// This buildscript block supplies dependencies for this file's own import
// declarations above. It exists solely for compatibility with projects that
// have not migrated to declaratively apply the Flutter Gradle Plugin;
// for those that have, FGP's `build.gradle.kts` takes care of this.
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
// When bumping, also update:
// * ndkVersion in FlutterExtension in packages/flutter_tools/gradle/src/main/groovy/flutter.groovy
// * AGP version in the buildscript block in packages/flutter_tools/gradle/src/main/groovy/flutter.groovy
// * AGP version constants in packages/flutter_tools/lib/src/android/gradle_utils.dart
// * AGP version in dependencies block in packages/flutter_tools/gradle/build.gradle.kts
classpath("com.android.tools.build:gradle:7.3.0")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.10")
}
}
apply<FlutterDependencyCheckerPlugin>()
class FlutterDependencyCheckerPlugin : Plugin<Project> {
override fun apply(project: Project) {
DependencyVersionChecker.checkDependencyVersions(project)
}
}
class DependencyVersionChecker {
companion object {
private const val GRADLE_NAME : String = "Gradle"
private const val JAVA_NAME : String = "Java"
private const val AGP_NAME : String = "Android Gradle Plugin"
private const val KGP_NAME : String = "Kotlin"
// The following messages represent best effort guesses at where a Flutter developer should
// look to upgrade a dependency that is below the corresponding threshold. Developers can
// change some of these locations, so they are not guaranteed to be accurate.
private fun getPotentialGradleFix(projectDirectory : String) : String {
return "Your project's gradle version is typically " +
"defined in the gradle wrapper file. By default, this can be found at " +
"$projectDirectory/gradle/wrapper/gradle-wrapper.properties. \n" +
"For more information, see https://docs.gradle.org/current/userguide/gradle_wrapper.html."
}
// The potential java fix does not make use of the project directory,
// so it left as a constant.
private const val POTENTIAL_JAVA_FIX : String = "The Java version used by Flutter can be " +
"set with `flutter config --jdk-dir=<path>`. \nFor more information about how Flutter " +
"chooses which version of Java to use, see the --jdk-dir section of the " +
"output of `flutter config -h`."
private fun getPotentialAGPFix(projectDirectory : String) : String {
return "Your project's AGP version is typically " +
"defined the plugins block of the `settings.gradle` file " +
"($projectDirectory/settings.gradle), by a plugin with the id of " +
"com.android.application. \nIf you don't see a plugins block, your project " +
"was likely created with an older template version. In this case it is most " +
"likely defined in the top-level build.gradle file " +
"($projectDirectory/build.gradle) by the following line in the dependencies" +
" block of the buildscript: \"classpath 'com.android.tools.build:gradle:<version>'\"."
}
private fun getPotentialKGPFix(projectDirectory : String) : String {
return "Your project's KGP version is typically " +
"defined the plugins block of the `settings.gradle` file " +
"($projectDirectory/settings.gradle), by a plugin with the id of " +
"org.jetbrains.kotlin.android. \nIf you don't see a plugins block, your project " +
"was likely created with an older template version, in which case it is most " +
"likely defined in the top-level build.gradle file " +
"($projectDirectory/build.gradle) by the ext.kotlin_version property."
}
// The following versions define our support policy for Gradle, Java, AGP, and KGP.
// All "error" versions are currently set to 0 as this policy is new. They will be increased
// to match the current values of the "warn" versions in the next release.
// Before updating any "error" version, ensure that you have updated the corresponding
// "warn" version for a full release to provide advanced warning. See
// flutter.dev/go/android-dependency-versions for more.
// TODO(gmackall): https://github.com/flutter/flutter/issues/142653.
val warnGradleVersion : Version = Version(7,0,2)
val errorGradleVersion : Version = Version(0,0,0)
val warnJavaVersion : JavaVersion = JavaVersion.VERSION_11
val errorJavaVersion : JavaVersion = JavaVersion.VERSION_1_1
val warnAGPVersion : Version = Version(7,0,0)
val errorAGPVersion : Version = Version(0,0,0)
val warnKGPVersion : Version = Version(1,5,0)
val errorKGPVersion : Version = Version(0,0,0)
/**
* Checks if the project's Android build time dependencies are each within the respective
* version range that we support. When we can't find a version for a given dependency
* we treat it as within the range for the purpose of this check.
*/
fun checkDependencyVersions(project : Project) {
var agpVersion : Version? = null
var kgpVersion : Version? = null
checkGradleVersion(getGradleVersion(project), project)
checkJavaVersion(getJavaVersion(project), project)
agpVersion = getAGPVersion(project)
if (agpVersion != null) {
checkAGPVersion(agpVersion, project)
} else {
project.logger.error("Warning: unable to detect project AGP version. Skipping " +
"version checking. \nThis may be because you have applied AGP after the Flutter Gradle Plugin.")
}
kgpVersion = getKGPVersion(project)
if (kgpVersion != null) {
checkKGPVersion(kgpVersion, project)
} else {
project.logger.error("Warning: unable to detect project KGP version. Skipping " +
"version checking. \nThis may be because you have applied KGP after the Flutter Gradle Plugin.")
}
}
// https://docs.gradle.org/current/kotlin-dsl/gradle/org.gradle.api.invocation/-gradle/index.html#-837060600%2FFunctions%2F-1793262594
fun getGradleVersion(project : Project) : Version {
val untrimmedGradleVersion : String = project.gradle.getGradleVersion()
// Trim to handle candidate gradle versions (example 7.6-rc-4). This means we treat all
// candidate versions of gradle as the same as their base version
// (i.e., "7.6"="7.6-rc-4").
return Version.fromString(untrimmedGradleVersion.substringBefore('-'))
}
// https://docs.gradle.org/current/kotlin-dsl/gradle/org.gradle.api/-java-version/index.html#-1790786897%2FFunctions%2F-1793262594
fun getJavaVersion(project : Project) : JavaVersion {
return JavaVersion.current()
}
// This approach is taken from AGP's own version checking plugin:
// https://android.googlesource.com/platform/tools/base/+/1839aa23b8dc562005e2f0f0cc8e8b4c5caa37d0/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/utils/agpVersionChecker.kt#58.
fun getAGPVersion(project: Project): Version? {
val agpPluginName : String = "com.android.base";
val agpVersionFieldName : String = "ANDROID_GRADLE_PLUGIN_VERSION"
var agpVersion: Version? = null
try {
agpVersion = Version.fromString(
project.plugins.getPlugin(agpPluginName)::class.java.classLoader.loadClass(
com.android.Version::class.java.name
).fields.find { it.name == agpVersionFieldName }!!
.get(null) as String
)
} catch (ignored: ClassNotFoundException) {
// Use deprecated Version class as it exists in older AGP (com.android.Version) does
// not exist in those versions.
agpVersion = Version.fromString(
project.plugins.getPlugin(agpPluginName)::class.java.classLoader.loadClass(
com.android.builder.model.Version::class.java.name
).fields.find { it.name == agpVersionFieldName }!!
.get(null) as String
)
}
return agpVersion
}
fun getKGPVersion(project : Project) : Version? {
val kotlinVersionProperty : String = "kotlin_version"
val firstKotlinVersionFieldName : String = "pluginVersion"
val secondKotlinVersionFieldName : String = "kotlinPluginVersion"
// This property corresponds to application of the Kotlin Gradle plugin in the
// top-level build.gradle file.
if (project.hasProperty(kotlinVersionProperty)) {
return Version.fromString(project.properties.get(kotlinVersionProperty) as String)
}
val kotlinPlugin = project.getPlugins()
.findPlugin(KotlinAndroidPluginWrapper::class.java)
val versionfield =
kotlinPlugin?.javaClass?.kotlin?.members?.first { it.name == firstKotlinVersionFieldName || it.name == secondKotlinVersionFieldName }
val versionString = versionfield?.call(kotlinPlugin)
if (versionString == null) {
return null
} else {
return Version.fromString(versionString!! as String)
}
}
private fun getErrorMessage(dependencyName : String,
versionString : String,
errorVersion : String,
potentialFix : String) : String {
return "Error: Your project's $dependencyName version ($versionString) is lower " +
"than Flutter's minimum supported version of $errorVersion. Please upgrade " +
"your $dependencyName version. \nAlternatively, use the flag " +
"\"--android-skip-build-dependency-validation\" to bypass this check.\n\n" +
"Potential fix: $potentialFix"
}
private fun getWarnMessage(dependencyName : String,
versionString : String,
warnVersion : String,
potentialFix : String) : String {
return "Warning: Flutter support for your project's $dependencyName version " +
"($versionString) will soon be dropped. Please upgrade your $dependencyName " +
"version to a version of at least $warnVersion soon." +
"\nAlternatively, use the flag \"--android-skip-build-dependency-validation\"" +
" to bypass this check.\n\n Potential fix: $potentialFix"
}
fun checkGradleVersion(version : Version, project : Project) {
if (version < errorGradleVersion) {
val errorMessage : String = getErrorMessage(
GRADLE_NAME,
version.toString(),
errorGradleVersion.toString(),
getPotentialGradleFix(project.getRootDir().getPath())
)
throw GradleException(errorMessage)
}
else if (version < warnGradleVersion) {
val warnMessage : String = getWarnMessage(
GRADLE_NAME,
version.toString(),
warnGradleVersion.toString(),
getPotentialGradleFix(project.getRootDir().getPath())
)
project.logger.error(warnMessage)
}
}
fun checkJavaVersion(version : JavaVersion, project : Project) {
if (version < errorJavaVersion) {
val errorMessage : String = getErrorMessage(
JAVA_NAME,
version.toString(),
errorJavaVersion.toString(),
POTENTIAL_JAVA_FIX
)
throw GradleException(errorMessage)
}
else if (version < warnJavaVersion) {
val warnMessage : String = getWarnMessage(
JAVA_NAME,
version.toString(),
warnJavaVersion.toString(),
POTENTIAL_JAVA_FIX
)
project.logger.error(warnMessage)
}
}
fun checkAGPVersion(version : Version, project : Project) {
if (version < errorAGPVersion) {
val errorMessage : String = getErrorMessage(
AGP_NAME,
version.toString(),
errorAGPVersion.toString(),
getPotentialAGPFix(project.getRootDir().getPath())
)
throw GradleException(errorMessage)
}
else if (version < warnAGPVersion) {
val warnMessage : String = getWarnMessage(
AGP_NAME,
version.toString(),
warnAGPVersion.toString(),
getPotentialAGPFix(project.getRootDir().getPath())
)
project.logger.error(warnMessage)
}
}
fun checkKGPVersion(version : Version, project : Project) {
if (version < errorKGPVersion) {
val errorMessage : String = getErrorMessage(
KGP_NAME,
version.toString(),
errorKGPVersion.toString(),
getPotentialKGPFix(project.getRootDir().getPath())
)
throw GradleException(errorMessage)
}
else if (version < warnKGPVersion) {
val warnMessage : String = getWarnMessage(
KGP_NAME,
version.toString(),
warnKGPVersion.toString(),
getPotentialKGPFix(project.getRootDir().getPath())
)
project.logger.error(warnMessage)
}
}
}
}
// Helper class to parse the versions that are provided as plain strings (Gradle, Kotlin) and
// perform easy comparisons. All versions will have a major, minor, and patch value. These values
// default to 0 when they are not provided or are otherwise unparseable.
// For example the version strings "8.2", "8.2.2hfd", and "8.2.0" would parse to the same version.
class Version(val major : Int, val minor : Int, val patch : Int) : Comparable<Version> {
companion object {
fun fromString(version : String) : Version {
val asList : List<String> = version.split(".")
val convertedToNumbers : List<Int> = asList.map {it.toIntOrNull() ?: 0}
return Version(
major = convertedToNumbers.getOrElse(0, {0}),
minor = convertedToNumbers.getOrElse(1, {0}),
patch = convertedToNumbers.getOrElse(2, {0})
)
}
}
override fun compareTo(otherVersion : Version) : Int {
if (major != otherVersion.major) {
return major - otherVersion.major
}
if (minor != otherVersion.minor) {
return minor - otherVersion.minor
}
if (patch != otherVersion.patch) {
return patch - otherVersion.patch
}
return 0
}
override fun toString() : String {
return major.toString() + "." + minor.toString() + "." + patch.toString()
}
}

View file

@ -29,6 +29,11 @@ version.
SDK versions are updated (you should see these fail if you do not fix them
preemptively).
Also, make sure to also update to the same version in the following places:
- The version in the buildscript block in `packages/flutter_tools/gradle/src/main/groovy/flutter.groovy`.
- The version in the buildscript block in `packages/flutter_tools/gradle/src/main/kotlin/dependency_version_checker.gradle.kts`.
- The version in the dependencies block in `packages/flutter_tools/gradle/build.gradle.kts`.
#### Gradle
When updating the Gradle version used in project templates
(`templateDefaultGradleVersion`), make sure that:

View file

@ -370,6 +370,9 @@ class AndroidGradleBuilder implements AndroidBuilder {
if (!buildInfo.androidGradleDaemon) {
command.add('--no-daemon');
}
if (buildInfo.androidSkipBuildDependencyValidation) {
command.add('-PskipDependencyChecks=true');
}
final LocalEngineInfo? localEngineInfo = _artifacts.localEngineInfo;
if (localEngineInfo != null) {
final Directory localEngineRepo = _getLocalEngineRepo(

View file

@ -43,6 +43,7 @@ class BuildInfo {
this.nullSafetyMode = NullSafetyMode.sound,
this.codeSizeDirectory,
this.androidGradleDaemon = true,
this.androidSkipBuildDependencyValidation = false,
this.packageConfig = PackageConfig.empty,
this.initializeFromDill,
this.assumeInitializeFromDillUpToDate = false,
@ -158,6 +159,10 @@ class BuildInfo {
/// The Gradle daemon may also be disabled in the Android application's properties file.
final bool androidGradleDaemon;
/// Whether to skip checking of individual versions of our Android build time
/// dependencies.
final bool androidSkipBuildDependencyValidation;
/// Additional key value pairs that are passed directly to the gradle project via the `-P`
/// flag.
final List<String> androidProjectArgs;

View file

@ -147,6 +147,7 @@ abstract final class FlutterOptions {
static const String kAndroidGradleDaemon = 'android-gradle-daemon';
static const String kDeferredComponents = 'deferred-components';
static const String kAndroidProjectArgs = 'android-project-arg';
static const String kAndroidSkipBuildDependencyValidation = 'android-skip-build-dependency-validation';
static const String kInitializeFromDill = 'initialize-from-dill';
static const String kAssumeInitializeFromDillUpToDate = 'assume-initialize-from-dill-up-to-date';
static const String kNativeAssetsYamlFile = 'native-assets-yaml-file';
@ -974,6 +975,12 @@ abstract class FlutterCommand extends Command<void> {
defaultsTo: true,
hide: hide,
);
argParser.addFlag(
FlutterOptions.kAndroidSkipBuildDependencyValidation,
help: 'Whether to skip version checking for Java, Gradle, '
'the Android Gradle Plugin (AGP), and the Kotlin Gradle Plugin (KGP)'
' during Android builds.',
);
argParser.addMultiOption(
FlutterOptions.kAndroidProjectArgs,
help: 'Additional arguments specified as key=value that are passed directly to the gradle '
@ -1228,6 +1235,9 @@ abstract class FlutterCommand extends Command<void> {
final bool androidGradleDaemon = !argParser.options.containsKey(FlutterOptions.kAndroidGradleDaemon)
|| boolArg(FlutterOptions.kAndroidGradleDaemon);
final bool androidSkipBuildDependencyValidation = !argParser.options.containsKey(FlutterOptions.kAndroidSkipBuildDependencyValidation)
|| boolArg(FlutterOptions.kAndroidSkipBuildDependencyValidation);
final List<String> androidProjectArgs = argParser.options.containsKey(FlutterOptions.kAndroidProjectArgs)
? stringsArg(FlutterOptions.kAndroidProjectArgs)
: <String>[];
@ -1323,6 +1333,7 @@ abstract class FlutterCommand extends Command<void> {
nullSafetyMode: nullSafetyMode,
codeSizeDirectory: codeSizeDirectory,
androidGradleDaemon: androidGradleDaemon,
androidSkipBuildDependencyValidation: androidSkipBuildDependencyValidation,
packageConfig: packageConfig,
androidProjectArgs: androidProjectArgs,
initializeFromDill: argParser.options.containsKey(FlutterOptions.kInitializeFromDill)

View file

@ -1,6 +1,7 @@
plugins {
id "com.android.application"
id "kotlin-android"
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
id "dev.flutter.flutter-gradle-plugin"
}

View file

@ -1,6 +1,7 @@
plugins {
id "com.android.application"
id "kotlin-android"
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
id "dev.flutter.flutter-gradle-plugin"
}

View file

@ -0,0 +1,208 @@
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io';
import 'package:file/src/interface/file_system_entity.dart';
import '../integration.shard/test_utils.dart';
import '../src/common.dart';
import '../src/context.dart';
const String gradleSettingsFileContent = r'''
pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}()
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "AGP_REPLACE_ME" apply false
id "org.jetbrains.kotlin.android" version "KGP_REPLACE_ME" apply false
}
include ":app"
''';
const String agpReplacementString = 'AGP_REPLACE_ME';
const String kgpReplacementString = 'KGP_REPLACE_ME';
const String gradleWrapperPropertiesFileContent = r'''
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-GRADLE_REPLACE_ME-all.zip
''';
const String gradleReplacementString = 'GRADLE_REPLACE_ME';
// This test is currently on the preview shard (but not using the preview
// version of Android) because it is the only one using Java 11. This test
// requires Java 11 due to the intentionally low version of Gradle.
void main() {
late Directory tempDir;
setUpAll(() async {
tempDir = createResolvedTempDirectorySync('run_test.');
});
tearDownAll(() async {
tryToDelete(tempDir as FileSystemEntity);
});
testUsingContext(
'AGP version out of "warn" support band prints warning but still builds', () async {
// Create a new flutter project.
final String flutterBin = fileSystem.path.join(getFlutterRoot(), 'bin', 'flutter');
ProcessResult result = await processManager.run(<String>[
flutterBin,
'create',
'dependency_checker_app',
'--platforms=android',
], workingDirectory: tempDir.path);
expect(result, const ProcessResultMatcher());
const String gradleVersion = '7.5';
const String agpVersion = '4.2.0';
const String kgpVersion = '1.7.10';
final Directory app = Directory(fileSystem.path.join(tempDir.path, 'dependency_checker_app'));
// Modify gradle version to passed in version.
final File gradleWrapperProperties = File(fileSystem.path.join(
app.path, 'android', 'gradle', 'wrapper', 'gradle-wrapper.properties'));
final String propertyContent = gradleWrapperPropertiesFileContent.replaceFirst(
gradleReplacementString,
gradleVersion,
);
await gradleWrapperProperties.writeAsString(propertyContent, flush: true);
final File gradleSettings = File(fileSystem.path.join(
app.path, 'android', 'settings.gradle'));
final String settingsContent = gradleSettingsFileContent
.replaceFirst(agpReplacementString, agpVersion)
.replaceFirst(kgpReplacementString, kgpVersion);
await gradleSettings.writeAsString(settingsContent, flush: true);
// Ensure that gradle files exists from templates.
result = await processManager.run(<String>[
flutterBin,
'build',
'apk',
'--debug',
], workingDirectory: app.path);
expect(result, const ProcessResultMatcher());
expect(result.stderr, contains('Please upgrade your Android Gradle '
'Plugin version'));
});
testUsingContext(
'Gradle version out of "warn" support band prints warning but still builds', () async {
// Create a new flutter project.
final String flutterBin = fileSystem.path.join(getFlutterRoot(), 'bin', 'flutter');
ProcessResult result = await processManager.run(<String>[
flutterBin,
'create',
'dependency_checker_app',
'--platforms=android',
], workingDirectory: tempDir.path);
expect(result, const ProcessResultMatcher());
const String gradleVersion = '7.0';
const String agpVersion = '4.2.0';
const String kgpVersion = '1.7.10';
final Directory app = Directory(fileSystem.path.join(tempDir.path, 'dependency_checker_app'));
// Modify gradle version to passed in version.
final File gradleWrapperProperties = File(fileSystem.path.join(
app.path, 'android', 'gradle', 'wrapper', 'gradle-wrapper.properties'));
final String propertyContent = gradleWrapperPropertiesFileContent.replaceFirst(
gradleReplacementString,
gradleVersion,
);
await gradleWrapperProperties.writeAsString(propertyContent, flush: true);
final File gradleSettings = File(fileSystem.path.join(
app.path, 'android', 'settings.gradle'));
final String settingsContent = gradleSettingsFileContent
.replaceFirst(agpReplacementString, agpVersion)
.replaceFirst(kgpReplacementString, kgpVersion);
await gradleSettings.writeAsString(settingsContent, flush: true);
// Ensure that gradle files exists from templates.
result = await processManager.run(<String>[
flutterBin,
'build',
'apk',
'--debug',
], workingDirectory: app.path);
expect(result, const ProcessResultMatcher());
expect(result.stderr, contains('Please upgrade your Gradle version'));
});
testUsingContext(
'Kotlin version out of "warn" support band prints warning but still builds', () async {
// Create a new flutter project.
final String flutterBin = fileSystem.path.join(getFlutterRoot(), 'bin', 'flutter');
ProcessResult result = await processManager.run(<String>[
flutterBin,
'create',
'dependency_checker_app',
'--platforms=android',
], workingDirectory: tempDir.path);
expect(result, const ProcessResultMatcher());
const String gradleVersion = '7.5';
const String agpVersion = '7.4.0';
const String kgpVersion = '1.4.10';
final Directory app = Directory(fileSystem.path.join(tempDir.path, 'dependency_checker_app'));
// Modify gradle version to passed in version.
final File gradleWrapperProperties = File(fileSystem.path.join(
app.path, 'android', 'gradle', 'wrapper', 'gradle-wrapper.properties'));
final String propertyContent = gradleWrapperPropertiesFileContent.replaceFirst(
gradleReplacementString,
gradleVersion,
);
await gradleWrapperProperties.writeAsString(propertyContent, flush: true);
final File gradleSettings = File(fileSystem.path.join(
app.path, 'android', 'settings.gradle'));
final String settingsContent = gradleSettingsFileContent
.replaceFirst(agpReplacementString, agpVersion)
.replaceFirst(kgpReplacementString, kgpVersion);
await gradleSettings.writeAsString(settingsContent, flush: true);
// Ensure that gradle files exists from templates.
result = await processManager.run(<String>[
flutterBin,
'build',
'apk',
'--debug',
], workingDirectory: app.path);
expect(result, const ProcessResultMatcher());
expect(result.stderr, contains('Please upgrade your Kotlin version'));
});
// TODO(gmackall): Add tests for build blocking when the
// corresponding error versions are enabled.
}