Auto-roller accounts do not get labeled/commented with needs tests (#1925)

diff --git a/app_dart/lib/src/request_handlers/github_webhook.dart b/app_dart/lib/src/request_handlers/github_webhook.dart
index c11c6a8..69ab6f1 100644
--- a/app_dart/lib/src/request_handlers/github_webhook.dart
+++ b/app_dart/lib/src/request_handlers/github_webhook.dart
@@ -262,6 +262,7 @@
         needsTests = !_allChangesAreCodeComments(file);
       }
 
+      // Check to see if tests were submitted with this PR.
       if (_isATest(filename)) {
         hasTests = true;
       }
@@ -277,6 +278,11 @@
       await gitHubClient.issues.addLabelsToIssue(slug, pr.number!, labels.toList());
     }
 
+    // We do not need to add test labels if this is an auto roller author.
+    if (config.rollerAccounts.contains(pr.user!.login)) {
+      return;
+    }
+
     if (!hasTests && needsTests && !pr.draft! && !_isReleaseBranch(pr)) {
       final String body = config.missingTestsPullRequestMessage;
       if (!await _alreadyCommented(gitHubClient, pr, body)) {
@@ -383,9 +389,11 @@
   }
 
   Future<void> _applyEngineRepoLabels(GitHub gitHubClient, String? eventAction, PullRequest pr) async {
+    // Do not apply the test labels for the autoroller accounts.
     if (pr.user!.login == 'skia-flutter-autoroll') {
       return;
     }
+
     final RepositorySlug slug = pr.base!.repo!.slug();
     final Stream<PullRequestFile> files = gitHubClient.pullRequests.listFiles(slug, pr.number!);
     final Set<String> labels = <String>{};
@@ -413,6 +421,11 @@
       await gitHubClient.issues.addLabelsToIssue(slug, pr.number!, labels.toList());
     }
 
+    // We do not need to add test labels if this is an auto roller author.
+    if (config.rollerAccounts.contains(pr.user!.login)) {
+      return;
+    }
+
     if (!hasTests && needsTests && !pr.draft! && !_isReleaseBranch(pr)) {
       final String body = config.missingTestsPullRequestMessage;
       if (!await _alreadyCommented(gitHubClient, pr, body)) {
@@ -466,6 +479,11 @@
       }
     }
 
+    // We do not need to add test labels if this is an auto roller author.
+    if (config.rollerAccounts.contains(pr.user!.login)) {
+      return;
+    }
+
     if (!hasTests && needsTests && !pr.draft! && !_isReleaseBranch(pr)) {
       final String body = config.missingTestsPullRequestMessage;
       if (!await _alreadyCommented(gitHubClient, pr, body)) {
diff --git a/app_dart/test/request_handlers/github_webhook_test.dart b/app_dart/test/request_handlers/github_webhook_test.dart
index 83859d8..a2b16ec 100644
--- a/app_dart/test/request_handlers/github_webhook_test.dart
+++ b/app_dart/test/request_handlers/github_webhook_test.dart
@@ -113,6 +113,11 @@
     config.webhookKeyValue = keyString;
     config.githubClient = gitHubClient;
     config.deviceLabServiceAccountValue = const ServiceAccountInfo(email: serviceAccountEmail);
+    config.rollerAccountsValue = const <String>{
+      'skia-flutter-autoroll',
+      'engine-flutter-autoroll',
+      'dependabot',
+    };
   });
 
   group('github webhook pull_request event', () {
@@ -704,6 +709,90 @@
       )).called(1);
     });
 
