[appengine] Migrate to null safety
Change-Id: Id7e51123e0a53c10698f850fe090653f89f96321
Reviewed-on: https://dart-review.googlesource.com/c/dart_ci/+/244662
Commit-Queue: William Hesse <whesse@google.com>
Auto-Submit: Alexander Thomas <athom@google.com>
Reviewed-by: William Hesse <whesse@google.com>
diff --git a/appengine/CHANGELOG.md b/appengine/CHANGELOG.md
index 794867f..bab2790 100644
--- a/appengine/CHANGELOG.md
+++ b/appengine/CHANGELOG.md
@@ -1,3 +1,9 @@
+## 0.3.0
+
+* Upgraded to Dart 2.17.0.
+* Migrated to null safety.
+* Added package:lints.
+
## 0.2.0
* Package name changed to dart_ci, moved to dart_lang/dart_ci repo on Github.
diff --git a/appengine/analysis_options.yaml b/appengine/analysis_options.yaml
new file mode 100644
index 0000000..ea2c9e9
--- /dev/null
+++ b/appengine/analysis_options.yaml
@@ -0,0 +1 @@
+include: package:lints/recommended.yaml
\ No newline at end of file
diff --git a/appengine/bin/log.dart b/appengine/bin/log.dart
index 0c58f1f..2068dc6 100755
--- a/appengine/bin/log.dart
+++ b/appengine/bin/log.dart
@@ -9,15 +9,18 @@
import 'package:dart_ci/src/get_log.dart';
-void main(List<String> args) {
- final parser = new ArgParser();
- parser.addOption("builder", abbr: "b", help: "Fetch log from this builder");
+void main(List<String> args) async {
+ final parser = ArgParser();
+ parser.addOption("builder",
+ abbr: "b", defaultsTo: "any", help: "Fetch log from this builder");
parser.addOption("build-number",
abbr: "n",
defaultsTo: "latest",
help: "Fetch log from this build on the chosen builder");
parser.addOption("test",
- abbr: "t", help: "Fetch log for this test on the chosen builder");
+ abbr: "t",
+ defaultsTo: "*",
+ help: "Fetch log for this test on the chosen builder");
parser.addOption("configuration",
abbr: "c",
defaultsTo: "*",
@@ -25,10 +28,17 @@
parser.addFlag("help", help: "Show the program usage.", negatable: false);
final options = parser.parse(args);
- final builder = options["builder"];
- final test = options["test"];
- final build = options["build-number"];
- final configuration = options["configuration"];
+ final builder = options["builder"] as String;
+ var build = options["build-number"] as String;
+ final configuration = options["configuration"] as String;
+ final test = options["test"] as String;
- getLog(builder, build, configuration, test).then((log) => print(log));
+ if (build == "latest") {
+ if (builder != "any") {
+ build = await getLatestBuildNumber(builder);
+ } else if (configuration != "*") {
+ build = await getLatestConfigurationBuildNumber(configuration);
+ }
+ }
+ print(await getLog(builder, build, configuration, test));
}
diff --git a/appengine/bin/server.dart b/appengine/bin/server.dart
index 3e82ff7..20328e4 100644
--- a/appengine/bin/server.dart
+++ b/appengine/bin/server.dart
@@ -44,7 +44,7 @@
}
}
-void serveFrontPage(HttpRequest request) async {
+Future<void> serveFrontPage(HttpRequest request) async {
request.response.headers.contentType = ContentType.html;
request.response.write("""<!DOCTYPE html>
<html lang="en">
@@ -117,7 +117,7 @@
Future<void> redirectToTest(HttpRequest request) async {
final parts = request.uri.pathSegments.skip(1).toList();
final isCl = parts.first == 'cl';
- var revision;
+ late String revision;
if (isCl) {
final review = int.parse(parts[1]);
final patchset = int.parse(parts[2]);
@@ -153,7 +153,7 @@
return request.response.close();
}
-Future<void> notFound(HttpRequest request, {String message}) {
+Future<void> notFound(HttpRequest request, {String? message}) {
request.response.statusCode = HttpStatus.notFound;
if (message != null) {
request.response.write(message);
diff --git a/appengine/lib/src/get_log.dart b/appengine/lib/src/get_log.dart
index cf354ae..40ad19f 100644
--- a/appengine/lib/src/get_log.dart
+++ b/appengine/lib/src/get_log.dart
@@ -18,6 +18,7 @@
UserVisibleFailure(this.message);
+ @override
String toString() => "error: $message";
}
@@ -26,7 +27,7 @@
try {
final api = storage.StorageApi(client);
final media = await api.objects
- .get(bucket, path, downloadOptions: DownloadOptions.FullMedia) as Media;
+ .get(bucket, path, downloadOptions: DownloadOptions.fullMedia) as Media;
return await utf8.decodeStream(media.stream);
} catch (e) {
throw UserVisibleFailure(
@@ -43,7 +44,7 @@
getCloudFile(resultsBucket, 'configuration/main/$configuration/latest');
/// Fetches a log or logs and formats them for output.
-Future<String> getLog(
+Future<String?> getLog(
String builder, String build, String configuration, String test) async {
final safeRegExp = RegExp('^[-\\w]*\$');
final digitsRegExp = RegExp('^\\d*\$');
@@ -72,13 +73,15 @@
final logs = LineSplitter.split(jsonLogs)
.where((line) => line.isNotEmpty)
- .map(jsonDecode);
- var testFilter = (Map<String, dynamic> log) => log['name'] == test;
+ .map(jsonDecode)
+ .cast<Map<String, dynamic>>();
+ bool Function(Map<String, dynamic>) testFilter =
+ (Map<String, dynamic> log) => log['name'] == test;
if (test.endsWith('*')) {
final prefix = test.substring(0, test.length - 1);
testFilter = (Map<String, dynamic> log) => log['name'].startsWith(prefix);
}
- var configurationFilter =
+ bool Function(Map<String, dynamic>) configurationFilter =
(Map<String, dynamic> log) => log['configuration'] == configuration;
if (configuration.endsWith('*')) {
final prefix = configuration.substring(0, configuration.length - 1);
diff --git a/appengine/lib/src/test_source.dart b/appengine/lib/src/test_source.dart
index 54d6296..008f531 100644
--- a/appengine/lib/src/test_source.dart
+++ b/appengine/lib/src/test_source.dart
@@ -45,7 +45,7 @@
"fasta/textual_outline",
];
-String findBaseName(String suite, Iterable<String> nameParts) {
+String? findBaseName(String suite, Iterable<String> nameParts) {
var parts = nameParts.toList();
final regExp = (suite == 'co19' || suite == 'co19_2')
? RegExp(r"t[0-9]{2,3}$")
@@ -60,11 +60,11 @@
return null;
}
-Future<Uri> guessFileName(
+Future<Uri?> guessFileName(
String suite, Uri testDirectory, Iterable<String> parts) async {
final baseName = findBaseName(suite, parts);
if (baseName != null) {
- return testDirectory.resolve(baseName + ".dart");
+ return testDirectory.resolve('$baseName.dart');
} else {
return null;
}
@@ -79,17 +79,17 @@
return false;
}
-Future<Uri> findTestFile(
+Future<Uri?> findTestFile(
String testName, Uri root, String suite, Iterable<String> testParts) async {
if (isCo19(suite)) {
return await guessFileName(suite, root, testParts);
} else if (isExternalPackage(suite)) {
- return root.resolve(testParts.join('/') + ".dart");
+ return root.resolve('${testParts.join('/')}.dart');
} else if (testDirectories.containsKey(suite)) {
- var testDir = root.resolveUri(Uri.directory(testDirectories[suite]));
+ var testDir = root.resolveUri(Uri.directory(testDirectories[suite]!));
return await guessFileName(suite, testDir, testParts);
} else if (customTestRunnerSuites.containsKey(suite)) {
- return root.resolve(customTestRunnerSuites[suite]);
+ return root.resolve(customTestRunnerSuites[suite]!);
} else if (suite == 'pkg') {
if (testParts.first == 'front_end' &&
isFrontEndUnitTestSuiteTest(testName)) {
@@ -127,7 +127,8 @@
}
Future<String> findDepsRevision(String revision, String package) async {
- final url = "https://dart.googlesource.com/sdk/+/$revision/DEPS?format=TEXT";
+ final url = Uri.parse(
+ 'https://dart.googlesource.com/sdk/+/$revision/DEPS?format=TEXT');
final response = await http.get(url);
if (response.statusCode != HttpStatus.ok) {
throw Exception("Unable to download DEPS for revision '$revision'"
@@ -135,14 +136,17 @@
}
final body = String.fromCharCodes(base64Decode(response.body));
final match = RegExp('"${package}_rev": "(.*)",').firstMatch(body);
- return match?.group(1);
+ if (match == null) {
+ throw Exception("Unable to find $package revision '$revision' at $url");
+ }
+ return match.group(1)!;
}
const gerritDataHeader = ")]}'";
Future<String> getPatchsetRevision(int review, int patchset) async {
- final url = 'https://dart-review.googlesource.com/'
- 'changes/$review/revisions/$patchset/commit';
+ final url = Uri.parse('https://dart-review.googlesource.com/'
+ 'changes/$review/revisions/$patchset/commit');
final response = await http.get(url);
if (response.statusCode != HttpStatus.ok) {
throw Exception("Can't find revision for cl/$review/$patchset");
@@ -155,12 +159,12 @@
return data['commit'];
}
-Future<Uri> computeTestSource(
+Future<Uri?> computeTestSource(
String revision, String testName, bool useGob) async {
final splitName = testName.split('/');
var parts = splitName.skip(1);
final suite = splitName.first;
- var root;
+ String root;
if (isCo19(suite)) {
revision = await findDepsRevision(revision, suite);
root = "https://github.com/dart-lang/co19/blob/$revision/";
diff --git a/appengine/pubspec.lock b/appengine/pubspec.lock
index f2d0c49..ef5a70a 100644
--- a/appengine/pubspec.lock
+++ b/appengine/pubspec.lock
@@ -7,118 +7,118 @@
name: _discoveryapis_commons
url: "https://pub.dartlang.org"
source: hosted
- version: "0.1.9"
+ version: "1.0.2"
args:
dependency: "direct main"
description:
name: args
url: "https://pub.dartlang.org"
source: hosted
- version: "1.6.0"
+ version: "2.3.1"
async:
dependency: transitive
description:
name: async
url: "https://pub.dartlang.org"
source: hosted
- version: "2.4.1"
+ version: "2.9.0"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.3"
+ version: "1.3.1"
collection:
dependency: transitive
description:
name: collection
url: "https://pub.dartlang.org"
source: hosted
- version: "1.14.12"
- convert:
- dependency: transitive
- description:
- name: convert
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.1.1"
+ version: "1.16.0"
crypto:
dependency: transitive
description:
name: crypto
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.4"
+ version: "3.0.2"
googleapis:
dependency: "direct main"
description:
name: googleapis
url: "https://pub.dartlang.org"
source: hosted
- version: "0.51.1"
+ version: "8.1.0"
googleapis_auth:
dependency: "direct main"
description:
name: googleapis_auth
url: "https://pub.dartlang.org"
source: hosted
- version: "0.2.11+1"
+ version: "1.3.1"
http:
dependency: "direct main"
description:
name: http
url: "https://pub.dartlang.org"
source: hosted
- version: "0.11.3+17"
+ version: "0.13.4"
http_parser:
dependency: transitive
description:
name: http_parser
url: "https://pub.dartlang.org"
source: hosted
- version: "3.1.4"
+ version: "4.0.0"
+ lints:
+ dependency: "direct dev"
+ description:
+ name: lints
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.0.0"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.8"
+ version: "1.7.0"
path:
dependency: transitive
description:
name: path
url: "https://pub.dartlang.org"
source: hosted
- version: "1.7.0"
+ version: "1.8.1"
source_span:
dependency: transitive
description:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
- version: "1.7.0"
+ version: "1.9.0"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
- version: "1.0.5"
+ version: "1.1.0"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.0"
+ version: "1.2.0"
typed_data:
dependency: transitive
description:
name: typed_data
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.6"
+ version: "1.3.0"
sdks:
- dart: ">=2.6.0 <3.0.0"
+ dart: ">=2.17.0 <3.0.0"
diff --git a/appengine/pubspec.yaml b/appengine/pubspec.yaml
index 9f35244..cc6d121 100644
--- a/appengine/pubspec.yaml
+++ b/appengine/pubspec.yaml
@@ -1,13 +1,16 @@
name: dart_ci
-version: 0.2.0
+version: 0.3.0
publish_to: none
environment:
- sdk: '>=2.0.0 <3.0.0'
+ sdk: '>=2.17.0 <3.0.0'
dependencies:
- _discoveryapis_commons: ^0.1.3+1
- args: ^1.5.0
- googleapis: ^0.51.0
- googleapis_auth: ^0.2.7
- http: ^0.11.1+1
+ _discoveryapis_commons: ^1.0.2
+ args: ^2.3.1
+ googleapis: ^8.1.0
+ googleapis_auth: ^1.3.1
+ http: ^0.13.4
+
+dev_dependencies:
+ lints: ^2.0.0
diff --git a/appengine/test/create_source_tests.dart b/appengine/test/create_source_tests.dart
index de27723..579555c 100644
--- a/appengine/test/create_source_tests.dart
+++ b/appengine/test/create_source_tests.dart
@@ -44,13 +44,13 @@
testNames.putIfAbsent(key, () => testName);
}
- Map<String, Map<String, String>> results = {
+ Map<String, Map<String, String?>> results = {
'suite/not_a_basename': {"true": null, "false": null},
};
for (var name in testNames.values) {
results[name] = {};
for (var gob in [true, false]) {
- results[name][gob.toString()] =
+ results[name]![gob.toString()] =
(await computeTestSource(revision, name, gob)).toString();
}
}
diff --git a/appengine/test/test_source_test.dart b/appengine/test/test_source_test.dart
index baa7bcc..3f13c3d 100644
--- a/appengine/test/test_source_test.dart
+++ b/appengine/test/test_source_test.dart
@@ -21,12 +21,12 @@
main() async {
for (final name in testData.keys) {
for (final useGob in [true, false]) {
- final expected = testData[name][useGob.toString()];
- if (!testData[name].keys.toSet().containsAll(["true", "false"])) {
+ final expected = testData[name]![useGob.toString()];
+ if (!testData[name]!.keys.toSet().containsAll(["true", "false"])) {
throw 'Invalid test data for $name/$useGob';
}
- var actual;
- var url;
+ String? actual;
+ Uri? url;
try {
url = await computeTestSource(revision, name, useGob);
actual = url?.toString();