mirror of
https://github.com/flutter/flutter
synced 2024-10-01 05:54:08 +00:00
Allow plugins to use compileSdkPreview (#131901)
Fixes https://github.com/flutter/flutter/issues/124748 Based (heavily) off https://github.com/flutter/flutter/pull/104662
This commit is contained in:
parent
eb0890c9da
commit
9a72e1c699
30
.ci.yaml
30
.ci.yaml
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
# 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.
|
|
@ -0,0 +1,135 @@
|
|||
// 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 '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';
|
||||
|
||||
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.');
|
||||
flutterBin = fileSystem.path.join(
|
||||
getFlutterRoot(),
|
||||
'bin',
|
||||
'flutter',
|
||||
);
|
||||
pluginDir = tempDir.childDirectory('aaa');
|
||||
exampleAppDir = pluginDir.childDirectory('example');
|
||||
|
||||
processManager.runSync(<String>[
|
||||
flutterBin,
|
||||
...getLocalEngineArguments(),
|
||||
'create',
|
||||
'--template=plugin',
|
||||
'--platforms=android',
|
||||
'aaa',
|
||||
], workingDirectory: tempDir.path);
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
tryToDelete(tempDir);
|
||||
});
|
||||
|
||||
test(
|
||||
'build succeeds targeting string compileSdkVersion',
|
||||
() async {
|
||||
final File buildGradleFile = exampleAppDir.childDirectory('android').childDirectory('app').childFile('build.gradle');
|
||||
// write a build.gradle with compileSdkVersion as `android-UpsideDownCake` which is a string preview version
|
||||
buildGradleFile.writeAsStringSync(
|
||||
buildGradleFile.readAsStringSync().replaceFirst(compileSdkVersionMatch, 'compileSdkVersion "android-UpsideDownCake"'),
|
||||
flush: true
|
||||
);
|
||||
expect(buildGradleFile.readAsStringSync(), contains('compileSdkVersion "android-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'));
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'build succeeds targeting string compileSdkPreview',
|
||||
() async {
|
||||
final File buildGradleFile = exampleAppDir.childDirectory('android').childDirectory('app').childFile('build.gradle');
|
||||
// write a build.gradle with compileSdkPreview as `UpsideDownCake` which is a string preview version
|
||||
buildGradleFile.writeAsStringSync(
|
||||
buildGradleFile.readAsStringSync().replaceFirst(compileSdkVersionMatch, 'compileSdkPreview "UpsideDownCake"'),
|
||||
flush: true
|
||||
);
|
||||
expect(buildGradleFile.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'));
|
||||
},
|
||||
);
|
||||
|
||||
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.
|
||||
|
|
|
@ -1,94 +0,0 @@
|
|||
// 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 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:flutter_tools/src/base/io.dart';
|
||||
|
||||
import '../src/common.dart';
|
||||
import 'test_utils.dart';
|
||||
|
||||
void main() {
|
||||
late Directory tempDir;
|
||||
late String flutterBin;
|
||||
late Directory exampleAppDir;
|
||||
|
||||
setUp(() async {
|
||||
tempDir = createResolvedTempDirectorySync('flutter_plugin_test.');
|
||||
flutterBin = fileSystem.path.join(
|
||||
getFlutterRoot(),
|
||||
'bin',
|
||||
'flutter',
|
||||
);
|
||||
exampleAppDir = tempDir.childDirectory('aaa').childDirectory('example');
|
||||
|
||||
processManager.runSync(<String>[
|
||||
flutterBin,
|
||||
...getLocalEngineArguments(),
|
||||
'create',
|
||||
'--template=plugin',
|
||||
'--platforms=android',
|
||||
'aaa',
|
||||
], workingDirectory: tempDir.path);
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
tryToDelete(tempDir);
|
||||
});
|
||||
|
||||
test(
|
||||
'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
|
||||
buildGradleFile.writeAsStringSync(
|
||||
buildGradleFile.readAsStringSync().replaceFirst('compileSdk flutter.compileSdkVersion', 'compileSdk "android-Tiramisu"'),
|
||||
flush: true
|
||||
);
|
||||
expect(buildGradleFile.readAsStringSync(), contains('compileSdk "android-Tiramisu"'));
|
||||
|
||||
final ProcessResult result = await processManager.run(<String>[
|
||||
flutterBin,
|
||||
...getLocalEngineArguments(),
|
||||
'build',
|
||||
'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);
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'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
|
||||
buildGradleFile.writeAsStringSync(
|
||||
buildGradleFile.readAsStringSync().replaceFirst('compileSdk flutter.compileSdkVersion', 'compileSdkPreview "Tiramisu"'),
|
||||
flush: true
|
||||
);
|
||||
expect(buildGradleFile.readAsStringSync(), contains('compileSdkPreview "Tiramisu"'));
|
||||
|
||||
final ProcessResult result = await processManager.run(<String>[
|
||||
flutterBin,
|
||||
...getLocalEngineArguments(),
|
||||
'build',
|
||||
'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);
|
||||
},
|
||||
);
|
||||
}
|
Loading…
Reference in a new issue