+    group("Auto-roller accounts do not label Framework PR with test label or comment.", () {
+      Set<String> inputs = {
+        'skia-flutter-autoroll',
+        'dependabot',
+      };
+
+      for (String element in inputs) {
+        test('Framework does not label PR with no tests label if author is $element', () async {
+          const int issueNumber = 123;
+          request.headers.set('X-GitHub-Event', 'pull_request');
+          request.body = generatePullRequestEvent('opened', issueNumber, kDefaultBranchName, login: element);
+          final Uint8List body = utf8.encode(request.body!) as Uint8List;
+          final Uint8List key = utf8.encode(keyString) as Uint8List;
+          final String hmac = getHmac(body, key);
+          request.headers.set('X-Hub-Signature', 'sha1=$hmac');
+          final RepositorySlug slug = RepositorySlug('flutter', 'flutter');
+
+          when(pullRequestsService.listFiles(slug, issueNumber)).thenAnswer(
+            (_) => Stream<PullRequestFile>.value(
+              PullRequestFile()..filename = 'packages/flutter/blah.dart',
+            ),
+          );
+
+          when(issuesService.listCommentsByIssue(slug, issueNumber)).thenAnswer(
+            (_) => Stream<IssueComment>.value(
+              IssueComment()..body = 'some other comment',
+            ),
+          );
+
+          await tester.post(webhook);
+
+          verify(issuesService.addLabelsToIssue(
+            slug,
+            issueNumber,
+            <String>['framework'],
+          )).called(1);
+
+          verifyNever(issuesService.createComment(
+            slug,
+            issueNumber,
+            argThat(contains(config.missingTestsPullRequestMessageValue)),
+          ));
+        });
+      }
+    });
+
+    test('Framework does not label PR with no tests label if author is engine-flutter-autoroll', () async {
+      const int issueNumber = 123;
+      request.headers.set('X-GitHub-Event', 'pull_request');
+      request.body =
+          generatePullRequestEvent('opened', issueNumber, kDefaultBranchName, login: 'engine-flutter-autoroll');
+      final Uint8List body = utf8.encode(request.body!) as Uint8List;
+      final Uint8List key = utf8.encode(keyString) as Uint8List;
+      final String hmac = getHmac(body, key);
+      request.headers.set('X-Hub-Signature', 'sha1=$hmac');
+      final RepositorySlug slug = RepositorySlug('flutter', 'flutter');
+
+      when(pullRequestsService.listFiles(slug, issueNumber)).thenAnswer(
+        (_) => Stream<PullRequestFile>.value(
+          PullRequestFile()..filename = 'packages/flutter/blah.dart',
+        ),
+      );
+
+      when(issuesService.listCommentsByIssue(slug, issueNumber)).thenAnswer(
+        (_) => Stream<IssueComment>.value(
+          IssueComment()..body = 'some other comment',
+        ),
+      );
+
+      await tester.post(webhook);
+
+      verifyNever(issuesService.addLabelsToIssue(
+        slug,
+        issueNumber,
+        <String>['framework'],
+      ));
+
+      verifyNever(issuesService.createComment(
+        slug,
+        issueNumber,
+        argThat(contains(config.missingTestsPullRequestMessageValue)),
+      ));
+    });
+
     test('Framework labels PRs, comment if no tests including hit_test.dart file', () async {
       const int issueNumber = 123;
       request.headers.set('X-GitHub-Event', 'pull_request');
@@ -1282,6 +1371,105 @@
       )).called(1);
     });
 
