OLD | NEW |
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 /// Compares the test log of a build step with previous builds. | 5 /// Compares the test log of a build step with previous builds. |
6 /// | 6 /// |
7 /// Use this to detect flakiness of failures, especially timeouts. | 7 /// Use this to detect flakiness of failures, especially timeouts. |
8 | 8 |
9 import 'dart:async'; | 9 import 'dart:async'; |
| 10 import 'dart:io'; |
10 | 11 |
11 import 'package:gardening/src/bot.dart'; | 12 import 'package:gardening/src/bot.dart'; |
12 import 'package:gardening/src/buildbot_structures.dart'; | 13 import 'package:gardening/src/buildbot_structures.dart'; |
13 import 'package:gardening/src/buildbot_data.dart'; | 14 import 'package:gardening/src/buildbot_data.dart'; |
14 import 'package:gardening/src/util.dart'; | 15 import 'package:gardening/src/util.dart'; |
15 | 16 |
16 Future mainInternal(Bot bot, List<String> args, {int runCount: 10}) async { | 17 Future mainInternal(Bot bot, List<String> args, {int runCount: 10}) async { |
17 printBuildResultsSummary( | 18 printBuildResultsSummary( |
18 await loadBuildResults(bot, args, runCount: runCount), args); | 19 await loadBuildResults(bot, args, runCount: runCount), args); |
19 } | 20 } |
20 | 21 |
| 22 RegExp logdogUrlRegexp = |
| 23 new RegExp(r'https://luci-logdog.appspot.com/.*client.dart'); |
| 24 |
21 /// Loads [BuildResult]s for the [runCount] last builds for the build(s) in | 25 /// Loads [BuildResult]s for the [runCount] last builds for the build(s) in |
22 /// [args]. [args] can be a list of [BuildGroup] names or a list of log uris. | 26 /// [args]. [args] can be a list of [BuildGroup] names or a list of log uris. |
23 Future<Map<BuildUri, List<BuildResult>>> loadBuildResults( | 27 Future<Map<BuildUri, List<BuildResult>>> loadBuildResults( |
24 Bot bot, List<String> args, | 28 Bot bot, List<String> args, |
25 {int runCount: 10}) async { | 29 {int runCount: 10}) async { |
26 List<BuildUri> buildUriList = <BuildUri>[]; | 30 List<BuildUri> buildUriList = <BuildUri>[]; |
| 31 for (String arg in args) { |
| 32 if (logdogUrlRegexp.hasMatch(arg)) { |
| 33 print('Encountered a logdog URI ("${arg.substring(0,40)}...").'); |
| 34 print('Please use the regular log URI, even with --logdog.'); |
| 35 exit(-1); |
| 36 } |
| 37 } |
27 for (BuildGroup buildGroup in buildGroups) { | 38 for (BuildGroup buildGroup in buildGroups) { |
28 if (args.contains(buildGroup.groupName)) { | 39 if (args.contains(buildGroup.groupName)) { |
29 buildUriList.addAll(buildGroup.createUris(bot.mostRecentBuildNumber)); | 40 buildUriList.addAll(buildGroup.createUris(bot.mostRecentBuildNumber)); |
30 } | 41 } |
31 } | 42 } |
32 if (buildUriList.isEmpty) { | 43 if (buildUriList.isEmpty) { |
33 for (String url in args) { | 44 for (String url in args) { |
34 buildUriList.add(new BuildUri.fromUrl(url)); | 45 buildUriList.add(new BuildUri.fromUrl(url)); |
35 } | 46 } |
36 } | 47 } |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 } | 132 } |
122 | 133 |
123 class Summary { | 134 class Summary { |
124 final BuildUri buildUri; | 135 final BuildUri buildUri; |
125 final List<BuildResult> results; | 136 final List<BuildResult> results; |
126 final Set<TestConfiguration> timeoutIds = new Set<TestConfiguration>(); | 137 final Set<TestConfiguration> timeoutIds = new Set<TestConfiguration>(); |
127 final Set<TestConfiguration> errorIds = new Set<TestConfiguration>(); | 138 final Set<TestConfiguration> errorIds = new Set<TestConfiguration>(); |
128 | 139 |
129 Summary(this.buildUri, this.results) { | 140 Summary(this.buildUri, this.results) { |
130 for (BuildResult result in results) { | 141 for (BuildResult result in results) { |
| 142 if (result == null) continue; |
131 timeoutIds | 143 timeoutIds |
132 .addAll(result.timeouts.map((TestFailure failure) => failure.id)); | 144 .addAll(result.timeouts.map((TestFailure failure) => failure.id)); |
133 errorIds.addAll(result.errors.map((TestFailure failure) => failure.id)); | 145 errorIds.addAll(result.errors.map((TestFailure failure) => failure.id)); |
134 } | 146 } |
135 } | 147 } |
136 | 148 |
137 bool get isEmpty => timeoutIds.isEmpty && errorIds.isEmpty; | 149 bool get isEmpty => timeoutIds.isEmpty && errorIds.isEmpty; |
138 | 150 |
139 /// Generate a summary of the timeouts and other failures in [results]. | 151 /// Generate a summary of the timeouts and other failures in [results]. |
140 void printOn(StringBuffer sb) { | 152 void printOn(StringBuffer sb) { |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
211 sb.write('No errors found for ${name}'); | 223 sb.write('No errors found for ${name}'); |
212 } | 224 } |
213 } | 225 } |
214 | 226 |
215 String get name => results.isNotEmpty | 227 String get name => results.isNotEmpty |
216 // Use the first result as name since it most likely has an absolute build | 228 // Use the first result as name since it most likely has an absolute build |
217 // number. | 229 // number. |
218 ? results.first.buildUri.toString() | 230 ? results.first.buildUri.toString() |
219 : buildUri.toString(); | 231 : buildUri.toString(); |
220 } | 232 } |
OLD | NEW |