| 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 | 10 |
| 11 import 'package:gardening/src/bot.dart'; |
| 11 import 'package:gardening/src/buildbot_structures.dart'; | 12 import 'package:gardening/src/buildbot_structures.dart'; |
| 12 import 'package:gardening/src/buildbot_data.dart'; | 13 import 'package:gardening/src/buildbot_data.dart'; |
| 13 import 'package:gardening/src/client.dart'; | |
| 14 import 'package:gardening/src/util.dart'; | 14 import 'package:gardening/src/util.dart'; |
| 15 | 15 |
| 16 Future mainInternal(BuildbotClient client, List<String> args, | 16 Future mainInternal(Bot bot, List<String> args, {int runCount: 10}) async { |
| 17 {int runCount: 10}) async { | |
| 18 printBuildResultsSummary( | 17 printBuildResultsSummary( |
| 19 await loadBuildResults(client, args, runCount: runCount), args); | 18 await loadBuildResults(bot, args, runCount: runCount), args); |
| 20 } | 19 } |
| 21 | 20 |
| 22 /// Loads [BuildResult]s for the [runCount] last builds for the build(s) in | 21 /// Loads [BuildResult]s for the [runCount] last builds for the build(s) in |
| 23 /// [args]. [args] can be a list of [BuildGroup] names or a list of log uris. | 22 /// [args]. [args] can be a list of [BuildGroup] names or a list of log uris. |
| 24 Future<Map<BuildUri, List<BuildResult>>> loadBuildResults( | 23 Future<Map<BuildUri, List<BuildResult>>> loadBuildResults( |
| 25 BuildbotClient client, List<String> args, | 24 Bot bot, List<String> args, |
| 26 {int runCount: 10}) async { | 25 {int runCount: 10}) async { |
| 27 List<BuildUri> buildUriList = <BuildUri>[]; | 26 List<BuildUri> buildUriList = <BuildUri>[]; |
| 28 for (BuildGroup buildGroup in buildGroups) { | 27 for (BuildGroup buildGroup in buildGroups) { |
| 29 if (args.contains(buildGroup.groupName)) { | 28 if (args.contains(buildGroup.groupName)) { |
| 30 buildUriList.addAll(buildGroup.createUris(client.mostRecentBuildNumber)); | 29 buildUriList.addAll(buildGroup.createUris(bot.mostRecentBuildNumber)); |
| 31 } | 30 } |
| 32 } | 31 } |
| 33 if (buildUriList.isEmpty) { | 32 if (buildUriList.isEmpty) { |
| 34 for (String url in args) { | 33 for (String url in args) { |
| 35 buildUriList.add(new BuildUri.fromUrl(url)); | 34 buildUriList.add(new BuildUri.fromUrl(url)); |
| 36 } | 35 } |
| 37 } | 36 } |
| 38 Map<BuildUri, List<BuildResult>> buildResults = | 37 Map<BuildUri, List<BuildResult>> pastResultsMap = |
| 39 <BuildUri, List<BuildResult>>{}; | 38 <BuildUri, List<BuildResult>>{}; |
| 40 for (BuildUri buildUri in buildUriList) { | 39 List<BuildResult> buildResults = await bot.readResults(buildUriList); |
| 40 for (int index = 0; index < buildUriList.length; index++) { |
| 41 BuildUri buildUri = buildUriList[index]; |
| 42 BuildResult buildResult = buildResults[index]; |
| 41 List<BuildResult> results = | 43 List<BuildResult> results = |
| 42 await readBuildResults(client, buildUri, runCount); | 44 await readPastResults(bot, buildUri, buildResult, runCount); |
| 43 buildResults[buildUri] = results; | 45 pastResultsMap[buildUri] = results; |
| 44 } | 46 } |
| 45 return buildResults; | 47 return pastResultsMap; |
| 46 } | 48 } |
| 47 | 49 |
| 48 /// Prints summaries for the [buildResults]. | 50 /// Prints summaries for the [buildResults]. |
| 49 void printBuildResultsSummary( | 51 void printBuildResultsSummary( |
| 50 Map<BuildUri, List<BuildResult>> buildResults, List<String> args) { | 52 Map<BuildUri, List<BuildResult>> buildResults, List<String> args) { |
| 51 List<Summary> emptySummaries = <Summary>[]; | 53 List<Summary> emptySummaries = <Summary>[]; |
| 52 List<Summary> nonEmptySummaries = <Summary>[]; | 54 List<Summary> nonEmptySummaries = <Summary>[]; |
| 53 buildResults.forEach((BuildUri buildUri, List<BuildResult> results) { | 55 buildResults.forEach((BuildUri buildUri, List<BuildResult> results) { |
| 54 Summary summary = new Summary(buildUri, results); | 56 Summary summary = new Summary(buildUri, results); |
| 55 if (summary.isEmpty) { | 57 if (summary.isEmpty) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 92 sb.write( | 94 sb.write( |
| 93 'No errors found for the ${emptySummaries.length} remaining bots.'); | 95 'No errors found for the ${emptySummaries.length} remaining bots.'); |
| 94 } | 96 } |
| 95 } | 97 } |
| 96 } | 98 } |
| 97 print(sb); | 99 print(sb); |
| 98 } | 100 } |
| 99 | 101 |
| 100 /// Creates a [BuildResult] for [buildUri] and, if it contains failures, the | 102 /// Creates a [BuildResult] for [buildUri] and, if it contains failures, the |
| 101 /// [BuildResult]s for the previous [runCount] builds. | 103 /// [BuildResult]s for the previous [runCount] builds. |
| 102 Future<List<BuildResult>> readBuildResults( | 104 Future<List<BuildResult>> readPastResults( |
| 103 BuildbotClient client, BuildUri buildUri, int runCount) async { | 105 Bot bot, BuildUri buildUri, BuildResult summary, int runCount) async { |
| 104 List<BuildResult> summaries = <BuildResult>[]; | 106 List<BuildResult> summaries = <BuildResult>[]; |
| 105 BuildResult summary = await client.readResult(buildUri); | |
| 106 if (summary == null) { | 107 if (summary == null) { |
| 107 print('No result found for $buildUri'); | 108 print('No result found for $buildUri'); |
| 108 return summaries; | 109 return summaries; |
| 109 } | 110 } |
| 110 summaries.add(summary); | 111 summaries.add(summary); |
| 111 if (summary.hasFailures) { | 112 if (summary.hasFailures) { |
| 112 for (int i = 0; i < runCount; i++) { | 113 summaries.addAll(await bot.readHistoricResults(summary.buildUri.prev(), |
| 113 buildUri = summary.buildUri.prev(); | 114 previousCount: runCount - 1)); |
| 114 summary = await client.readResult(buildUri); | |
| 115 summaries.add(summary); | |
| 116 } | |
| 117 } | 115 } |
| 118 return summaries; | 116 return summaries; |
| 119 } | 117 } |
| 120 | 118 |
| 121 class Summary { | 119 class Summary { |
| 122 final BuildUri buildUri; | 120 final BuildUri buildUri; |
| 123 final List<BuildResult> results; | 121 final List<BuildResult> results; |
| 124 final Set<TestConfiguration> timeoutIds = new Set<TestConfiguration>(); | 122 final Set<TestConfiguration> timeoutIds = new Set<TestConfiguration>(); |
| 125 final Set<TestConfiguration> errorIds = new Set<TestConfiguration>(); | 123 final Set<TestConfiguration> errorIds = new Set<TestConfiguration>(); |
| 126 | 124 |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 209 sb.write('No errors found for ${name}'); | 207 sb.write('No errors found for ${name}'); |
| 210 } | 208 } |
| 211 } | 209 } |
| 212 | 210 |
| 213 String get name => results.isNotEmpty | 211 String get name => results.isNotEmpty |
| 214 // Use the first result as name since it most likely has an absolute build | 212 // Use the first result as name since it most likely has an absolute build |
| 215 // number. | 213 // number. |
| 216 ? results.first.buildUri.toString() | 214 ? results.first.buildUri.toString() |
| 217 : buildUri.toString(); | 215 : buildUri.toString(); |
| 218 } | 216 } |
| OLD | NEW |