Unverified Commit 9a72e1c6 authored by Gray Mackall's avatar Gray Mackall Committed by GitHub

Allow plugins to use compileSdkPreview (#131901)

Fixes https://github.com/flutter/flutter/issues/124748

Based (heavily) off https://github.com/flutter/flutter/pull/104662
parent eb0890c9
......@@ -1076,6 +1076,36 @@ targets:
- bin/**
- .ci.yaml
- name: Linux android_preview_tool_integration_tests
bringup: true
recipe: flutter/flutter_drone
timeout: 60
properties:
add_recipes_cq: "true"
# This makes use of UpsideDownCake, a preview version of android. Preview versions eventually
# get removed from the sdk manager, so it is hosted on CIPD to ensure integration testing
# doesn't flake when that happens.
# https://chrome-infra-packages.appspot.com/p/flutter/android/sdk/all/linux-amd64/+/version:udcv1
dependencies: >-
[
{"dependency": "android_sdk", "version": "version:udcv1"},
{"dependency": "chrome_and_driver", "version": "version:119.0.6045.9"},
{"dependency": "clang", "version": "git_revision:5d5aba78dbbee75508f01bcaa69aedb2ab79065a"},
{"dependency": "cmake", "version": "build_id:8787856497187628321"},
{"dependency": "goldctl", "version": "git_revision:720a542f6fe4f92922c3b8f0fdcc4d2ac6bb83cd"},
{"dependency": "ninja", "version": "version:1.9.0"},
{"dependency": "open_jdk", "version": "version:11"}
]
shard: android_preview_tool_integration_tests
tags: >
["framework", "hostonly", "shard", "linux"]
test_timeout_secs: "2700"
runIf:
- dev/**
- packages/flutter_tools/**
- bin/**
- .ci.yaml
- name: Linux tool_tests_commands
recipe: flutter/flutter_drone
timeout: 60
......
......@@ -253,6 +253,7 @@ Future<void> main(List<String> args) async {
// web_tool_tests is also used by HHH: https://dart.googlesource.com/recipes/+/refs/heads/master/recipes/dart/flutter_engine.py
'web_tool_tests': _runWebToolTests,
'tool_integration_tests': _runIntegrationToolTests,
'android_preview_tool_integration_tests': _runAndroidPreviewIntegrationToolTests,
'tool_host_cross_arch_tests': _runToolHostCrossArchTests,
// All the unit/widget tests run using `flutter test --platform=chrome --web-renderer=html`
'web_tests': _runWebHtmlUnitTests,
......@@ -477,6 +478,20 @@ Future<void> _runIntegrationToolTests() async {
);
}
Future<void> _runAndroidPreviewIntegrationToolTests() async {
final List<String> allTests = Directory(path.join(_toolsPath, 'test', 'android_preview_integration.shard'))
.listSync(recursive: true).whereType<File>()
.map<String>((FileSystemEntity entry) => path.relative(entry.path, from: _toolsPath))
.toList();
await _runDartTest(
_toolsPath,
forceSingleCore: true,
testPaths: _selectIndexOfTotalSubshard<String>(allTests),
collectMetrics: true,
);
}
Future<void> _runToolTests() async {
await selectSubshard(<String, ShardRunner>{
'general': _runGeneralToolTests,
......
......@@ -441,7 +441,7 @@ class FlutterPlugin implements Plugin<Project> {
pluginProject.afterEvaluate {
// Checks if there is a mismatch between the plugin compileSdkVersion and the project compileSdkVersion.
if (pluginProject.android.compileSdkVersion > project.android.compileSdkVersion) {
project.logger.quiet("Warning: The plugin ${pluginName} requires Android SDK version ${pluginProject.android.compileSdkVersion.substring(8)}.")
project.logger.quiet("Warning: The plugin ${pluginName} requires Android SDK version ${getCompileSdkFromProject(pluginProject)}.")
project.logger.quiet("For more information about build configuration, see $kWebsiteDeploymentAndroidBuildConfig.")
}
......@@ -483,9 +483,11 @@ class FlutterPlugin implements Plugin<Project> {
/** Prints error message and fix for any plugin compileSdkVersion or ndkVersion that are higher than the project. */
private void detectLowCompileSdkVersionOrNdkVersion() {
project.afterEvaluate {
int projectCompileSdkVersion = Integer.MAX_VALUE // Default to int max if using a preview version to skip the sdk check.
if (project.android.compileSdkVersion.substring(8).isInteger()) { // Stable versions use ints, legacy preview uses string.
projectCompileSdkVersion = project.android.compileSdkVersion.substring(8) as int
// Default to int max if using a preview version to skip the sdk check.
int projectCompileSdkVersion = Integer.MAX_VALUE
// Stable versions use ints, legacy preview uses string.
if (getCompileSdkFromProject(project).isInteger()) {
projectCompileSdkVersion = getCompileSdkFromProject(project) as int
}
int maxPluginCompileSdkVersion = projectCompileSdkVersion
String ndkVersionIfUnspecified = "21.1.6352462" /* The default for AGP 4.1.0 used in old templates. */
......@@ -496,7 +498,12 @@ class FlutterPlugin implements Plugin<Project> {
getPluginList().each { plugin ->
Project pluginProject = project.rootProject.findProject(plugin.key)
pluginProject.afterEvaluate {
int pluginCompileSdkVersion = pluginProject.android.compileSdkVersion.substring(8) as int
// Default to int min if using a preview version to skip the sdk check.
int pluginCompileSdkVersion = Integer.MIN_VALUE;
// Stable versions use ints, legacy preview uses string.
if (getCompileSdkFromProject(pluginProject).isInteger()) {
pluginCompileSdkVersion = getCompileSdkFromProject(pluginProject) as int;
}
maxPluginCompileSdkVersion = Math.max(pluginCompileSdkVersion, maxPluginCompileSdkVersion)
String pluginNdkVersion = pluginProject.android.ndkVersion ?: ndkVersionIfUnspecified
maxPluginNdkVersion = mostRecentSemanticVersion(pluginNdkVersion, maxPluginNdkVersion)
......@@ -515,6 +522,14 @@ class FlutterPlugin implements Plugin<Project> {
}
}
/**
* Returns the portion of the compileSdkVersion string that corresponds to either the numeric
* or string version.
*/
private String getCompileSdkFromProject(Project gradleProject) {
return gradleProject.android.compileSdkVersion.substring(8);
}
/**
* Returns `true` if the given path contains an `android/build.gradle` file.
*/
......
# Android preview integration tests
This directory contains integration tests which would otherwise live in `integration.shard`,
but require a dependency on a CIPD-hosted preview version of Android (and therefore their own
test shard). For additional information see the README in the `../integration.shard` directory.
\ No newline at end of file
......@@ -5,13 +5,17 @@
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';
import '../integration.shard/test_utils.dart';
import '../src/common.dart';
import 'test_utils.dart';
void main() {
late Directory tempDir;
late String flutterBin;
late Directory exampleAppDir;
late Directory pluginDir;
final RegExp compileSdkVersionMatch = RegExp(r'compileSdk [\w.]+');
final String builtApkPath = <String>['build', 'app', 'outputs', 'flutter-apk', 'app-debug.apk']
.join(platform.pathSeparator);
setUp(() async {
tempDir = createResolvedTempDirectorySync('flutter_plugin_test.');
......@@ -20,7 +24,8 @@ void main() {
'bin',
'flutter',
);
exampleAppDir = tempDir.childDirectory('aaa').childDirectory('example');
pluginDir = tempDir.childDirectory('aaa');
exampleAppDir = pluginDir.childDirectory('example');
processManager.runSync(<String>[
flutterBin,
......@@ -40,12 +45,12 @@ void main() {
'build succeeds targeting string compileSdkVersion',
() async {
final File buildGradleFile = exampleAppDir.childDirectory('android').childDirectory('app').childFile('build.gradle');
// write a build.gradle with compileSdk version as `android-Tiramisu` which is a string preview version
// write a build.gradle with compileSdkVersion as `android-UpsideDownCake` which is a string preview version
buildGradleFile.writeAsStringSync(
buildGradleFile.readAsStringSync().replaceFirst('compileSdk flutter.compileSdkVersion', 'compileSdk "android-Tiramisu"'),
buildGradleFile.readAsStringSync().replaceFirst(compileSdkVersionMatch, 'compileSdkVersion "android-UpsideDownCake"'),
flush: true
);
expect(buildGradleFile.readAsStringSync(), contains('compileSdk "android-Tiramisu"'));
expect(buildGradleFile.readAsStringSync(), contains('compileSdkVersion "android-UpsideDownCake"'));
final ProcessResult result = await processManager.run(<String>[
flutterBin,
......@@ -54,13 +59,13 @@ void main() {
'apk',
'--debug',
], workingDirectory: exampleAppDir.path);
expect(result.stdout, contains('Built build/app/outputs/flutter-apk/app-debug.apk.'));
expect(exampleAppDir.childDirectory('build')
.childDirectory('app')
.childDirectory('outputs')
.childDirectory('apk')
.childDirectory('debug')
.childFile('app-debug.apk').existsSync(), true);
expect(result.stdout, contains('Built $builtApkPath'));
},
);
......@@ -68,12 +73,12 @@ void main() {
'build succeeds targeting string compileSdkPreview',
() async {
final File buildGradleFile = exampleAppDir.childDirectory('android').childDirectory('app').childFile('build.gradle');
// write a build.gradle with compileSdkPreview as `Tiramisu` which is a string preview version
// write a build.gradle with compileSdkPreview as `UpsideDownCake` which is a string preview version
buildGradleFile.writeAsStringSync(
buildGradleFile.readAsStringSync().replaceFirst('compileSdk flutter.compileSdkVersion', 'compileSdkPreview "Tiramisu"'),
buildGradleFile.readAsStringSync().replaceFirst(compileSdkVersionMatch, 'compileSdkPreview "UpsideDownCake"'),
flush: true
);
expect(buildGradleFile.readAsStringSync(), contains('compileSdkPreview "Tiramisu"'));
expect(buildGradleFile.readAsStringSync(), contains('compileSdkPreview "UpsideDownCake"'));
final ProcessResult result = await processManager.run(<String>[
flutterBin,
......@@ -82,13 +87,49 @@ void main() {
'apk',
'--debug',
], workingDirectory: exampleAppDir.path);
expect(result.stdout, contains('Built build/app/outputs/flutter-apk/app-debug.apk.'));
expect(exampleAppDir.childDirectory('build')
.childDirectory('app')
.childDirectory('outputs')
.childDirectory('apk')
.childDirectory('debug')
.childFile('app-debug.apk').existsSync(), true);
expect(result.stdout, contains('Built $builtApkPath'));
},
);
test(
'build succeeds when both example app and plugin target compileSdkPreview',
() async {
final File appBuildGradleFile = exampleAppDir.childDirectory('android').childDirectory('app').childFile('build.gradle');
// write a build.gradle with compileSdkPreview as `UpsideDownCake` which is a string preview version
appBuildGradleFile.writeAsStringSync(
appBuildGradleFile.readAsStringSync().replaceFirst(compileSdkVersionMatch, 'compileSdkPreview "UpsideDownCake"'),
flush: true
);
expect(appBuildGradleFile.readAsStringSync(), contains('compileSdkPreview "UpsideDownCake"'));
final File pluginBuildGradleFile = pluginDir.childDirectory('android').childFile('build.gradle');
// change the plugin build.gradle to use a preview compile sdk version
pluginBuildGradleFile.writeAsStringSync(
pluginBuildGradleFile.readAsStringSync().replaceFirst(compileSdkVersionMatch, 'compileSdkPreview "UpsideDownCake"'),
flush: true
);
expect(pluginBuildGradleFile.readAsStringSync(), contains('compileSdkPreview "UpsideDownCake"'));
final ProcessResult result = await processManager.run(<String>[
flutterBin,
...getLocalEngineArguments(),
'build',
'apk',
'--debug',
], workingDirectory: exampleAppDir.path);
expect(exampleAppDir.childDirectory('build')
.childDirectory('app')
.childDirectory('outputs')
.childDirectory('apk')
.childDirectory('debug')
.childFile('app-debug.apk').existsSync(), true);
expect(result.stdout, contains('Built $builtApkPath'));
},
);
}
......@@ -20,3 +20,7 @@ information for the `flutter` tool (since they are black-box tests that
run the tool as a subprocess, rather than being unit tests). For this
reason, they are in a separate shard when running on continuous
integration and are not run when calculating coverage.
## Adding new test files
When adding a new test file make sure that it ends with `_test.dart`, or else it will not be run.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment