|  | #!/usr/bin/env dart | 
|  | // Copyright (c) 2023, the Dart project authors.  Please see the AUTHORS file | 
|  | // for details. All rights reserved. Use of this source code is governed by a | 
|  | // BSD-style license that can be found in the LICENSE file. | 
|  |  | 
|  | // A script to find all try jobs for a set of tests. | 
|  | // | 
|  | // Usage: | 
|  | // | 
|  | // ``` | 
|  | // $ tools/find_builders.dart ffi/regress_51504_test ffi/regress_52298_test | 
|  | // Cq-Include-Trybots: dart/try:vm-kernel-linux-debug-x64,... | 
|  | // ``` | 
|  |  | 
|  | import 'dart:convert'; | 
|  | import 'dart:io'; | 
|  |  | 
|  | // TODO(dacoharkes): Be able to use test full paths instead of test names. | 
|  | // TODO(dacoharkes): Be able to use different filters. | 
|  | Future<void> main(List<String> args) async { | 
|  | if (args.contains('--help')) { | 
|  | return printHelp(); | 
|  | } | 
|  | final testNames = args; | 
|  |  | 
|  | final configurations = _filterConfigurations({ | 
|  | for (final testName in testNames) ...await _testGetConfigurations(testName), | 
|  | }); | 
|  | final configurationBuilders = await _configurationBuilders(); | 
|  | final builders = | 
|  | _filterBuilders({ | 
|  | for (final config in configurations) configurationBuilders[config]!, | 
|  | }).toList() | 
|  | ..sort(); | 
|  |  | 
|  | final gerritTryList = builders.map((b) => '$b-try').join(','); | 
|  | print('Cq-Include-Trybots: dart/try:$gerritTryList'); | 
|  | } | 
|  |  | 
|  | Future<List<String>> _testGetConfigurations(String testName) async { | 
|  | final requestUrl = Uri( | 
|  | scheme: 'https', | 
|  | host: 'current-results-qvyo5rktwa-uc.a.run.app', | 
|  | path: 'v1/results', | 
|  | queryParameters: {'filter': testName}, | 
|  | ); | 
|  | final response = await _get(requestUrl); | 
|  | final object = jsonDecode(response) as Map<String, dynamic>; | 
|  | return [ | 
|  | for (final result in ((object['results'] as List)).cast<Map>()) | 
|  | result['configuration'], | 
|  | ]; | 
|  | } | 
|  |  | 
|  | Future<String> _get(Uri requestUrl) async { | 
|  | final client = HttpClient(); | 
|  | final request = await client.getUrl(requestUrl); | 
|  | final response = await request.close(); | 
|  | final responseString = await response.transform(const Utf8Decoder()).join(); | 
|  | client.close(); | 
|  | return responseString; | 
|  | } | 
|  |  | 
|  | Iterable<String> _filterConfigurations(Set<String> configs) { | 
|  | final result = <String>[]; | 
|  | for (final config in configs) { | 
|  | if (config.contains('debug')) { | 
|  | result.add(config); | 
|  | } else if (config.contains('release') && | 
|  | !configs.contains(config.replaceFirst('release', 'debug'))) { | 
|  | result.add(config); | 
|  | } else if (config.contains('profile') && | 
|  | !configs.contains(config.replaceFirst('profile', 'debug')) && | 
|  | !configs.contains(config.replaceFirst('profile', 'release'))) { | 
|  | result.add(config); | 
|  | } | 
|  | } | 
|  | return result..sort(); | 
|  | } | 
|  |  | 
|  | Iterable<String> _filterBuilders(Iterable<String> builders) { | 
|  | return builders.where( | 
|  | (b) => !_ciOnlyBuilders.contains(b) && !_denyListedBuilders.contains(b), | 
|  | ); | 
|  | } | 
|  |  | 
|  | const _ciOnlyBuilders = { | 
|  | 'vm-aot-linux-release-arm64', | 
|  | 'vm-linux-release-arm64', | 
|  | }; | 
|  |  | 
|  | const _denyListedBuilders = <String>{}; | 
|  |  | 
|  | Stream<Map<String, dynamic>> _configurationDocuments() async* { | 
|  | String? nextPageToken; | 
|  | do { | 
|  | final requestUrl = Uri( | 
|  | scheme: 'https', | 
|  | host: 'firestore.googleapis.com', | 
|  | path: 'v1/projects/dart-ci/databases/(default)/documents/configurations', | 
|  | queryParameters: { | 
|  | 'pageSize': '300', | 
|  | if (nextPageToken != null) 'pageToken': nextPageToken, | 
|  | }, | 
|  | ); | 
|  | final response = await _get(requestUrl); | 
|  | final object = jsonDecode(response) as Map<String, dynamic>; | 
|  | yield* Stream.fromIterable( | 
|  | (object['documents'] as List).cast<Map<String, dynamic>>(), | 
|  | ); | 
|  |  | 
|  | nextPageToken = object['nextPageToken']; | 
|  | } while (nextPageToken != null); | 
|  | } | 
|  |  | 
|  | Future<Map<String, String>> _configurationBuilders() async { | 
|  | return { | 
|  | await for (final document in _configurationDocuments()) | 
|  | if (document case { | 
|  | 'name': String fullName, | 
|  | 'fields': {'builder': {'stringValue': String builder}}, | 
|  | }) | 
|  | fullName.split('/').last: builder, | 
|  | }; | 
|  | } | 
|  |  | 
|  | void printHelp() { | 
|  | print(r''' | 
|  | A script to find all try jobs for a set of tests. | 
|  |  | 
|  | Usage: tools/find_builders.dart [selector] [selector2] [...] | 
|  |  | 
|  | Sample output: Cq-Include-Trybots: dart/try:vm-kernel-linux-debug-x64,... | 
|  | '''); | 
|  | } |