Adding approval of the revert request (#2089)
diff --git a/auto_submit/lib/requests/check_pull_request.dart b/auto_submit/lib/requests/check_pull_request.dart
index 46b99b3..095159a 100644
--- a/auto_submit/lib/requests/check_pull_request.dart
+++ b/auto_submit/lib/requests/check_pull_request.dart
@@ -62,7 +62,7 @@
await pubsub.acknowledge('auto-submit-queue-sub', message.ackId!);
continue;
} else {
- await approver.approve(pullRequest);
+ await approver.autoApproval(pullRequest);
log.info('Approved pull request: $rawBody');
processingLog.add(pullRequest.number!);
}
diff --git a/auto_submit/lib/service/approver_service.dart b/auto_submit/lib/service/approver_service.dart
index 421591b..b767d80 100644
--- a/auto_submit/lib/service/approver_service.dart
+++ b/auto_submit/lib/service/approver_service.dart
@@ -21,14 +21,34 @@
return ApproverService(config);
}
- Future<void> approve(PullRequest pullRequest) async {
+ Future<void> autoApproval(PullRequest pullRequest) async {
final String? author = pullRequest.user!.login;
if (!config.rollerAccounts.contains(author)) {
log.info('Auto-review ignored for $author');
- return;
+ } else {
+ await _approve(pullRequest, author);
}
+ }
+ /// Auto approves a pull request when the revert label is present.
+ Future<void> revertApproval(PullRequest pullRequest) async {
+ final Set<String> approvedAuthorAssociations = <String>{'MEMBER', 'OWNER'};
+
+ final String? author = pullRequest.user!.login;
+ final String? authorAssociation = pullRequest.authorAssociation;
+ final List<String> labelNames =
+ (pullRequest.labels as List<IssueLabel>).map<String>((IssueLabel labelMap) => labelMap.name).toList();
+
+ if (labelNames.contains(Config.kRevertLabel) &&
+ (config.rollerAccounts.contains(author) || approvedAuthorAssociations.contains(authorAssociation))) {
+ await _approve(pullRequest, author);
+ } else {
+ log.info('Auto-review ignored for $author');
+ }
+ }
+
+ Future<void> _approve(PullRequest pullRequest, String? author) async {
final RepositorySlug slug = pullRequest.base!.repo!.slug();
final GitHub botClient = await config.createFlutterGitHubBotClient(slug);
diff --git a/auto_submit/lib/service/validation_service.dart b/auto_submit/lib/service/validation_service.dart
index ef17b8d..caf02cb 100644
--- a/auto_submit/lib/service/validation_service.dart
+++ b/auto_submit/lib/service/validation_service.dart
@@ -3,6 +3,7 @@
// found in the LICENSE file.
import 'package:auto_submit/requests/check_pull_request_queries.dart';
+import 'package:auto_submit/service/approver_service.dart';
import 'package:auto_submit/service/config.dart';
import 'package:auto_submit/service/github_service.dart';
import 'package:auto_submit/service/graphql_service.dart';
@@ -196,6 +197,10 @@
final GithubService githubService = await config.createGithubService(slug);
if (revertValidationResult.result) {
+ // Approve the pull request automatically as it has been validated.
+ ApproverService approverService = ApproverService(config);
+ approverService.revertApproval(messagePullRequest);
+
bool processed = await processMerge(config, result, messagePullRequest);
if (processed) {
await pubsub.acknowledge('auto-submit-queue-sub', ackId);
diff --git a/auto_submit/pubspec.yaml b/auto_submit/pubspec.yaml
index 553c19a..eb38652 100644
--- a/auto_submit/pubspec.yaml
+++ b/auto_submit/pubspec.yaml
@@ -19,7 +19,7 @@
graphql: ^5.1.1
gql: ^0.13.1
http: ^0.13.5
- json_annotation: ^4.5.0
+ json_annotation: ^4.6.0
meta: ^1.8.0
neat_cache: ^2.0.2
shelf: ^1.3.2
diff --git a/auto_submit/test/service/approver_service_test.dart b/auto_submit/test/service/approver_service_test.dart
index 57b0525..e71291d 100644
--- a/auto_submit/test/service/approver_service_test.dart
+++ b/auto_submit/test/service/approver_service_test.dart
@@ -28,14 +28,14 @@
test('Verify approval ignored', () async {
PullRequest pr = generatePullRequest(author: 'not_a_user');
- await service.approve(pr);
+ await service.autoApproval(pr);
verifyNever(pullRequests.createReview(any, captureAny));
});
test('Verify approve', () async {
when(pullRequests.listReviews(any, any)).thenAnswer((_) => const Stream<PullRequestReview>.empty());
PullRequest pr = generatePullRequest(author: 'dependabot[bot]');
- await service.approve(pr);
+ await service.autoApproval(pr);
final List<dynamic> reviews = verify(pullRequests.createReview(any, captureAny)).captured;
expect(reviews.length, 1);
final CreatePullRequestReview review = reviews.single as CreatePullRequestReview;
@@ -46,7 +46,43 @@
PullRequestReview review = PullRequestReview(id: 123, user: User(login: 'fluttergithubbot'), state: 'APPROVED');
when(pullRequests.listReviews(any, any)).thenAnswer((_) => Stream<PullRequestReview>.value(review));
PullRequest pr = generatePullRequest(author: 'dependabot[bot]');
- await service.approve(pr);
+ await service.autoApproval(pr);
+ verifyNever(pullRequests.createReview(any, captureAny));
+ });
+
+ test('AutoApproval does not approve revert pull request.', () async {
+ PullRequest pr = generatePullRequest(author: 'not_a_user');
+ List<IssueLabel> issueLabels = pr.labels ?? [];
+ IssueLabel issueLabel = IssueLabel(name: 'revert');
+ issueLabels.add(issueLabel);
+ await service.autoApproval(pr);
+ verifyNever(pullRequests.createReview(any, captureAny));
+ });
+
+ test('Revert request is auto approved.', () async {
+ when(pullRequests.listReviews(any, any)).thenAnswer((_) => const Stream<PullRequestReview>.empty());
+ PullRequest pr = generatePullRequest(author: 'dependabot[bot]');
+
+ List<IssueLabel> issueLabels = pr.labels ?? [];
+ IssueLabel issueLabel = IssueLabel(name: 'revert');
+ issueLabels.add(issueLabel);
+
+ await service.revertApproval(pr);
+ final List<dynamic> reviews = verify(pullRequests.createReview(any, captureAny)).captured;
+ expect(reviews.length, 1);
+ final CreatePullRequestReview review = reviews.single as CreatePullRequestReview;
+ expect(review.event, 'APPROVE');
+ });
+
+ test('Revert request is not auto approved when the revert label is not present.', () async {
+ PullRequest pr = generatePullRequest(author: 'not_a_user');
+ await service.revertApproval(pr);
+ verifyNever(pullRequests.createReview(any, captureAny));
+ });
+
+ test('Revert request is not auto approved on bad author association.', () async {
+ PullRequest pr = generatePullRequest(author: 'not_a_user', authorAssociation: 'CONTRIBUTOR');
+ await service.revertApproval(pr);
verifyNever(pullRequests.createReview(any, captureAny));
});
}
diff --git a/auto_submit/test/utilities/mocks.mocks.dart b/auto_submit/test/utilities/mocks.mocks.dart
index 702a90d..33d35ac 100644
--- a/auto_submit/test/utilities/mocks.mocks.dart
+++ b/auto_submit/test/utilities/mocks.mocks.dart
@@ -200,8 +200,13 @@
(super.noSuchMethod(Invocation.getter(#config), returnValue: _FakeConfig_0(this, Invocation.getter(#config)))
as _i2.Config);
@override
- _i6.Future<void> approve(_i4.PullRequest? pullRequest) =>
- (super.noSuchMethod(Invocation.method(#approve, [pullRequest]),
+ _i6.Future<void> autoApproval(_i4.PullRequest? pullRequest) =>
+ (super.noSuchMethod(Invocation.method(#autoApproval, [pullRequest]),
+ returnValue: _i6.Future<void>.value(),
+ returnValueForMissingStub: _i6.Future<void>.value()) as _i6.Future<void>);
+ @override
+ _i6.Future<void> revertApproval(_i4.PullRequest? pullRequest) =>
+ (super.noSuchMethod(Invocation.method(#revertApproval, [pullRequest]),
returnValue: _i6.Future<void>.value(),
returnValueForMissingStub: _i6.Future<void>.value()) as _i6.Future<void>);
}