+    group("Auto-roller accounts do not label Engine PR with test label or comment.", () {
+      Set<String> inputs = {
+        'engine-flutter-autoroll',
+        'dependabot',
+      };
+
+      for (String element in inputs) {
+        test('Engine does not label PR for no tests if author is $element', () async {
+          const int issueNumber = 123;
+          request.headers.set('X-GitHub-Event', 'pull_request');
+          request.body = generatePullRequestEvent('opened', issueNumber, kDefaultBranchName,
+              repoName: 'engine', repoFullName: 'flutter/engine', login: element);
+
+          final Uint8List body = utf8.encode(request.body!) as Uint8List;
+          final Uint8List key = utf8.encode(keyString) as Uint8List;
+          final String hmac = getHmac(body, key);
+          request.headers.set('X-Hub-Signature', 'sha1=$hmac');
+          final RepositorySlug slug = RepositorySlug('flutter', 'engine');
+
+          when(pullRequestsService.listFiles(slug, issueNumber)).thenAnswer(
+            (_) => Stream<PullRequestFile>.value(
+              PullRequestFile()..filename = 'shell/platform/darwin/ios/framework/Source/boost.mm',
+            ),
+          );
+
+          when(issuesService.listCommentsByIssue(slug, issueNumber)).thenAnswer(
+            (_) => Stream<IssueComment>.value(
+              IssueComment()..body = 'some other comment',
+            ),
+          );
+
+          await tester.post(webhook);
+
+          verify(issuesService.addLabelsToIssue(
+            slug,
+            issueNumber,
+            <String>['platform-ios'],
+          )).called(1);
+
+          verifyNever(issuesService.createComment(
+            slug,
+            issueNumber,
+            argThat(contains(config.missingTestsPullRequestMessageValue)),
+          ));
+
+          verifyNever(issuesService.addLabelsToIssue(
+            slug,
+            issueNumber,
+            <String>['needs tests'],
+          ));
+        });
+      }
+    });
+
+    test('Engine does not label PR for no tests if author is skia-flutter-autoroll', () async {
+      const int issueNumber = 123;
+      request.headers.set('X-GitHub-Event', 'pull_request');
+      request.body = generatePullRequestEvent('opened', issueNumber, kDefaultBranchName,
+          repoName: 'engine', repoFullName: 'flutter/engine', login: 'skia-flutter-autoroll');
+
+      final Uint8List body = utf8.encode(request.body!) as Uint8List;
+      final Uint8List key = utf8.encode(keyString) as Uint8List;
+      final String hmac = getHmac(body, key);
+      request.headers.set('X-Hub-Signature', 'sha1=$hmac');
+      final RepositorySlug slug = RepositorySlug('flutter', 'engine');
+
+      when(pullRequestsService.listFiles(slug, issueNumber)).thenAnswer(
+        (_) => Stream<PullRequestFile>.value(
+          PullRequestFile()..filename = 'shell/platform/darwin/ios/framework/Source/boost.mm',
+        ),
+      );
+
+      when(issuesService.listCommentsByIssue(slug, issueNumber)).thenAnswer(
+        (_) => Stream<IssueComment>.value(
+          IssueComment()..body = 'some other comment',
+        ),
+      );
+
+      await tester.post(webhook);
+
+      verifyNever(issuesService.addLabelsToIssue(
+        slug,
+        issueNumber,
+        <String>['platform-ios'],
+      ));
+
+      verifyNever(issuesService.createComment(
+        slug,
+        issueNumber,
+        argThat(contains(config.missingTestsPullRequestMessageValue)),
+      ));
+
+      verifyNever(issuesService.addLabelsToIssue(
+        slug,
+        issueNumber,
+        <String>['needs tests'],
+      ));
+    });
+
     test('Engine labels PRs, no code files', () async {
       const int issueNumber = 123;
       request.headers.set('X-GitHub-Event', 'pull_request');
@@ -1554,6 +1742,60 @@
       )).called(1);
     });
 
+    group('Plugins does not comment and label if author is an autoroller account.', () {
+      Set<String> inputs = {
+        'engine-flutter-autoroll',
+        'skia-flutter-autoroll',
+        'dependabot',
+      };
+
+      for (String element in inputs) {
+        test('Plugins does not comment and label if author is $element.', () async {
+          const int issueNumber = 123;
+          request.headers.set('X-GitHub-Event', 'pull_request');
+          request.body = generatePullRequestEvent(
+            'opened',
+            issueNumber,
+            kDefaultBranchName,
+            repoName: 'plugins',
+            repoFullName: 'flutter/plugins',
+            login: element,
+          );
+          final Uint8List body = utf8.encode(request.body!) as Uint8List;
+          final Uint8List key = utf8.encode(keyString) as Uint8List;
+          final String hmac = getHmac(body, key);
+          request.headers.set('X-Hub-Signature', 'sha1=$hmac');
+          final RepositorySlug slug = RepositorySlug('flutter', 'plugins');
+
+          when(pullRequestsService.listFiles(slug, issueNumber)).thenAnswer(
+            (_) => Stream<PullRequestFile>.value(
+              PullRequestFile()..filename = 'packages/foo/foo_ios/ios/Classes/Foo.m',
+            ),
+          );
+
+          when(issuesService.listCommentsByIssue(slug, issueNumber)).thenAnswer(
+            (_) => Stream<IssueComment>.value(
+              IssueComment()..body = 'some other comment',
+            ),
+          );
+
+          await tester.post(webhook);
+
+          verifyNever(issuesService.createComment(
+            slug,
+            issueNumber,
+            argThat(contains(config.missingTestsPullRequestMessageValue)),
+          ));
+
+          verifyNever(issuesService.addLabelsToIssue(
+            slug,
+            issueNumber,
+            <String>['needs tests'],
+          ));
+        });
+      }
+    });
+
     test('Plugins apply no label or comment if pr is for release branches', () async {
       const int issueNumber = 123;
       request.headers.set('X-GitHub-Event', 'pull_request');