Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/builder.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
fail-fast: false
matrix:
sdk:
- 3.1.0
- 3.10.1
os:
- ubuntu-latest
steps:
Expand Down
70 changes: 45 additions & 25 deletions builder/bin/find_base_commit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,24 @@ import 'package:glob/glob.dart';

void main(List<String> args) async {
final parser = ArgParser();
parser.addMultiOption('builder',
abbr: 'b',
help: 'Select the builders matching the glob [option is repeatable]',
splitCommas: false);
parser.addOption('branch',
abbr: 'B',
help: 'Select the builders building this branch',
defaultsTo: 'main');
parser.addOption('count',
abbr: 'c', help: 'List this many commits', defaultsTo: '1');
parser.addMultiOption(
'builder',
abbr: 'b',
help: 'Select the builders matching the glob [option is repeatable]',
splitCommas: false,
);
parser.addOption(
'branch',
abbr: 'B',
help: 'Select the builders building this branch',
defaultsTo: 'main',
);
parser.addOption(
'count',
abbr: 'c',
help: 'List this many commits',
defaultsTo: '1',
);
parser.addFlag('help', help: 'Show the program usage.', negatable: false);

final options = parser.parse(args);
Expand All @@ -41,21 +49,24 @@ ${parser.usage}''');

int count = int.parse(options['count']);
final globs = List<Glob>.from(
options['builder'].map((String pattern) => Glob(pattern)));
options['builder'].map((String pattern) => Glob(pattern)),
);

// Download the most recent builds from buildbucket.
const maxBuilds = 1000;
final url = Uri.parse('https://cr-buildbucket.appspot.com'
'/prpc/buildbucket.v2.Builds/SearchBuilds');
final url = Uri.parse(
'https://cr-buildbucket.appspot.com'
'/prpc/buildbucket.v2.Builds/SearchBuilds',
);
const maxRetries = 3;
const timeout = Duration(seconds: 30);
final query = jsonEncode({
'predicate': {
'builder': {'project': 'dart', 'bucket': 'ci.sandbox'},
'status': 'ENDED_MASK'
'status': 'ENDED_MASK',
},
'pageSize': maxBuilds,
'fields': 'builds.*.builder.builder,builds.*.input'
'fields': 'builds.*.builder.builder,builds.*.input',
});
late Map<String, dynamic> searchResult;
for (int i = 1; i <= maxRetries; i++) {
Expand All @@ -67,16 +78,21 @@ ${parser.usage}''');
..write(query);
final response = await request.close().timeout(timeout);
if (response.statusCode != 200) {
print('Failed to search for builds: '
'${response.statusCode}:${response.reasonPhrase}');
print(
'Failed to search for builds: '
'${response.statusCode}:${response.reasonPhrase}',
);
exit(1);
}
const prefix = ")]}'";
searchResult = await (response
.cast<List<int>>()
.transform(Utf8Decoder())
.map((event) =>
event.startsWith(prefix) ? event.substring(prefix.length) : event)
.map(
(event) => event.startsWith(prefix)
? event.substring(prefix.length)
: event,
)
.transform(JsonDecoder())
.cast<Map<String, dynamic>>()
.first
Expand All @@ -86,7 +102,8 @@ ${parser.usage}''');
} on TimeoutException catch (e) {
final inSeconds = e.duration?.inSeconds;
stderr.writeln(
'Attempt $i of $maxRetries timed out after $inSeconds seconds');
'Attempt $i of $maxRetries timed out after $inSeconds seconds',
);
if (i == maxRetries) {
stderr.writeln('error: Failed to download $url');
exit(1);
Expand Down Expand Up @@ -131,8 +148,10 @@ ${parser.usage}''');
continue;
}
final commit = input['id'] as String;
final buildersForCommit =
buildersForCommits.putIfAbsent(commit, () => <String>{});
final buildersForCommit = buildersForCommits.putIfAbsent(
commit,
() => <String>{},
);
buildersForCommit.add(builder);
}

Expand All @@ -148,9 +167,10 @@ ${parser.usage}''');
}

// List commits run on the most builders.
for (final commit in buildersForCommits.keys
.where((commit) => buildersForCommits[commit]!.length == maxBots)
.take(count)) {
for (final commit
in buildersForCommits.keys
.where((commit) => buildersForCommits[commit]!.length == maxBots)
.take(count)) {
print(commit);
}
}
57 changes: 36 additions & 21 deletions builder/bin/upload_results_to_database.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,20 @@ import 'package:http/http.dart' as http;
late BuildInfo buildInfo;

Future<List<Map<String, dynamic>>> readChangedResults(File resultsFile) async {
final lines = (await resultsFile.readAsLines())
.map((line) => jsonDecode(line)! as Map<String, dynamic>);
final lines = (await resultsFile.readAsLines()).map(
(line) => jsonDecode(line)! as Map<String, dynamic>,
);
if (lines.isEmpty) {
print('Empty input results.json file');
exit(1);
}
buildInfo = BuildInfo.fromResult(
lines.first, {for (final line in lines) line[fConfiguration]});
buildInfo = BuildInfo.fromResult(lines.first, {
for (final line in lines) line[fConfiguration],
});
return lines.where(isChangedResult).toList();
}

File fileOption(options, String name) {
File fileOption(ArgResults options, String name) {
final path = options[name];
if (path == null) {
print("Required option '$name'!");
Expand All @@ -40,37 +42,50 @@ File fileOption(options, String name) {
return file;
}

Future<BuildStatus> processResults(options, client, firestore) async {
Future<BuildStatus> processResults(
ArgResults options,
http.Client client,
FirestoreService firestore,
) async {
final inputFile = fileOption(options, 'results');
final results = await readChangedResults(inputFile);
final String? buildbucketID = options['buildbucket_id'];
final String? baseRevision = options['base_revision'];
final commitCache = CommitsCache(firestore, client);
if (buildInfo is TryBuildInfo) {
return Tryjob(buildInfo as TryBuildInfo, buildbucketID!, baseRevision!,
commitCache, firestore, client)
.process(results);
return Tryjob(
buildInfo as TryBuildInfo,
buildbucketID!,
baseRevision!,
commitCache,
firestore,
client,
).process(results);
} else {
return Build(buildInfo, commitCache, firestore).process(results);
}
}

void main(List<String> arguments) async {
final options = (ArgParser()
..addOption('project',
abbr: 'p',
defaultsTo: 'dart-ci-staging',
allowed: ['dart-ci-staging', 'dart-ci'])
..addOption('results', abbr: 'r')
..addOption('buildbucket_id', abbr: 'i')
..addOption('base_revision', abbr: 'b')
..addOption('status_file'))
.parse(arguments);
final options =
(ArgParser()
..addOption(
'project',
abbr: 'p',
defaultsTo: 'dart-ci-staging',
allowed: ['dart-ci-staging', 'dart-ci'],
)
..addOption('results', abbr: 'r')
..addOption('buildbucket_id', abbr: 'i')
..addOption('base_revision', abbr: 'b')
..addOption('status_file'))
.parse(arguments);

final baseClient = http.Client();
final client = await clientViaApplicationDefaultCredentials(
scopes: ['https://www.googleapis.com/auth/cloud-platform'],
baseClient: baseClient);
scopes: ['https://www.googleapis.com/auth/cloud-platform'],
baseClient: baseClient,
);
final api = FirestoreApi(client);
final firestore = FirestoreService(api, client, project: options['project']);

Expand Down
Loading
Loading