[cloud functions] Copy tryjob approvals from the last patchset group only.
Pin CI results approved on a tryjob to the commit landing that CL.
Change-Id: Ie61228dff7f7f371503de6920c05f9d2de718350
Reviewed-on: https://dart-review.googlesource.com/c/dart_ci/+/131641
Reviewed-by: Alexander Thomas <athom@google.com>
diff --git a/functions/node/builder.dart b/functions/node/builder.dart
index 8e106b5..08854f1 100644
--- a/functions/node/builder.dart
+++ b/functions/node/builder.dart
@@ -58,7 +58,7 @@
int buildNumber;
int startIndex;
int endIndex;
- Set<String> tryApprovals = {};
+ Map<String, int> tryApprovals = {};
bool success = true; // Changed to false if any unapproved failure is seen.
int countChanges = 0;
int commitsFetched;
@@ -127,17 +127,17 @@
"built commit: $commitHash");
}
}
- Future<void> fetchApprovals(Map<String, dynamic> commit) async {
- if (commit.containsKey('review')) {
- for (final result in await firestore.tryApprovals(commit['review'])) {
- tryApprovals.add(testResult(result));
+ Future<void> fetchApprovals(int review) async {
+ if (review != null) {
+ for (final result in await firestore.tryApprovals(review)) {
+ tryApprovals[testResult(result)] = review;
}
}
}
- await fetchApprovals(endCommit);
+ await fetchApprovals(endCommit['review']);
for (var index = startIndex; index < endIndex; ++index) {
- await fetchApprovals(await firestore.getCommitByIndex(index));
+ await fetchApprovals((await firestore.getCommitByIndex(index))['review']);
}
}
@@ -217,9 +217,10 @@
Map<String, dynamic> activeResult =
await firestore.findActiveResult(change);
if (result == null) {
- approved = tryApprovals.contains(testResult(change));
+ final approvingReview = tryApprovals[testResult(change)];
+ approved = approvingReview != null;
await firestore.storeResult(change, startIndex, endIndex,
- approved: approved, failure: failure);
+ approved: approved, review: approvingReview, failure: failure);
if (approved) {
countApprovalsCopied++;
if (countApprovalsCopied <= 10)
diff --git a/functions/node/firestore.dart b/functions/node/firestore.dart
index b054b9e..f54fc0f 100644
--- a/functions/node/firestore.dart
+++ b/functions/node/firestore.dart
@@ -28,7 +28,7 @@
Future<void> storeResult(
Map<String, dynamic> change, int startIndex, int endIndex,
- {bool approved, bool failure});
+ {bool approved, int review, bool failure});
Future<bool> updateResult(
String result, String configuration, int startIndex, int endIndex,
diff --git a/functions/node/firestore_impl.dart b/functions/node/firestore_impl.dart
index 8e9bf75..355bd42 100644
--- a/functions/node/firestore_impl.dart
+++ b/functions/node/firestore_impl.dart
@@ -133,7 +133,7 @@
Future<void> storeResult(
Map<String, dynamic> change, int startIndex, int endIndex,
- {bool approved, bool failure}) =>
+ {bool approved, int review, bool failure}) =>
firestore.collection('results').add(DocumentData.fromMap({
'name': change['name'],
'result': change['result'],
@@ -141,6 +141,7 @@
'expected': change['expected'],
'blamelist_start_index': startIndex,
'blamelist_end_index': endIndex,
+ if (startIndex != endIndex && approved) 'pinned_index': review,
'configurations': <String>[change['configuration']],
'approved': approved,
if (failure) 'active': true,
@@ -307,10 +308,19 @@
}
Future<List<Map<String, dynamic>>> tryApprovals(int review) async {
+ final patchsets = await firestore
+ .collection('reviews/$review/patchsets')
+ .orderBy('number', descending: true)
+ .limit(1)
+ .get();
+ final lastPatchsetGroup =
+ patchsets.documents.first.data.getInt('patchset_group');
+ print(lastPatchsetGroup);
QuerySnapshot approvals = await firestore
.collection('try_results')
.where('approved', isEqualTo: true)
.where('review', isEqualTo: review)
+ .where('patchset', isGreaterThanOrEqualTo: lastPatchsetGroup)
.get();
return [for (final document in approvals.documents) document.data.toMap()];
}
diff --git a/functions/node/test/firestore_test_nodejs.dart b/functions/node/test/firestore_test_nodejs.dart
index c475dc9..1e09c08 100644
--- a/functions/node/test/firestore_test_nodejs.dart
+++ b/functions/node/test/firestore_test_nodejs.dart
@@ -78,6 +78,73 @@
for (final doc in snapshot.documents) {
await doc.reference.delete();
}
+ snapshot =
+ await fs.firestore.collection('reviews/$testReview/patchsets').get();
+ for (final doc in snapshot.documents) {
+ await doc.reference.delete();
+ }
+ await fs.firestore.document('reviews/$testReview').delete();
+ });
+
+ test('approved try result fetching', () async {
+ await firestore.storeReview(testReview.toString(), {
+ 'subject': 'test review: approved try result fetching',
+ });
+ await firestore.storePatchset(testReview.toString(), 1, {
+ 'kind': 'REWORK',
+ 'description': 'Initial upload',
+ 'patchset_group': 1,
+ 'number': 1,
+ });
+ await firestore.storePatchset(testReview.toString(), 2, {
+ 'kind': 'REWORK',
+ 'description': 'change',
+ 'patchset_group': 2,
+ 'number': 2,
+ });
+ await firestore.storePatchset(testReview.toString(), 3, {
+ 'kind': 'NO_CODE_CHANGE',
+ 'description': 'Edit commit message',
+ 'patchset_group': 2,
+ 'number': 3,
+ });
+ final tryResult = {
+ 'review': testReview,
+ 'configuration': 'test_configuration',
+ 'name': 'test_suite/test_name',
+ 'patchset': 1,
+ 'result': 'RuntimeError',
+ 'expected': 'Pass',
+ 'previous_result': 'Pass',
+ };
+ await firestore.storeTryChange(tryResult, testReview, 1);
+ final tryResult2 = Map<String, dynamic>.from(tryResult);
+ tryResult2['patchset'] = 2;
+ tryResult2['name'] = 'test_suite/test_name_2';
+ await firestore.storeTryChange(tryResult2, testReview, 2);
+ tryResult['patchset'] = 3;
+ tryResult['name'] = 'test_suite/test_name';
+ tryResult['expected'] = 'CompileTimeError';
+ await firestore.storeTryChange(tryResult, testReview, 3);
+ // Set the results on patchsets 1 and 2 to approved.
+ final snapshot = await fs.firestore
+ .collection('try_results')
+ .where('approved', isEqualTo: false)
+ .where('review', isEqualTo: testReview)
+ .where('patchset', isLessThanOrEqualTo: 2)
+ .get();
+ for (final document in snapshot.documents) {
+ await document.reference
+ .updateData(UpdateData.fromMap({'approved': true}));
+ }
+
+ // Should return only the approved change on patchset 2,
+ // not the one on patchset 1 or the unapproved change on patchset 3.
+ final approvals = await firestore.tryApprovals(testReview);
+ tryResult2['configurations'] = [tryResult2['configuration']];
+ tryResult2['approved'] = true;
+ tryResult2.remove('configuration');
+ expect(approvals, [tryResult2]);
});
test('Test tryjob result processing', () async {
@@ -87,7 +154,7 @@
final previousFailingChange = Map<String, dynamic>.from(
tryjobFailingChange)
..addAll(
- {"commit_hash": testPreviousPatchsetPath, "build_number": "307"});
+ {'commit_hash': testPreviousPatchsetPath, 'build_number': '307'});
await Tryjob(testPreviousPatchsetPath, 1, firestore, null)
.process([previousFailingChange]);
var snapshot = await fs.firestore
diff --git a/functions/node/test/test.dart b/functions/node/test/test.dart
index f561385..acc0a4a 100644
--- a/functions/node/test/test.dart
+++ b/functions/node/test/test.dart
@@ -84,8 +84,10 @@
await builder.storeBuildCommitsInfo();
expect(builder.endIndex, landedCommit['index']);
expect(builder.startIndex, existingCommit['index'] + 1);
- expect(builder.tryApprovals,
- {testResult(tryjobResults[0]), testResult(tryjobResults[1])});
+ expect(builder.tryApprovals, {
+ testResult(tryjobResults[0]): 44445,
+ testResult(tryjobResults[1]): 77779
+ });
verifyInOrder([
verify(firestore.getCommit(landedCommitHash)).called(2),
verify(firestore.getLastCommit()),
@@ -146,6 +148,7 @@
firestore.findResult(any, 53, 54),
firestore.storeResult(any, 53, 54,
approved: argThat(isTrue, named: 'approved'),
+ review: argThat(equals(44445), named: 'review'),
failure: argThat(isTrue, named: 'failure'))
]);
});