From e7f0bcf8847330d646300b60d9fda119da7e97dc Mon Sep 17 00:00:00 2001
From: Zettat123 <zettat123@gmail.com>
Date: Thu, 23 Mar 2023 12:04:15 +0800
Subject: [PATCH] Improve workflow event triggers (#23613)

Follow #23037
Fix [#22598
comment](https://github.com/go-gitea/gitea/issues/22958#issuecomment-1475763042)

Workflows with `pull_request` trigger event can't be triggered by
`pull_request_sync` event. This PR adds the `canGithubEventMatch`
function to check if a Github event can match any Gitea event. If the
Github event matches a Gitea event, the related workflows should be
triggered.

---------

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
---
 modules/actions/github.go      |  53 ++++++++++++----
 modules/actions/github_test.go | 113 +++++++++++++++++++++++++++++++++
 modules/actions/workflows.go   |   2 +-
 3 files changed, 155 insertions(+), 13 deletions(-)
 create mode 100644 modules/actions/github_test.go

diff --git a/modules/actions/github.go b/modules/actions/github.go
index bcde9a0f55..1148554139 100644
--- a/modules/actions/github.go
+++ b/modules/actions/github.go
@@ -5,8 +5,6 @@ package actions
 
 import (
 	webhook_module "code.gitea.io/gitea/modules/webhook"
-
-	"github.com/nektos/act/pkg/jobparser"
 )
 
 const (
@@ -25,17 +23,48 @@ const (
 	githubEventPullRequestComment       = "pull_request_comment"
 )
 
-func convertFromGithubEvent(evt *jobparser.Event) string {
-	switch evt.Name {
-	case githubEventPullRequest, githubEventPullRequestTarget, githubEventPullRequestReview,
-		githubEventPullRequestReviewComment:
-		return string(webhook_module.HookEventPullRequest)
+// canGithubEventMatch check if the input Github event can match any Gitea event.
+func canGithubEventMatch(eventName string, triggedEvent webhook_module.HookEventType) bool {
+	switch eventName {
 	case githubEventRegistryPackage:
-		return string(webhook_module.HookEventPackage)
-	case githubEventCreate, githubEventDelete, githubEventFork, githubEventPush,
-		githubEventIssues, githubEventIssueComment, githubEventRelease, githubEventPullRequestComment:
-		fallthrough
+		return triggedEvent == webhook_module.HookEventPackage
+
+	case githubEventIssues:
+		switch triggedEvent {
+		case webhook_module.HookEventIssues,
+			webhook_module.HookEventIssueAssign,
+			webhook_module.HookEventIssueLabel,
+			webhook_module.HookEventIssueMilestone:
+			return true
+
+		default:
+			return false
+		}
+
+	case githubEventPullRequest, githubEventPullRequestTarget:
+		switch triggedEvent {
+		case webhook_module.HookEventPullRequest,
+			webhook_module.HookEventPullRequestSync,
+			webhook_module.HookEventPullRequestAssign,
+			webhook_module.HookEventPullRequestLabel:
+			return true
+
+		default:
+			return false
+		}
+
+	case githubEventPullRequestReview:
+		switch triggedEvent {
+		case webhook_module.HookEventPullRequestReviewApproved,
+			webhook_module.HookEventPullRequestReviewComment,
+			webhook_module.HookEventPullRequestReviewRejected:
+			return true
+
+		default:
+			return false
+		}
+
 	default:
-		return evt.Name
+		return eventName == string(triggedEvent)
 	}
 }
diff --git a/modules/actions/github_test.go b/modules/actions/github_test.go
new file mode 100644
index 0000000000..e7f4158ae2
--- /dev/null
+++ b/modules/actions/github_test.go
@@ -0,0 +1,113 @@
+// Copyright 2023 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package actions
+
+import (
+	"testing"
+
+	webhook_module "code.gitea.io/gitea/modules/webhook"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestCanGithubEventMatch(t *testing.T) {
+	testCases := []struct {
+		desc           string
+		eventName      string
+		triggeredEvent webhook_module.HookEventType
+		expected       bool
+	}{
+		// registry_package event
+		{
+			"registry_package matches",
+			githubEventRegistryPackage,
+			webhook_module.HookEventPackage,
+			true,
+		},
+		{
+			"registry_package cannot match",
+			githubEventRegistryPackage,
+			webhook_module.HookEventPush,
+			false,
+		},
+		// issues event
+		{
+			"issue matches",
+			githubEventIssues,
+			webhook_module.HookEventIssueLabel,
+			true,
+		},
+		{
+			"issue cannot match",
+			githubEventIssues,
+			webhook_module.HookEventIssueComment,
+			false,
+		},
+		// issue_comment event
+		{
+			"issue_comment matches",
+			githubEventIssueComment,
+			webhook_module.HookEventIssueComment,
+			true,
+		},
+		{
+			"issue_comment cannot match",
+			githubEventIssueComment,
+			webhook_module.HookEventIssues,
+			false,
+		},
+		// pull_request event
+		{
+			"pull_request matches",
+			githubEventPullRequest,
+			webhook_module.HookEventPullRequestSync,
+			true,
+		},
+		{
+			"pull_request cannot match",
+			githubEventPullRequest,
+			webhook_module.HookEventPullRequestComment,
+			false,
+		},
+		// pull_request_target event
+		{
+			"pull_request_target matches",
+			githubEventPullRequest,
+			webhook_module.HookEventPullRequest,
+			true,
+		},
+		{
+			"pull_request_target cannot match",
+			githubEventPullRequest,
+			webhook_module.HookEventPullRequestComment,
+			false,
+		},
+		// pull_request_review event
+		{
+			"pull_request_review matches",
+			githubEventPullRequestReview,
+			webhook_module.HookEventPullRequestReviewComment,
+			true,
+		},
+		{
+			"pull_request_review cannot match",
+			githubEventPullRequestReview,
+			webhook_module.HookEventPullRequestComment,
+			false,
+		},
+		// other events
+		{
+			"create event",
+			githubEventCreate,
+			webhook_module.HookEventCreate,
+			true,
+		},
+	}
+
+	for _, tc := range testCases {
+		t.Run(tc.desc, func(t *testing.T) {
+			assert.Equalf(t, tc.expected, canGithubEventMatch(tc.eventName, tc.triggeredEvent), "canGithubEventMatch(%v, %v)", tc.eventName, tc.triggeredEvent)
+		})
+	}
+}
diff --git a/modules/actions/workflows.go b/modules/actions/workflows.go
index 67c3b12427..738026142b 100644
--- a/modules/actions/workflows.go
+++ b/modules/actions/workflows.go
@@ -99,7 +99,7 @@ func DetectWorkflows(commit *git.Commit, triggedEvent webhook_module.HookEventTy
 }
 
 func detectMatched(commit *git.Commit, triggedEvent webhook_module.HookEventType, payload api.Payloader, evt *jobparser.Event) bool {
-	if convertFromGithubEvent(evt) != string(triggedEvent) {
+	if !canGithubEventMatch(evt.Name, triggedEvent) {
 		return false
 	}