[flutter_plugin_tools] Migrate more commands to NNBD (#4026)
Migrates:
- `all_plugins_app`
- `podspecs`
- `firebase-test-lab`
Minor functional changes to `firebase-test-lab` based on issues highlighted by the migration:
- The build ID used in the path is now a) passable, and b) given a fallback value in the path that
isn't "null"
- Flag setup will no longer assume that `$HOME` must be set in the environment.
- Adds a --build-id flag to `firebase-test-lab` instead of hard-coding the use of `CIRRUS_BUILD_ID`.
The default is still `CIRRUS_BUILD_ID` so no CI changes are needed.
Part of https://github.com/flutter/flutter/issues/81912
diff --git a/script/tool/CHANGELOG.md b/script/tool/CHANGELOG.md
index bd0875c..2ada2cc 100644
--- a/script/tool/CHANGELOG.md
+++ b/script/tool/CHANGELOG.md
@@ -1,3 +1,9 @@
+## NEXT
+
+- Add a --build-id flag to `firebase-test-lab` instead of hard-coding the use of
+ `CIRRUS_BUILD_ID`. `CIRRUS_BUILD_ID` is the default value for that flag, for backward
+ compatibility.
+
## 0.2.0
- Remove `xctest`'s `--skip`, which is redundant with `--ignore`.
diff --git a/script/tool/lib/src/create_all_plugins_app_command.dart b/script/tool/lib/src/create_all_plugins_app_command.dart
index 9de7f1b..cd5b85e 100644
--- a/script/tool/lib/src/create_all_plugins_app_command.dart
+++ b/script/tool/lib/src/create_all_plugins_app_command.dart
@@ -2,9 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// @dart=2.9
-
-import 'dart:async';
import 'dart:io' as io;
import 'package:file/file.dart';
@@ -18,17 +15,17 @@
/// Creates an instance of the builder command.
CreateAllPluginsAppCommand(
Directory packagesDir, {
- this.pluginsRoot,
- }) : super(packagesDir) {
- pluginsRoot ??= packagesDir.fileSystem.currentDirectory;
- appDirectory = pluginsRoot.childDirectory('all_plugins');
+ Directory? pluginsRoot,
+ }) : pluginsRoot = pluginsRoot ?? packagesDir.fileSystem.currentDirectory,
+ super(packagesDir) {
+ appDirectory = this.pluginsRoot.childDirectory('all_plugins');
}
/// The root directory of the plugin repository.
Directory pluginsRoot;
/// The location of the synthesized app project.
- Directory appDirectory;
+ late Directory appDirectory;
@override
String get description =>
@@ -177,7 +174,7 @@
version: ${pubspec.version}
-environment:${_pubspecMapString(pubspec.environment)}
+environment:${_pubspecMapString(pubspec.environment!)}
dependencies:${_pubspecMapString(pubspec.dependencies)}
diff --git a/script/tool/lib/src/firebase_test_lab_command.dart b/script/tool/lib/src/firebase_test_lab_command.dart
index 6db0d62..741d856 100644
--- a/script/tool/lib/src/firebase_test_lab_command.dart
+++ b/script/tool/lib/src/firebase_test_lab_command.dart
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// @dart=2.9
-
import 'dart:async';
import 'dart:io' as io;
@@ -27,15 +25,25 @@
defaultsTo: 'flutter-infra',
help: 'The Firebase project name.',
);
+ final String? homeDir = io.Platform.environment['HOME'];
argParser.addOption('service-key',
defaultsTo:
- p.join(io.Platform.environment['HOME'], 'gcloud-service-key.json'));
+ homeDir == null ? null : p.join(homeDir, 'gcloud-service-key.json'),
+ help: 'The path to the service key for gcloud authentication.\n'
+ r'If not provided, \$HOME/gcloud-service-key.json will be '
+ r'assumed if $HOME is set.');
argParser.addOption('test-run-id',
defaultsTo: const Uuid().v4(),
help:
'Optional string to append to the results path, to avoid conflicts. '
'Randomly chosen on each invocation if none is provided. '
'The default shown here is just an example.');
+ argParser.addOption('build-id',
+ defaultsTo:
+ io.Platform.environment['CIRRUS_BUILD_ID'] ?? 'unknown_build',
+ help:
+ 'Optional string to append to the results path, to avoid conflicts. '
+ r'Defaults to $CIRRUS_BUILD_ID if that is set.');
argParser.addMultiOption('device',
splitCommas: false,
defaultsTo: <String>[
@@ -66,38 +74,43 @@
final Print _print;
- Completer<void> _firebaseProjectConfigured;
+ Completer<void>? _firebaseProjectConfigured;
Future<void> _configureFirebaseProject() async {
if (_firebaseProjectConfigured != null) {
- return _firebaseProjectConfigured.future;
- } else {
- _firebaseProjectConfigured = Completer<void>();
+ return _firebaseProjectConfigured!.future;
}
- await processRunner.run(
- 'gcloud',
- <String>[
- 'auth',
- 'activate-service-account',
- '--key-file=${getStringArg('service-key')}',
- ],
- exitOnError: true,
- logOnError: true,
- );
- final int exitCode = await processRunner.runAndStream('gcloud', <String>[
- 'config',
- 'set',
- 'project',
- getStringArg('project'),
- ]);
- if (exitCode == 0) {
- _print('\nFirebase project configured.');
- return;
+ _firebaseProjectConfigured = Completer<void>();
+
+ final String serviceKey = getStringArg('service-key');
+ if (serviceKey.isEmpty) {
+ _print('No --service-key provided; skipping gcloud authorization');
} else {
- _print(
- '\nWarning: gcloud config set returned a non-zero exit code. Continuing anyway.');
+ await processRunner.run(
+ 'gcloud',
+ <String>[
+ 'auth',
+ 'activate-service-account',
+ '--key-file=$serviceKey',
+ ],
+ exitOnError: true,
+ logOnError: true,
+ );
+ final int exitCode = await processRunner.runAndStream('gcloud', <String>[
+ 'config',
+ 'set',
+ 'project',
+ getStringArg('project'),
+ ]);
+ if (exitCode == 0) {
+ _print('\nFirebase project configured.');
+ return;
+ } else {
+ _print(
+ '\nWarning: gcloud config set returned a non-zero exit code. Continuing anyway.');
+ }
}
- _firebaseProjectConfigured.complete(null);
+ _firebaseProjectConfigured!.complete(null);
}
@override
@@ -212,7 +225,7 @@
failingPackages.add(packageName);
continue;
}
- final String buildId = io.Platform.environment['CIRRUS_BUILD_ID'];
+ final String buildId = getStringArg('build-id');
final String testRunId = getStringArg('test-run-id');
final String resultsDir =
'plugins_android_test/$packageName/$buildId/$testRunId/${resultsCounter++}/';
diff --git a/script/tool/lib/src/lint_podspecs_command.dart b/script/tool/lib/src/lint_podspecs_command.dart
index 72bb6af..364653b 100644
--- a/script/tool/lib/src/lint_podspecs_command.dart
+++ b/script/tool/lib/src/lint_podspecs_command.dart
@@ -2,9 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// @dart=2.9
-
-import 'dart:async';
import 'dart:convert';
import 'dart:io';
@@ -122,7 +119,7 @@
}
Future<ProcessResult> _runPodLint(String podspecPath,
- {bool libraryLint}) async {
+ {required bool libraryLint}) async {
final bool allowWarnings = (getStringListArg('ignore-warnings'))
.contains(p.basenameWithoutExtension(podspecPath));
final List<String> arguments = <String>[
diff --git a/script/tool/test/create_all_plugins_app_command_test.dart b/script/tool/test/create_all_plugins_app_command_test.dart
index b3cbd59..5bde5e0 100644
--- a/script/tool/test/create_all_plugins_app_command_test.dart
+++ b/script/tool/test/create_all_plugins_app_command_test.dart
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// @dart=2.9
-
import 'package:args/command_runner.dart';
import 'package:file/file.dart';
import 'package:file/local.dart';
@@ -14,11 +12,11 @@
void main() {
group('$CreateAllPluginsAppCommand', () {
- CommandRunner<void> runner;
+ late CommandRunner<void> runner;
FileSystem fileSystem;
- Directory testRoot;
- Directory packagesDir;
- Directory appDir;
+ late Directory testRoot;
+ late Directory packagesDir;
+ late Directory appDir;
setUp(() {
// Since the core of this command is a call to 'flutter create', the test
diff --git a/script/tool/test/firebase_test_lab_test.dart b/script/tool/test/firebase_test_lab_test.dart
index 7480900..aa8be17 100644
--- a/script/tool/test/firebase_test_lab_test.dart
+++ b/script/tool/test/firebase_test_lab_test.dart
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// @dart=2.9
-
import 'dart:io';
import 'package:args/command_runner.dart';
@@ -19,10 +17,10 @@
void main() {
group('$FirebaseTestLabCommand', () {
FileSystem fileSystem;
- Directory packagesDir;
- List<String> printedMessages;
- CommandRunner<void> runner;
- RecordingProcessRunner processRunner;
+ late Directory packagesDir;
+ late List<String> printedMessages;
+ late CommandRunner<void> runner;
+ late RecordingProcessRunner processRunner;
setUp(() {
fileSystem = MemoryFileSystem();
@@ -31,7 +29,7 @@
processRunner = RecordingProcessRunner();
final FirebaseTestLabCommand command = FirebaseTestLabCommand(packagesDir,
processRunner: processRunner,
- print: (Object message) => printedMessages.add(message.toString()));
+ print: (Object? message) => printedMessages.add(message.toString()));
runner = CommandRunner<void>(
'firebase_test_lab_command', 'Test for $FirebaseTestLabCommand');
@@ -97,6 +95,8 @@
'model=seoul,version=26',
'--test-run-id',
'testRunId',
+ '--build-id',
+ 'buildId',
]);
expect(
@@ -130,7 +130,7 @@
'/packages/plugin/example/android'),
ProcessCall(
'gcloud',
- 'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 5m --results-bucket=gs://flutter_firebase_testlab --results-dir=plugins_android_test/plugin/null/testRunId/0/ --device model=flame,version=29 --device model=seoul,version=26'
+ 'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 5m --results-bucket=gs://flutter_firebase_testlab --results-dir=plugins_android_test/plugin/buildId/testRunId/0/ --device model=flame,version=29 --device model=seoul,version=26'
.split(' '),
'/packages/plugin/example'),
ProcessCall(
@@ -140,7 +140,7 @@
'/packages/plugin/example/android'),
ProcessCall(
'gcloud',
- 'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 5m --results-bucket=gs://flutter_firebase_testlab --results-dir=plugins_android_test/plugin/null/testRunId/1/ --device model=flame,version=29 --device model=seoul,version=26'
+ 'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 5m --results-bucket=gs://flutter_firebase_testlab --results-dir=plugins_android_test/plugin/buildId/testRunId/1/ --device model=flame,version=29 --device model=seoul,version=26'
.split(' '),
'/packages/plugin/example'),
ProcessCall(
@@ -150,7 +150,7 @@
'/packages/plugin/example/android'),
ProcessCall(
'gcloud',
- 'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 5m --results-bucket=gs://flutter_firebase_testlab --results-dir=plugins_android_test/plugin/null/testRunId/2/ --device model=flame,version=29 --device model=seoul,version=26'
+ 'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 5m --results-bucket=gs://flutter_firebase_testlab --results-dir=plugins_android_test/plugin/buildId/testRunId/2/ --device model=flame,version=29 --device model=seoul,version=26'
.split(' '),
'/packages/plugin/example'),
ProcessCall(
@@ -160,7 +160,7 @@
'/packages/plugin/example/android'),
ProcessCall(
'gcloud',
- 'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 5m --results-bucket=gs://flutter_firebase_testlab --results-dir=plugins_android_test/plugin/null/testRunId/3/ --device model=flame,version=29 --device model=seoul,version=26'
+ 'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 5m --results-bucket=gs://flutter_firebase_testlab --results-dir=plugins_android_test/plugin/buildId/testRunId/3/ --device model=flame,version=29 --device model=seoul,version=26'
.split(' '),
'/packages/plugin/example'),
]),
@@ -196,6 +196,8 @@
'model=flame,version=29',
'--test-run-id',
'testRunId',
+ '--build-id',
+ 'buildId',
'--enable-experiment=exp1',
]);
@@ -221,7 +223,7 @@
'/packages/plugin/example/android'),
ProcessCall(
'gcloud',
- 'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 5m --results-bucket=gs://flutter_firebase_testlab --results-dir=plugins_android_test/plugin/null/testRunId/0/ --device model=flame,version=29'
+ 'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 5m --results-bucket=gs://flutter_firebase_testlab --results-dir=plugins_android_test/plugin/buildId/testRunId/0/ --device model=flame,version=29'
.split(' '),
'/packages/plugin/example'),
ProcessCall(
@@ -231,7 +233,7 @@
'/packages/plugin/example/android'),
ProcessCall(
'gcloud',
- 'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 5m --results-bucket=gs://flutter_firebase_testlab --results-dir=plugins_android_test/plugin/null/testRunId/1/ --device model=flame,version=29'
+ 'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 5m --results-bucket=gs://flutter_firebase_testlab --results-dir=plugins_android_test/plugin/buildId/testRunId/1/ --device model=flame,version=29'
.split(' '),
'/packages/plugin/example'),
ProcessCall(
@@ -241,7 +243,7 @@
'/packages/plugin/example/android'),
ProcessCall(
'gcloud',
- 'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 5m --results-bucket=gs://flutter_firebase_testlab --results-dir=plugins_android_test/plugin/null/testRunId/2/ --device model=flame,version=29'
+ 'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 5m --results-bucket=gs://flutter_firebase_testlab --results-dir=plugins_android_test/plugin/buildId/testRunId/2/ --device model=flame,version=29'
.split(' '),
'/packages/plugin/example'),
ProcessCall(
@@ -251,7 +253,7 @@
'/packages/plugin/example/android'),
ProcessCall(
'gcloud',
- 'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 5m --results-bucket=gs://flutter_firebase_testlab --results-dir=plugins_android_test/plugin/null/testRunId/3/ --device model=flame,version=29'
+ 'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 5m --results-bucket=gs://flutter_firebase_testlab --results-dir=plugins_android_test/plugin/buildId/testRunId/3/ --device model=flame,version=29'
.split(' '),
'/packages/plugin/example'),
]),
diff --git a/script/tool/test/lint_podspecs_command_test.dart b/script/tool/test/lint_podspecs_command_test.dart
index 349607b..0183704 100644
--- a/script/tool/test/lint_podspecs_command_test.dart
+++ b/script/tool/test/lint_podspecs_command_test.dart
@@ -2,15 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// @dart=2.9
-
import 'package:args/command_runner.dart';
import 'package:file/file.dart';
import 'package:file/memory.dart';
import 'package:flutter_plugin_tools/src/lint_podspecs_command.dart';
-import 'package:mockito/mockito.dart';
import 'package:path/path.dart' as p;
-import 'package:platform/platform.dart';
import 'package:test/test.dart';
import 'mocks.dart';
@@ -19,24 +15,24 @@
void main() {
group('$LintPodspecsCommand', () {
FileSystem fileSystem;
- Directory packagesDir;
- CommandRunner<void> runner;
- MockPlatform mockPlatform;
- final RecordingProcessRunner processRunner = RecordingProcessRunner();
- List<String> printedMessages;
+ late Directory packagesDir;
+ late CommandRunner<void> runner;
+ late MockPlatform mockPlatform;
+ late RecordingProcessRunner processRunner;
+ late List<String> printedMessages;
setUp(() {
fileSystem = MemoryFileSystem();
packagesDir = createPackagesDirectory(fileSystem: fileSystem);
printedMessages = <String>[];
- mockPlatform = MockPlatform();
- when(mockPlatform.isMacOS).thenReturn(true);
+ mockPlatform = MockPlatform(isMacOS: true);
+ processRunner = RecordingProcessRunner();
final LintPodspecsCommand command = LintPodspecsCommand(
packagesDir,
processRunner: processRunner,
platform: mockPlatform,
- print: (Object message) => printedMessages.add(message.toString()),
+ print: (Object? message) => printedMessages.add(message.toString()),
);
runner =
@@ -53,7 +49,7 @@
<String>['plugin1.podspec'],
]);
- when(mockPlatform.isMacOS).thenReturn(false);
+ mockPlatform.isMacOS = false;
await runner.run(<String>['podspecs']);
expect(
@@ -172,5 +168,3 @@
});
});
}
-
-class MockPlatform extends Mock implements Platform {}
diff --git a/script/tool/test/mocks.dart b/script/tool/test/mocks.dart
index 66267ec..ba6a03d 100644
--- a/script/tool/test/mocks.dart
+++ b/script/tool/test/mocks.dart
@@ -7,6 +7,14 @@
import 'package:file/file.dart';
import 'package:mockito/mockito.dart';
+import 'package:platform/platform.dart';
+
+class MockPlatform extends Mock implements Platform {
+ MockPlatform({this.isMacOS = false});
+
+ @override
+ bool isMacOS;
+}
class MockProcess extends Mock implements io.Process {
final Completer<int> exitCodeCompleter = Completer<int>();
diff --git a/script/tool/test/util.dart b/script/tool/test/util.dart
index a0a316f..c9d4ed2 100644
--- a/script/tool/test/util.dart
+++ b/script/tool/test/util.dart
@@ -257,13 +257,13 @@
Encoding stderrEncoding = io.systemEncoding,
}) async {
recordedCalls.add(ProcessCall(executable, args, workingDir?.path));
- io.ProcessResult? result;
final io.Process? process = processToReturn;
- if (process != null) {
- result = io.ProcessResult(process.pid, await process.exitCode,
- resultStdout ?? process.stdout, resultStderr ?? process.stderr);
- }
+ final io.ProcessResult result = process == null
+ ? io.ProcessResult(1, 1, '', '')
+ : io.ProcessResult(process.pid, await process.exitCode,
+ resultStdout ?? process.stdout, resultStderr ?? process.stderr);
+
return Future<io.ProcessResult>.value(result);
}