Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 38 additions & 19 deletions script/tool/lib/src/update_dependency_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,19 @@ class UpdateDependencyCommand extends PackageLoopingCommand {
argParser.addOption(_androidDependency,
help: 'An Android dependency to update.',
allowed: <String>[
_AndroidDepdencyType.gradle,
_AndroidDepdencyType.compileSdk,
_AndroidDepdencyType.compileSdkForExamples,
_AndroidDependencyType.gradle,
_AndroidDependencyType.androidGradlePlugin,
_AndroidDependencyType.compileSdk,
_AndroidDependencyType.compileSdkForExamples,
],
allowedHelp: <String, String>{
_AndroidDepdencyType.gradle:
_AndroidDependencyType.gradle:
'Updates Gradle version used in plugin example apps.',
_AndroidDepdencyType.compileSdk:
_AndroidDependencyType.androidGradlePlugin:
'Updates AGP version used in plugin example apps.',
_AndroidDependencyType.compileSdk:
'Updates compileSdk version used to compile plugins.',
_AndroidDepdencyType.compileSdkForExamples:
_AndroidDependencyType.compileSdkForExamples:
'Updates compileSdk version used to compile plugin examples.',
});
argParser.addOption(
Expand Down Expand Up @@ -137,22 +140,25 @@ ${response.httpResponse.body}
if (version == null) {
printError('A version must be provided to update this dependency.');
throw ToolExit(_exitNoTargetVersion);
} else if (_targetAndroidDependency == _AndroidDepdencyType.gradle) {
final RegExp validGradleVersionPattern =
} else if (_targetAndroidDependency == _AndroidDependencyType.gradle ||
_targetAndroidDependency ==
_AndroidDependencyType.androidGradlePlugin) {
final RegExp validGradleAGPVersionPattern =
RegExp(r'^\d{1,2}\.\d{1,2}(?:\.\d)?$');
final bool isValidGradleVersion =
validGradleVersionPattern.stringMatch(version) == version;
if (!isValidGradleVersion) {
final bool isValidGradleAGPVersion =
validGradleAGPVersionPattern.stringMatch(version) == version;
if (!isValidGradleAGPVersion) {
printError('''
A version with a valid format (maximum 2-3 numbers separated by 1-2 periods) must be provided.
1. The first number must have one or two digits
2. The second number must have one or two digits
3. If present, the third number must have a single digit''');
throw ToolExit(_exitInvalidTargetVersion);
}
} else if (_targetAndroidDependency == _AndroidDepdencyType.compileSdk ||
} else if (_targetAndroidDependency ==
_AndroidDependencyType.compileSdk ||
_targetAndroidDependency ==
_AndroidDepdencyType.compileSdkForExamples) {
_AndroidDependencyType.compileSdkForExamples) {
final RegExp validSdkVersion = RegExp(r'^\d{1,2}$');
final bool isValidSdkVersion =
validSdkVersion.stringMatch(version) == version;
Expand Down Expand Up @@ -254,11 +260,13 @@ A version with a valid format (maximum 2-3 numbers separated by 1-2 periods) mus
/// an Android dependency.
Future<PackageResult> _runForAndroidDependency(
RepositoryPackage package) async {
if (_targetAndroidDependency == _AndroidDepdencyType.compileSdk) {
if (_targetAndroidDependency == _AndroidDependencyType.compileSdk) {
return _runForCompileSdkVersion(package);
} else if (_targetAndroidDependency == _AndroidDepdencyType.gradle ||
} else if (_targetAndroidDependency == _AndroidDependencyType.gradle ||
_targetAndroidDependency ==
_AndroidDepdencyType.compileSdkForExamples) {
_AndroidDependencyType.compileSdkForExamples ||
_targetAndroidDependency ==
_AndroidDependencyType.androidGradlePlugin) {
return _runForAndroidDependencyOnExamples(package);
}

Expand All @@ -283,7 +291,7 @@ A version with a valid format (maximum 2-3 numbers separated by 1-2 periods) mus
final RegExp dependencyVersionPattern;
final String newDependencyVersionEntry;

if (_targetAndroidDependency == _AndroidDepdencyType.gradle) {
if (_targetAndroidDependency == _AndroidDependencyType.gradle) {
if (androidDirectory
.childDirectory('gradle')
.childDirectory('wrapper')
Expand Down Expand Up @@ -311,12 +319,22 @@ A version with a valid format (maximum 2-3 numbers separated by 1-2 periods) mus
newDependencyVersionEntry =
'distributionUrl=https\\://services.gradle.org/distributions/gradle-$_targetVersion-all.zip';
} else if (_targetAndroidDependency ==
_AndroidDepdencyType.compileSdkForExamples) {
_AndroidDependencyType.compileSdkForExamples) {
filesToUpdate.add(
androidDirectory.childDirectory('app').childFile('build.gradle'));
dependencyVersionPattern = RegExp(
r'(compileSdk|compileSdkVersion) (\d{1,2}|flutter.compileSdkVersion)');
newDependencyVersionEntry = 'compileSdk $_targetVersion';
} else if (_targetAndroidDependency ==
_AndroidDependencyType.androidGradlePlugin) {
if (androidDirectory.childFile('settings.gradle').existsSync()) {
filesToUpdate.add(androidDirectory.childFile('settings.gradle'));
}
dependencyVersionPattern = RegExp(
r'^\s*id\s+"com\.android\.application"\s+version\s+"(\d{1,2}\.\d{1,2}(?:\.\d)?)"\s+apply\s+false\s*$',
multiLine: true);
newDependencyVersionEntry =
' id "com.android.application" version "$_targetVersion" apply false';
} else {
printError(
'Target Android dependency $_targetAndroidDependency is unrecognized.');
Expand Down Expand Up @@ -504,8 +522,9 @@ class _PubDependencyInfo {

enum _PubDependencyType { normal, dev }

class _AndroidDepdencyType {
class _AndroidDependencyType {
static const String gradle = 'gradle';
static const String androidGradlePlugin = 'androidGradlePlugin';
static const String compileSdk = 'compileSdk';
static const String compileSdkForExamples = 'compileSdkForExamples';
}
150 changes: 142 additions & 8 deletions script/tool/test/update_dependency_command_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -607,15 +607,15 @@ dev_dependencies:
});

group('Android dependencies', () {
group('gradle', () {
final List<String> invalidGradleVersionsFormat = <String>[
'81',
'811.1',
'8.123',
'8.12.12'
];
final List<String> invalidGradleAgpVersionsFormat = <String>[
'81',
'811.1',
'8.123',
'8.12.12'
];

for (final String gradleVersion in invalidGradleVersionsFormat) {
group('gradle', () {
for (final String gradleVersion in invalidGradleAgpVersionsFormat) {
test('throws because gradleVersion: $gradleVersion is invalid',
() async {
Error? commandError;
Expand Down Expand Up @@ -907,6 +907,140 @@ distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-all.zip
'gradle-$newGradleVersion-all.zip'));
});
});
group('agp', () {
for (final String agpVersion in invalidGradleAgpVersionsFormat) {
test('throws because agpVersion: $agpVersion is invalid', () async {
Error? commandError;
final List<String> output = await runCapturingPrint(runner, <String>[
'update-dependency',
'--android-dependency',
'androidGradlePlugin',
'--version',
agpVersion,
], errorHandler: (Error e) {
commandError = e;
});

expect(commandError, isA<ToolExit>());
expect(
output,
containsAllInOrder(<Matcher>[
contains('''
A version with a valid format (maximum 2-3 numbers separated by 1-2 periods) must be provided.
1. The first number must have one or two digits
2. The second number must have one or two digits
3. If present, the third number must have a single digit'''),
]),
);
});
}

test('skips if example app does not run on Android', () async {
final RepositoryPackage package =
createFakePlugin('fake_plugin', packagesDir);

final List<String> output = await runCapturingPrint(runner, <String>[
'update-dependency',
'--packages',
package.displayName,
'--android-dependency',
'androidGradlePlugin',
'--version',
'8.11.1',
]);

expect(
output,
containsAllInOrder(<Matcher>[
contains('SKIPPING: No example apps run on Android.'),
]),
);
});

test('succeeds if example app has android/settings.gradle structure',
() async {
final RepositoryPackage package = createFakePlugin(
'fake_plugin', packagesDir,
extraFiles: <String>['example/android/settings.gradle']);
const String newAgpVersion = '9.9';

final File gradleSettingsFile = package.directory
.childDirectory('example')
.childDirectory('android')
.childFile('settings.gradle');

gradleSettingsFile.writeAsStringSync(r'''
...
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "8.11.1" apply false
...
}
...
''');

await runCapturingPrint(runner, <String>[
'update-dependency',
'--packages',
package.displayName,
'--android-dependency',
'androidGradlePlugin',
'--version',
newAgpVersion,
]);

final String updatedGradleSettingsContents =
gradleSettingsFile.readAsStringSync();

expect(
updatedGradleSettingsContents,
contains(r' id "com.android.application" version '
'"$newAgpVersion" apply false'));
});

test('succeeds if one example app runs on Android and another does not',
() async {
final RepositoryPackage package = createFakePlugin(
'fake_plugin', packagesDir,
examples: <String>['example_1', 'example_2'],
extraFiles: <String>['example/example_2/android/settings.gradle']);
const String newAgpVersion = '9.9';

final File gradleSettingsFile = package.directory
.childDirectory('example')
.childDirectory('example_2')
.childDirectory('android')
.childFile('settings.gradle');

gradleSettingsFile.writeAsStringSync(r'''
...
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "8.11.1" apply false
...
}
...
''');

await runCapturingPrint(runner, <String>[
'update-dependency',
'--packages',
package.displayName,
'--android-dependency',
'androidGradlePlugin',
'--version',
newAgpVersion,
]);

final String updatedGradleSettingsContents =
gradleSettingsFile.readAsStringSync();

expect(
updatedGradleSettingsContents,
contains(r' id "com.android.application" version '
'"$newAgpVersion" apply false'));
});
});

group('compileSdk/compileSdkForExamples', () {
// Tests if the compileSdk version is updated for the provided
Expand Down