Skip to content

Fix mismatch between hook events and github event types #24048

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Apr 12, 2023
222 changes: 198 additions & 24 deletions modules/actions/workflows.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,40 +115,60 @@ func detectMatched(commit *git.Commit, triggedEvent webhook_module.HookEventType
}

switch triggedEvent {
case webhook_module.HookEventCreate,
case // events with no activity types
webhook_module.HookEventCreate,
webhook_module.HookEventDelete,
webhook_module.HookEventFork,
webhook_module.HookEventIssueAssign,
webhook_module.HookEventIssueLabel,
webhook_module.HookEventIssueMilestone,
webhook_module.HookEventPullRequestAssign,
webhook_module.HookEventPullRequestLabel,
webhook_module.HookEventPullRequestMilestone,
webhook_module.HookEventPullRequestComment,
webhook_module.HookEventPullRequestReviewApproved,
webhook_module.HookEventPullRequestReviewRejected,
webhook_module.HookEventPullRequestReviewComment,
webhook_module.HookEventWiki,
webhook_module.HookEventRepository,
webhook_module.HookEventRelease,
webhook_module.HookEventPackage:
// FIXME: `wiki` event should match `gollum` event.
// See: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#gollum
webhook_module.HookEventWiki:
if len(evt.Acts()) != 0 {
log.Warn("Ignore unsupported %s event arguments %v", triggedEvent, evt.Acts())
}
// no special filter parameters for these events, just return true if name matched
return true

case webhook_module.HookEventPush:
case // push
webhook_module.HookEventPush:
return matchPushEvent(commit, payload.(*api.PushPayload), evt)

case webhook_module.HookEventIssues:
case // issues
webhook_module.HookEventIssues,
webhook_module.HookEventIssueAssign,
webhook_module.HookEventIssueLabel,
webhook_module.HookEventIssueMilestone:
return matchIssuesEvent(commit, payload.(*api.IssuePayload), evt)

case webhook_module.HookEventPullRequest, webhook_module.HookEventPullRequestSync:
case // issue_comment
webhook_module.HookEventIssueComment,
// `pull_request_comment` is same as `issue_comment`
// See: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_comment-use-issue_comment
webhook_module.HookEventPullRequestComment:
return matchIssueCommentEvent(commit, payload.(*api.IssueCommentPayload), evt)

case // pull_request
webhook_module.HookEventPullRequest,
webhook_module.HookEventPullRequestSync,
webhook_module.HookEventPullRequestAssign,
webhook_module.HookEventPullRequestLabel:
return matchPullRequestEvent(commit, payload.(*api.PullRequestPayload), evt)

case webhook_module.HookEventIssueComment:
return matchIssueCommentEvent(commit, payload.(*api.IssueCommentPayload), evt)
case // pull_request_review
webhook_module.HookEventPullRequestReviewApproved,
webhook_module.HookEventPullRequestReviewRejected:
return matchPullRequestReviewEvent(commit, payload.(*api.PullRequestPayload), evt)

case // pull
webhook_module.HookEventPullRequestReviewComment:
return matchPullRequestReviewCommentEvent(commit, payload.(*api.PullRequestPayload), evt)

case // release
webhook_module.HookEventRelease:
return matchReleaseEvent(commit, payload.(*api.ReleasePayload), evt)

case // registry_package
webhook_module.HookEventPackage:
return matchPackageEvent(commit, payload.(*api.PackagePayload), evt)

default:
log.Warn("unsupported event %q", triggedEvent)
Expand Down Expand Up @@ -265,8 +285,15 @@ func matchIssuesEvent(commit *git.Commit, issuePayload *api.IssuePayload, evt *j
for cond, vals := range evt.Acts() {
switch cond {
case "types":
action := issuePayload.Action
switch action {
case api.HookIssueLabelUpdated:
action = "labeled"
case api.HookIssueLabelCleared:
action = "unlabeled"
}
for _, val := range vals {
if glob.MustCompile(val, '/').Match(string(issuePayload.Action)) {
if glob.MustCompile(val, '/').Match(string(action)) {
matchTimes++
break
}
Expand All @@ -281,8 +308,9 @@ func matchIssuesEvent(commit *git.Commit, issuePayload *api.IssuePayload, evt *j
func matchPullRequestEvent(commit *git.Commit, prPayload *api.PullRequestPayload, evt *jobparser.Event) bool {
// with no special filter parameters
if len(evt.Acts()) == 0 {
// defaultly, only pull request opened and synchronized will trigger workflow
return prPayload.Action == api.HookIssueSynchronized || prPayload.Action == api.HookIssueOpened
// defaultly, only pull request `opened`, `reopened`` and `synchronized` will trigger workflow
// See: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request
return prPayload.Action == api.HookIssueSynchronized || prPayload.Action == api.HookIssueOpened || prPayload.Action == api.HookIssueReOpened
}

matchTimes := 0
Expand All @@ -291,8 +319,13 @@ func matchPullRequestEvent(commit *git.Commit, prPayload *api.PullRequestPayload
switch cond {
case "types":
action := prPayload.Action
if prPayload.Action == api.HookIssueSynchronized {
switch action {
case api.HookIssueSynchronized:
action = "synchronize"
case api.HookIssueLabelUpdated:
action = "labeled"
case api.HookIssueLabelCleared:
action = "unlabeled"
}
log.Trace("matching pull_request %s with %v", action, vals)
for _, val := range vals {
Expand Down Expand Up @@ -375,3 +408,144 @@ func matchIssueCommentEvent(commit *git.Commit, issueCommentPayload *api.IssueCo
}
return matchTimes == len(evt.Acts())
}

func matchPullRequestReviewEvent(commit *git.Commit, prPayload *api.PullRequestPayload, evt *jobparser.Event) bool {
// with no special filter parameters
if len(evt.Acts()) == 0 {
return true
}

matchTimes := 0
// all acts conditions should be satisfied
for cond, vals := range evt.Acts() {
switch cond {
case "types":
actions := make([]string, 0)
if prPayload.Action == api.HookIssueReviewed {
// the `reviewed` HookIssueAction can match the two activity types: `submitted` and `edited`
// See: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_review
actions = append(actions, "submitted", "edited")
}
// TODO: support the `dismissed` activity type

matched := false
for _, val := range vals {
for _, action := range actions {
if glob.MustCompile(val, '/').Match(action) {
matched = true
break
}
}
if matched {
break
}
}
if matched {
matchTimes++
}
default:
log.Warn("pull request review event unsupported condition %q", cond)
}
}
return matchTimes == len(evt.Acts())
}

func matchPullRequestReviewCommentEvent(commit *git.Commit, prPayload *api.PullRequestPayload, evt *jobparser.Event) bool {
// with no special filter parameters
if len(evt.Acts()) == 0 {
return true
}

matchTimes := 0
// all acts conditions should be satisfied
for cond, vals := range evt.Acts() {
switch cond {
case "types":
actions := make([]string, 0)
if prPayload.Action == api.HookIssueReviewed {
// the `reviewed` HookIssueAction can match the two activity types: `created` and `edited`
// See: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_review_comment
actions = append(actions, "created", "edited")
}
// TODO: support the `deleted` activity type

matched := false
for _, val := range vals {
for _, action := range actions {
if glob.MustCompile(val, '/').Match(action) {
matched = true
break
}
}
if matched {
break
}
}
if matched {
matchTimes++
}
default:
log.Warn("pull request review comment event unsupported condition %q", cond)
}
}
return matchTimes == len(evt.Acts())
}

func matchReleaseEvent(commit *git.Commit, payload *api.ReleasePayload, evt *jobparser.Event) bool {
// with no special filter parameters
if len(evt.Acts()) == 0 {
return true
}

matchTimes := 0
// all acts conditions should be satisfied
for cond, vals := range evt.Acts() {
switch cond {
case "types":
action := payload.Action
switch action {
case api.HookReleaseUpdated:
action = "edited"
}
for _, val := range vals {
if glob.MustCompile(val, '/').Match(string(action)) {
matchTimes++
break
}
}
default:
log.Warn("release event unsupported condition %q", cond)
}
}
return matchTimes == len(evt.Acts())
}

func matchPackageEvent(commit *git.Commit, payload *api.PackagePayload, evt *jobparser.Event) bool {
// with no special filter parameters
if len(evt.Acts()) == 0 {
return true
}

matchTimes := 0
// all acts conditions should be satisfied
for cond, vals := range evt.Acts() {
switch cond {
case "types":
action := payload.Action
switch action {
case api.HookPackageCreated:
action = "published"
// TODO: support the `updated` activity type
}
for _, val := range vals {
if glob.MustCompile(val, '/').Match(string(action)) {
matchTimes++
break
}
}
default:
log.Warn("package event unsupported condition %q", cond)
}
}
return matchTimes == len(evt.Acts())
}