[results feed] Add log links to try job failure results
Change-Id: I452ce94fd0709b36a3d4641d9ea8c9b996a9e63f
Reviewed-on: https://dart-review.googlesource.com/c/dart_ci/+/132061
Reviewed-by: Alexander Thomas <athom@google.com>
diff --git a/results_feed/lib/src/components/blamelist.css b/results_feed/lib/src/components/blamelist.css
index f8c38ab..b0bfc70 100644
--- a/results_feed/lib/src/components/blamelist.css
+++ b/results_feed/lib/src/components/blamelist.css
@@ -4,6 +4,6 @@
* BSD-style license that can be found in the LICENSE file.
*/
-.commit { margin-bottom: 8px; display: flex; }
+.commit { margin-bottom: 8px; }
.comment-body { padding-left: 32px; }
span.nowrap { white-space: nowrap; }
\ No newline at end of file
diff --git a/results_feed/lib/src/components/results_panel.dart b/results_feed/lib/src/components/results_panel.dart
index 56625fe..2c6c253 100644
--- a/results_feed/lib/src/components/results_panel.dart
+++ b/results_feed/lib/src/components/results_panel.dart
@@ -15,6 +15,7 @@
import '../formatting.dart' as formatting;
import '../model/commit.dart';
import '../services/filter_service.dart';
+import '../services/try_data_service.dart';
import 'log_component.dart';
@Component(
@@ -43,9 +44,19 @@
@Input()
Changes changes;
+ /// [range] will be null if these are try results
@Input()
IntRange range;
+ /// [builds] will be null if these are CI results
+ @Input()
+ Map<int, Map<String, TryBuild>> builds;
+
+ /// A map from configurations to try builders. Null for CI results.
+ // TODO(whesse): Make lazy, fetch directly from try data service, not an input.
+ @Input()
+ Map<String, String> builders;
+
@Input()
Filter filter = Filter.defaultFilter;
@@ -64,6 +75,9 @@
RelativePosition.OffsetTopLeft
];
+ String buildbucketID(int patchset, String configuration) =>
+ builds[patchset][builders[configuration]].buildbucketID;
+
String approvalContent(Change change) =>
change.approved ? formatting.checkmark : '';
}
diff --git a/results_feed/lib/src/components/results_panel.html b/results_feed/lib/src/components/results_panel.html
index fd49d27..40d3705 100644
--- a/results_feed/lib/src/components/results_panel.html
+++ b/results_feed/lib/src/components/results_panel.html
@@ -30,21 +30,36 @@
tooltipTarget #logs="tooltipTarget"
class="indent pointer">
{{approvalContent(change)}}{{change.name}}<br>
- <material-tooltip-card
- *ngIf="range.length > 0"
- [for]="logs"
- [preferredPositions]="preferredTooltipPositions">
- <div *deferredContent>
- <h4>Logs</h4>
- <dart-log
- *ngFor="let configuration of change.configurations.configurations"
- [configuration]="configuration"
- [index]="range.end"
- [test]="change.name">
- </dart-log>
- </div>
- </material-tooltip-card>
- </span>
+ <material-tooltip-card
+ *ngIf="range != null"
+ [for]="logs"
+ [preferredPositions]="preferredTooltipPositions">
+ <div *deferredContent>
+ <h4>Logs</h4>
+ <dart-log
+ *ngFor="let configuration of change.configurations.configurations"
+ [configuration]="configuration"
+ [index]="range.end"
+ [test]="change.name">
+ </dart-log>
+ </div>
+ </material-tooltip-card>
+ <material-tooltip-card
+ *ngIf="builds != null"
+ [for]="logs"
+ [preferredPositions]="preferredTooltipPositions">
+ <div *deferredContent>
+ <h4>Logs</h4>
+ <div *ngFor="let configuration of change.configurations.configurations">
+ <a *ngIf="buildbucketID(change.patchset, configuration) != null"
+ target="_blank"
+ href="https://logs.chromium.org/logs/dart/buildbucket/cr-buildbucket.appspot.com/{{buildbucketID(change.patchset, configuration)}}/+/steps/test_results/0/logs/new_test_failures__logs_/0">
+ {{configuration}}
+ </a>
+ </div>
+ </div>
+ </material-tooltip-card>
+ </span>
<div
*ngIf="resultGroup.length > resultLimit"
(click)="resultLimit = resultGroup.length"
diff --git a/results_feed/lib/src/components/results_selector_panel.dart b/results_feed/lib/src/components/results_selector_panel.dart
index 8b8957e..b8c4355 100644
--- a/results_feed/lib/src/components/results_selector_panel.dart
+++ b/results_feed/lib/src/components/results_selector_panel.dart
@@ -17,6 +17,7 @@
import '../formatting.dart' as formatting;
import '../model/commit.dart';
import '../services/filter_service.dart';
+import '../services/try_data_service.dart';
import 'log_component.dart';
@Component(
@@ -78,9 +79,19 @@
@Input()
ChangeGroup commit;
+ /// [range] will be null if these are try results
@Input()
IntRange range;
+ /// [builds] will be null if these are CI results
+ @Input()
+ Map<int, Map<String, TryBuild>> builds;
+
+ /// A map from configurations to try builders. Null for CI results.
+ // TODO(whesse): Make lazy, fetch directly from try data service, not an input.
+ @Input()
+ Map<String, String> builders;
+
@Input()
Filter filter = Filter.defaultFilter;
@@ -121,6 +132,9 @@
return configurations.summaries;
}
+ String buildbucketID(int patchset, String configuration) =>
+ builds[patchset][builders[configuration]].buildbucketID;
+
String approvalContent(Change change) =>
change.approved ? formatting.checkmark : '';
diff --git a/results_feed/lib/src/components/results_selector_panel.html b/results_feed/lib/src/components/results_selector_panel.html
index b1202f4..6d44bf5 100644
--- a/results_feed/lib/src/components/results_selector_panel.html
+++ b/results_feed/lib/src/components/results_selector_panel.html
@@ -52,7 +52,7 @@
{{approvalContent(change)}}{{change.name}}
</span><br>
<material-tooltip-card
- *ngIf="range.length > 0"
+ *ngIf="range != null"
[for]="logs"
[preferredPositions]="preferredTooltipPositions">
<div *deferredContent>
@@ -65,6 +65,21 @@
</dart-log>
</div>
</material-tooltip-card>
+ <material-tooltip-card
+ *ngIf="builds != null"
+ [for]="logs"
+ [preferredPositions]="preferredTooltipPositions">
+ <div *deferredContent>
+ <h4>Logs</h4>
+ <div *ngFor="let configuration of change.configurations.configurations">
+ <a *ngIf="buildbucketID(change.patchset, configuration) != null"
+ target="_blank"
+ href="https://logs.chromium.org/logs/dart/buildbucket/cr-buildbucket.appspot.com/{{buildbucketID(change.patchset, configuration)}}/+/steps/test_results/0/logs/new_test_failures__logs_/0">
+ {{configuration}}
+ </a>
+ </div>
+ </div>
+ </material-tooltip-card>
</span>
<div
*ngIf="resultGroup.length > resultLimit"
diff --git a/results_feed/lib/src/components/try_results_component.dart b/results_feed/lib/src/components/try_results_component.dart
index 1b9ecdb..83140da 100644
--- a/results_feed/lib/src/components/try_results_component.dart
+++ b/results_feed/lib/src/components/try_results_component.dart
@@ -47,6 +47,8 @@
int cachedPatchset;
List<Change> changes;
List<Comment> comments;
+ Map<int, Map<String, TryBuild>> builds;
+ Map<String, String> builders;
final IntRange emptyRange = IntRange(1, 0);
bool updating = false;
bool updatePending = false;
@@ -116,6 +118,13 @@
if (review != cachedReview || patchset != cachedPatchset) {
changes = await _tryDataService.changes(reviewInfo, patchset);
comments = await _tryDataService.comments(reviewInfo.review);
+ builds = {
+ for (final patchset in reviewInfo.patchsets) patchset.number: {}
+ };
+ for (final build in reviewInfo.builds) {
+ builds[build.patchset][build.builder] = build;
+ }
+ builders = await _tryDataService.builders();
comments..sort();
cachedReview = review;
cachedPatchset = patchset;
diff --git a/results_feed/lib/src/components/try_results_component.html b/results_feed/lib/src/components/try_results_component.html
index ab18155..bfd2c2e 100644
--- a/results_feed/lib/src/components/try_results_component.html
+++ b/results_feed/lib/src/components/try_results_component.html
@@ -7,11 +7,13 @@
<h2 *ngIf="changeGroup.changes.isEmpty">No changed test results</h2>
<results-panel *ngIf="!approving"
[changes]="changeGroup.changes"
- [range]="emptyRange">
+ [builds]="builds"
+ [builders]="builders">
</results-panel>
<results-selector-panel *ngIf="approving"
[changes]="changeGroup.changes"
- [range]="emptyRange"
+ [builds]="builds"
+ [builders]="builders"
[selected]="selected"
failuresOnly>
</results-selector-panel>
diff --git a/results_feed/lib/src/model/commit.dart b/results_feed/lib/src/model/commit.dart
index 921f9f7..90a1524 100644
--- a/results_feed/lib/src/model/commit.dart
+++ b/results_feed/lib/src/model/commit.dart
@@ -163,6 +163,8 @@
this.blamelistStartIndex,
this.blamelistEndIndex,
this.pinnedIndex,
+ this.review,
+ this.patchset,
this.approved,
this.active)
: changesText = '$previousResult -> $result (expected $expected)',
@@ -180,6 +182,8 @@
document.get('blamelist_start_index'),
document.get('blamelist_end_index'),
document.get('pinned_index'),
+ document.get('review'),
+ document.get('patchset'),
// Old documents may not have this field.
document.get('approved') ?? false,
// Field is only present when true.
@@ -196,6 +200,8 @@
final int blamelistStartIndex;
final int blamelistEndIndex;
int pinnedIndex;
+ final int review;
+ final int patchset;
bool approved;
bool active;
final String configurationsText;
diff --git a/results_feed/lib/src/services/firestore_service.dart b/results_feed/lib/src/services/firestore_service.dart
index 134cc90..02a4dd1 100644
--- a/results_feed/lib/src/services/firestore_service.dart
+++ b/results_feed/lib/src/services/firestore_service.dart
@@ -67,15 +67,22 @@
}
Future<List<firestore.DocumentSnapshot>> fetchTryChanges(
- int cl, int patch) async {
+ int review, int patchset) async {
final results = app.firestore().collection('try_results');
final firestore.QuerySnapshot snapshot = await results
- .where('review', '==', cl)
- .where('patchset', '==', patch)
+ .where('review', '==', review)
+ .where('patchset', '==', patchset)
.get();
return snapshot.docs;
}
+ Future<List<firestore.DocumentSnapshot>> fetchTryBuilds(int review) async {
+ final results = app.firestore().collection('try_builds');
+ final firestore.QuerySnapshot snapshot =
+ await results.where('review', '==', review).get();
+ return snapshot.docs;
+ }
+
Future<firestore.DocumentSnapshot> fetchComment(String id) =>
app.firestore().collection('comments').doc(id).get();
diff --git a/results_feed/lib/src/services/try_data_service.dart b/results_feed/lib/src/services/try_data_service.dart
index 6efc398..03ff973 100644
--- a/results_feed/lib/src/services/try_data_service.dart
+++ b/results_feed/lib/src/services/try_data_service.dart
@@ -1,3 +1,5 @@
+import 'dart:developer';
+
import 'package:firebase/src/firestore.dart';
import '../model/comment.dart';
@@ -13,6 +15,12 @@
bool get isLoggedIn => _firestoreService.isLoggedIn;
+ Map<String, String> _builders;
+
+ Future<Map<String, String>> builders() async {
+ return _builders ??= await _getBuilders();
+ }
+
Future<List<Change>> changes(ReviewInfo reviewInfo, int patchset) async {
final patchsets = reviewInfo.patchsets;
if (patchsets.length < patchset) return [];
@@ -34,7 +42,8 @@
final doc = await _firestoreService.fetchReviewInfo(review);
if (doc.exists) {
return ReviewInfo.fromDocument(doc)
- ..setPatchsets(await _firestoreService.fetchPatchsetInfo(review));
+ ..setPatchsets(await _firestoreService.fetchPatchsetInfo(review))
+ ..setBuilds(await _firestoreService.fetchTryBuilds(review));
} else {
return ReviewInfo(review, "No results received yet for CL $review", []);
}
@@ -53,12 +62,21 @@
approve, comment, baseComment,
tryResultIds: resultIds, review: review));
}
+
+ Future<Map<String, String>> _getBuilders() async {
+ await _firestoreService.getFirebaseClient();
+ List<DocumentSnapshot> builderDocs =
+ await _firestoreService.fetchBuilders();
+ return Map<String, String>.fromIterable(builderDocs,
+ key: (doc) => doc.id, value: (doc) => '${doc.get('builder')}-try');
+ }
}
class ReviewInfo {
int review;
String title;
List<Patchset> patchsets;
+ List<TryBuild> builds;
ReviewInfo(this.review, this.title, this.patchsets);
@@ -69,7 +87,11 @@
}
void setPatchsets(List<DocumentSnapshot> docs) {
- patchsets = docs.map((doc) => Patchset.fromDocument(doc)).toList();
+ patchsets = [for (final doc in docs) Patchset.fromDocument(doc)];
+ }
+
+ void setBuilds(List<DocumentSnapshot> docs) {
+ builds = [for (final doc in docs) TryBuild.fromDocument(doc)];
}
}
@@ -91,3 +113,24 @@
String toString() => "Patchset($number, $patchsetGroup, $description, $kind)";
}
+
+class TryBuild {
+ String builder;
+ int buildNumber;
+ String buildbucketID;
+ bool completed;
+ bool success;
+ int review;
+ int patchset;
+
+ TryBuild.fromDocument(DocumentSnapshot doc) {
+ final data = doc.data();
+ builder = data['builder'];
+ buildNumber = data['build_number'];
+ buildbucketID = data['buildbucket_id'];
+ completed = data['completed'];
+ success = data['success'];
+ review = data['review'];
+ patchset = data['patchset'];
+ }
+}