diff --git a/app_dart/lib/src/request_handlers/github/webhook_subscription.dart b/app_dart/lib/src/request_handlers/github/webhook_subscription.dart index d7ddb8df5..a7c2e0642 100644 --- a/app_dart/lib/src/request_handlers/github/webhook_subscription.dart +++ b/app_dart/lib/src/request_handlers/github/webhook_subscription.dart @@ -199,11 +199,14 @@ final class GithubWebhookSubscription extends SubscriptionHandler { final result = await _processPullRequestClosed(pullRequestEvent); return result.toResponse(); case 'edited': - await _addCICDForRollers(pullRequestEvent); + if (pullRequestEvent.changes != null && + pullRequestEvent.changes!.base != null) { + await _addCICDForRollersAndMembers(pullRequestEvent); + } await _checkForTests(pullRequestEvent); break; case 'opened': - await _addCICDForRollers(pullRequestEvent); + await _addCICDForRollersAndMembers(pullRequestEvent); await _checkForTests(pullRequestEvent); await _tryReleaseApproval(pullRequestEvent); break; @@ -232,8 +235,10 @@ final class GithubWebhookSubscription extends SubscriptionHandler { case 'dequeued': await _respondToPullRequestDequeued(pullRequestEvent); break; - // Ignore the rest of the events. case 'synchronize': + await _addCICDForRollersAndMembers(pullRequestEvent); + break; + // Ignore the rest of the events. case 'ready_for_review': case 'unlabeled': case 'assigned': @@ -569,12 +574,17 @@ final class GithubWebhookSubscription extends SubscriptionHandler { ); } - Future _addCICDForRollers(PullRequestEvent pullRequestEvent) async { + Future _addCICDForRollersAndMembers( + PullRequestEvent pullRequestEvent, + ) async { final pr = pullRequestEvent.pullRequest!; final slug = pr.base!.repo!.slug(); - if (config.rollerAccounts.contains(pr.user!.login) && - config.supportedRepos.contains(slug)) { + final isRoller = config.rollerAccounts.contains(pr.user!.login); + final association = pr.authorAssociation; + final isOrgMember = association == 'MEMBER' || association == 'OWNER'; + + if (config.supportedRepos.contains(slug) && (isRoller || isOrgMember)) { final gitHubClient = await config.createGitHubClient(pullRequest: pr); await gitHubClient.issues.addLabelsToIssue(slug, pr.number!, ['CICD']); } diff --git a/app_dart/test/request_handlers/github/webhook_subscription_test.dart b/app_dart/test/request_handlers/github/webhook_subscription_test.dart index 57aac77ec..817a77b1f 100644 --- a/app_dart/test/request_handlers/github/webhook_subscription_test.dart +++ b/app_dart/test/request_handlers/github/webhook_subscription_test.dart @@ -408,6 +408,7 @@ void main() { number: issueNumber, baseRef: 'master', slug: Config.packagesSlug, + isOrgMember: false, ); tester.message = pushMessage; @@ -459,6 +460,7 @@ void main() { baseRef: 'master', slug: Config.packagesSlug, includeChanges: true, + isOrgMember: false, ); tester.message = pushMessage; @@ -531,6 +533,7 @@ void main() { action: 'opened', number: issueNumber, isDraft: true, + isOrgMember: false, ); var batchRequestCalled = false; @@ -935,6 +938,7 @@ void main() { const issueNumber = 123; tester.message = generateGithubWebhookMessage( + isOrgMember: false, action: 'opened', number: issueNumber, ); @@ -1064,6 +1068,7 @@ void main() { const issueNumber = 123; tester.message = generateGithubWebhookMessage( + isOrgMember: false, action: 'opened', number: issueNumber, ); @@ -1691,6 +1696,7 @@ void foo() { const issueNumber = 123; tester.message = generateGithubWebhookMessage( + isOrgMember: false, action: 'opened', number: issueNumber, baseRef: kReleaseBaseRef, @@ -1829,6 +1835,7 @@ void foo() { const issueNumber = 123; tester.message = generateGithubWebhookMessage( + isOrgMember: false, action: 'opened', number: issueNumber, baseRef: 'master', @@ -1865,6 +1872,7 @@ void foo() { const issueNumber = 123; tester.message = generateGithubWebhookMessage( + isOrgMember: false, action: 'opened', number: issueNumber, baseRef: 'master', @@ -1901,6 +1909,7 @@ void foo() { const issueNumber = 123; tester.message = generateGithubWebhookMessage( + isOrgMember: false, action: 'opened', number: issueNumber, baseRef: 'master', @@ -2331,6 +2340,7 @@ void foo() { const issueNumber = 123; tester.message = generateGithubWebhookMessage( + isOrgMember: false, action: 'opened', number: issueNumber, baseRef: kReleaseBaseRef, @@ -2553,6 +2563,7 @@ void foo() { const issueNumber = 123; tester.message = generateGithubWebhookMessage( + isOrgMember: false, action: 'opened', number: issueNumber, ); @@ -2667,6 +2678,7 @@ void foo() { tester.message = generateGithubWebhookMessage( action: 'synchronize', number: issueNumber, + isOrgMember: false, ); final mockRepositoriesService = MockRepositoriesService(); @@ -3712,6 +3724,24 @@ void foo() { expect(scheduler.triggerPresubmitTargetsCnt, 0); }); + test('opened PR with adds CICD label if author is MEMBER', () async { + tester.message = generateGithubWebhookMessage(action: 'opened'); + + await tester.post(webhook); + + verify(issuesService.addLabelsToIssue(Config.flutterSlug, 123, ['CICD'])); + }); + test('opened PR does not add CICD label if author is not MEMBER', () async { + tester.message = generateGithubWebhookMessage( + action: 'opened', + isOrgMember: false, + ); + + await tester.post(webhook); + + verifyNever(issuesService.addLabelsToIssue(Config.flutterSlug, 123, any)); + }); + test( 'labeled event with CICD label schedules tests on flutter/flutter', () async { @@ -3796,11 +3826,36 @@ void foo() { tester.message = generateGithubWebhookMessage( action: 'synchronize', withCicdLabel: true, + isOrgMember: false, ); await tester.post(webhook); expect(scheduler.triggerPresubmitTargetsCnt, 0); }, ); + + test('synchronize event adds CICD label if author is member', () async { + tester.message = generateGithubWebhookMessage( + action: 'synchronize', + isOrgMember: true, + ); + + await tester.post(webhook); + verify(issuesService.addLabelsToIssue(Config.flutterSlug, 123, ['CICD'])); + }); + test( + 'synchronize event does not add CICD label if author is not member', + () async { + tester.message = generateGithubWebhookMessage( + action: 'synchronize', + isOrgMember: false, + ); + + await tester.post(webhook); + verifyNever( + issuesService.addLabelsToIssue(Config.flutterSlug, 123, any), + ); + }, + ); }); } diff --git a/packages/cocoon_integration_test/lib/src/utilities/webhook_generators.dart b/packages/cocoon_integration_test/lib/src/utilities/webhook_generators.dart index 700343332..46759daf5 100644 --- a/packages/cocoon_integration_test/lib/src/utilities/webhook_generators.dart +++ b/packages/cocoon_integration_test/lib/src/utilities/webhook_generators.dart @@ -30,6 +30,7 @@ PushMessage generateGithubWebhookMessage({ bool withAutosubmit = false, bool withRevertOf = false, bool withCicdLabel = false, + bool isOrgMember = true, DateTime? closedAt, Iterable additionalLabels = const [], Map? labeledLabel, @@ -54,6 +55,7 @@ PushMessage generateGithubWebhookMessage({ withAutosubmit: withAutosubmit, withRevertOf: withRevertOf, withCicdLabel: withCicdLabel, + isOrgMember: isOrgMember, closedAt: closedAt, additionalLabels: additionalLabels, labeledLabel: labeledLabel, @@ -81,6 +83,7 @@ String _generatePullRequestEvent( required bool withAutosubmit, required bool withRevertOf, bool withCicdLabel = false, + bool isOrgMember = true, Iterable additionalLabels = const [], Map? labeledLabel, }) { @@ -463,7 +466,7 @@ String _generatePullRequestEvent( "href": "https://api.github.com/repos/${slug.fullName}/statuses/deadbeef" } }, - "author_association": "MEMBER", + "author_association": "${isOrgMember ? 'MEMBER' : 'CONTRIBUTOR'}", "draft" : $isDraft, "merged": $merged, "mergeable": $isMergeable,