Skip to content

Commit 893c97d

Browse files
authored
Fix mismatch between hook events and github event types (#24048) (#24091)
Backport #24048 Some workflow trigger events can have multiple activity types, such as `issues` and `pull_request`, and user can specify which types can trigger the workflow. See GitHub documentation: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows Now some hook events cannot match the workflow trigger events correctly because we don't check the activity types. For example, `pull_request_label` is an individual hook event. But there isn't a `pull_request_label` workflow trigger event, we can only use `pull_request` event's `label` activity type. If we don't check the activity types, the workflows without the `label` activity type may be triggered by the `pull_request_label` event by mistake. We need to improve the match logic. - [x] [`issues` ](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#issues) - [x] [`issue_comment`](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#issue_comment) - [x] [`pull_request`](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request) - [x] [`pull_request_review`](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_review) - [x] [`pull_request_review_comment`](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_review_comment) - [x] [`release`](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#release) - [x] [`registry_package`](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#registry_package)
1 parent 447fa67 commit 893c97d

File tree

2 files changed

+368
-25
lines changed

2 files changed

+368
-25
lines changed

modules/actions/workflows.go

+257-25
Original file line numberDiff line numberDiff line change
@@ -99,40 +99,60 @@ func detectMatched(commit *git.Commit, triggedEvent webhook_module.HookEventType
9999
}
100100

101101
switch triggedEvent {
102-
case webhook_module.HookEventCreate,
102+
case // events with no activity types
103+
webhook_module.HookEventCreate,
103104
webhook_module.HookEventDelete,
104105
webhook_module.HookEventFork,
105-
webhook_module.HookEventIssueAssign,
106-
webhook_module.HookEventIssueLabel,
107-
webhook_module.HookEventIssueMilestone,
108-
webhook_module.HookEventPullRequestAssign,
109-
webhook_module.HookEventPullRequestLabel,
110-
webhook_module.HookEventPullRequestMilestone,
111-
webhook_module.HookEventPullRequestComment,
112-
webhook_module.HookEventPullRequestReviewApproved,
113-
webhook_module.HookEventPullRequestReviewRejected,
114-
webhook_module.HookEventPullRequestReviewComment,
115-
webhook_module.HookEventWiki,
116-
webhook_module.HookEventRepository,
117-
webhook_module.HookEventRelease,
118-
webhook_module.HookEventPackage:
106+
// FIXME: `wiki` event should match `gollum` event
107+
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#gollum
108+
webhook_module.HookEventWiki:
119109
if len(evt.Acts()) != 0 {
120110
log.Warn("Ignore unsupported %s event arguments %v", triggedEvent, evt.Acts())
121111
}
122112
// no special filter parameters for these events, just return true if name matched
123113
return true
124114

125-
case webhook_module.HookEventPush:
115+
case // push
116+
webhook_module.HookEventPush:
126117
return matchPushEvent(commit, payload.(*api.PushPayload), evt)
127118

128-
case webhook_module.HookEventIssues:
119+
case // issues
120+
webhook_module.HookEventIssues,
121+
webhook_module.HookEventIssueAssign,
122+
webhook_module.HookEventIssueLabel,
123+
webhook_module.HookEventIssueMilestone:
129124
return matchIssuesEvent(commit, payload.(*api.IssuePayload), evt)
130125

131-
case webhook_module.HookEventPullRequest, webhook_module.HookEventPullRequestSync:
126+
case // issue_comment
127+
webhook_module.HookEventIssueComment,
128+
// `pull_request_comment` is same as `issue_comment`
129+
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_comment-use-issue_comment
130+
webhook_module.HookEventPullRequestComment:
131+
return matchIssueCommentEvent(commit, payload.(*api.IssueCommentPayload), evt)
132+
133+
case // pull_request
134+
webhook_module.HookEventPullRequest,
135+
webhook_module.HookEventPullRequestSync,
136+
webhook_module.HookEventPullRequestAssign,
137+
webhook_module.HookEventPullRequestLabel:
132138
return matchPullRequestEvent(commit, payload.(*api.PullRequestPayload), evt)
133139

134-
case webhook_module.HookEventIssueComment:
135-
return matchIssueCommentEvent(commit, payload.(*api.IssueCommentPayload), evt)
140+
case // pull_request_review
141+
webhook_module.HookEventPullRequestReviewApproved,
142+
webhook_module.HookEventPullRequestReviewRejected:
143+
return matchPullRequestReviewEvent(commit, payload.(*api.PullRequestPayload), evt)
144+
145+
case // pull_request_review_comment
146+
webhook_module.HookEventPullRequestReviewComment:
147+
return matchPullRequestReviewCommentEvent(commit, payload.(*api.PullRequestPayload), evt)
148+
149+
case // release
150+
webhook_module.HookEventRelease:
151+
return matchReleaseEvent(commit, payload.(*api.ReleasePayload), evt)
152+
153+
case // registry_package
154+
webhook_module.HookEventPackage:
155+
return matchPackageEvent(commit, payload.(*api.PackagePayload), evt)
136156

137157
default:
138158
log.Warn("unsupported event %q", triggedEvent)
@@ -249,8 +269,24 @@ func matchIssuesEvent(commit *git.Commit, issuePayload *api.IssuePayload, evt *j
249269
for cond, vals := range evt.Acts() {
250270
switch cond {
251271
case "types":
272+
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#issues
273+
// Actions with the same name:
274+
// opened, edited, closed, reopened, assigned, unassigned, milestoned, demilestoned
275+
// Actions need to be converted:
276+
// label_updated -> labeled
277+
// label_cleared -> unlabeled
278+
// Unsupported activity types:
279+
// deleted, transferred, pinned, unpinned, locked, unlocked
280+
281+
action := issuePayload.Action
282+
switch action {
283+
case api.HookIssueLabelUpdated:
284+
action = "labeled"
285+
case api.HookIssueLabelCleared:
286+
action = "unlabeled"
287+
}
252288
for _, val := range vals {
253-
if glob.MustCompile(val, '/').Match(string(issuePayload.Action)) {
289+
if glob.MustCompile(val, '/').Match(string(action)) {
254290
matchTimes++
255291
break
256292
}
@@ -265,18 +301,34 @@ func matchIssuesEvent(commit *git.Commit, issuePayload *api.IssuePayload, evt *j
265301
func matchPullRequestEvent(commit *git.Commit, prPayload *api.PullRequestPayload, evt *jobparser.Event) bool {
266302
// with no special filter parameters
267303
if len(evt.Acts()) == 0 {
268-
// defaultly, only pull request opened and synchronized will trigger workflow
269-
return prPayload.Action == api.HookIssueSynchronized || prPayload.Action == api.HookIssueOpened
304+
// defaultly, only pull request `opened`, `reopened` and `synchronized` will trigger workflow
305+
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request
306+
return prPayload.Action == api.HookIssueSynchronized || prPayload.Action == api.HookIssueOpened || prPayload.Action == api.HookIssueReOpened
270307
}
271308

272309
matchTimes := 0
273310
// all acts conditions should be satisfied
274311
for cond, vals := range evt.Acts() {
275312
switch cond {
276313
case "types":
314+
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request
315+
// Actions with the same name:
316+
// opened, edited, closed, reopened, assigned, unassigned
317+
// Actions need to be converted:
318+
// synchronized -> synchronize
319+
// label_updated -> labeled
320+
// label_cleared -> unlabeled
321+
// Unsupported activity types:
322+
// converted_to_draft, ready_for_review, locked, unlocked, review_requested, review_request_removed, auto_merge_enabled, auto_merge_disabled
323+
277324
action := prPayload.Action
278-
if prPayload.Action == api.HookIssueSynchronized {
325+
switch action {
326+
case api.HookIssueSynchronized:
279327
action = "synchronize"
328+
case api.HookIssueLabelUpdated:
329+
action = "labeled"
330+
case api.HookIssueLabelCleared:
331+
action = "unlabeled"
280332
}
281333
log.Trace("matching pull_request %s with %v", action, vals)
282334
for _, val := range vals {
@@ -347,14 +399,194 @@ func matchIssueCommentEvent(commit *git.Commit, issueCommentPayload *api.IssueCo
347399
for cond, vals := range evt.Acts() {
348400
switch cond {
349401
case "types":
402+
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#issue_comment
403+
// Actions with the same name:
404+
// created, edited, deleted
405+
// Actions need to be converted:
406+
// NONE
407+
// Unsupported activity types:
408+
// NONE
409+
350410
for _, val := range vals {
351411
if glob.MustCompile(val, '/').Match(string(issueCommentPayload.Action)) {
352412
matchTimes++
353413
break
354414
}
355415
}
356416
default:
357-
log.Warn("issue comment unsupported condition %q", cond)
417+
log.Warn("issue comment event unsupported condition %q", cond)
418+
}
419+
}
420+
return matchTimes == len(evt.Acts())
421+
}
422+
423+
func matchPullRequestReviewEvent(commit *git.Commit, prPayload *api.PullRequestPayload, evt *jobparser.Event) bool {
424+
// with no special filter parameters
425+
if len(evt.Acts()) == 0 {
426+
return true
427+
}
428+
429+
matchTimes := 0
430+
// all acts conditions should be satisfied
431+
for cond, vals := range evt.Acts() {
432+
switch cond {
433+
case "types":
434+
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_review
435+
// Activity types with the same name:
436+
// NONE
437+
// Activity types need to be converted:
438+
// reviewed -> submitted
439+
// reviewed -> edited
440+
// Unsupported activity types:
441+
// dismissed
442+
443+
actions := make([]string, 0)
444+
if prPayload.Action == api.HookIssueReviewed {
445+
// the `reviewed` HookIssueAction can match the two activity types: `submitted` and `edited`
446+
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_review
447+
actions = append(actions, "submitted", "edited")
448+
}
449+
450+
matched := false
451+
for _, val := range vals {
452+
for _, action := range actions {
453+
if glob.MustCompile(val, '/').Match(action) {
454+
matched = true
455+
break
456+
}
457+
}
458+
if matched {
459+
break
460+
}
461+
}
462+
if matched {
463+
matchTimes++
464+
}
465+
default:
466+
log.Warn("pull request review event unsupported condition %q", cond)
467+
}
468+
}
469+
return matchTimes == len(evt.Acts())
470+
}
471+
472+
func matchPullRequestReviewCommentEvent(commit *git.Commit, prPayload *api.PullRequestPayload, evt *jobparser.Event) bool {
473+
// with no special filter parameters
474+
if len(evt.Acts()) == 0 {
475+
return true
476+
}
477+
478+
matchTimes := 0
479+
// all acts conditions should be satisfied
480+
for cond, vals := range evt.Acts() {
481+
switch cond {
482+
case "types":
483+
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_review_comment
484+
// Activity types with the same name:
485+
// NONE
486+
// Activity types need to be converted:
487+
// reviewed -> created
488+
// reviewed -> edited
489+
// Unsupported activity types:
490+
// deleted
491+
492+
actions := make([]string, 0)
493+
if prPayload.Action == api.HookIssueReviewed {
494+
// the `reviewed` HookIssueAction can match the two activity types: `created` and `edited`
495+
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_review_comment
496+
actions = append(actions, "created", "edited")
497+
}
498+
499+
matched := false
500+
for _, val := range vals {
501+
for _, action := range actions {
502+
if glob.MustCompile(val, '/').Match(action) {
503+
matched = true
504+
break
505+
}
506+
}
507+
if matched {
508+
break
509+
}
510+
}
511+
if matched {
512+
matchTimes++
513+
}
514+
default:
515+
log.Warn("pull request review comment event unsupported condition %q", cond)
516+
}
517+
}
518+
return matchTimes == len(evt.Acts())
519+
}
520+
521+
func matchReleaseEvent(commit *git.Commit, payload *api.ReleasePayload, evt *jobparser.Event) bool {
522+
// with no special filter parameters
523+
if len(evt.Acts()) == 0 {
524+
return true
525+
}
526+
527+
matchTimes := 0
528+
// all acts conditions should be satisfied
529+
for cond, vals := range evt.Acts() {
530+
switch cond {
531+
case "types":
532+
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#release
533+
// Activity types with the same name:
534+
// published
535+
// Activity types need to be converted:
536+
// updated -> edited
537+
// Unsupported activity types:
538+
// unpublished, created, deleted, prereleased, released
539+
540+
action := payload.Action
541+
switch action {
542+
case api.HookReleaseUpdated:
543+
action = "edited"
544+
}
545+
for _, val := range vals {
546+
if glob.MustCompile(val, '/').Match(string(action)) {
547+
matchTimes++
548+
break
549+
}
550+
}
551+
default:
552+
log.Warn("release event unsupported condition %q", cond)
553+
}
554+
}
555+
return matchTimes == len(evt.Acts())
556+
}
557+
558+
func matchPackageEvent(commit *git.Commit, payload *api.PackagePayload, evt *jobparser.Event) bool {
559+
// with no special filter parameters
560+
if len(evt.Acts()) == 0 {
561+
return true
562+
}
563+
564+
matchTimes := 0
565+
// all acts conditions should be satisfied
566+
for cond, vals := range evt.Acts() {
567+
switch cond {
568+
case "types":
569+
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#registry_package
570+
// Activity types with the same name:
571+
// NONE
572+
// Activity types need to be converted:
573+
// created -> published
574+
// Unsupported activity types:
575+
// updated
576+
577+
action := payload.Action
578+
switch action {
579+
case api.HookPackageCreated:
580+
action = "published"
581+
}
582+
for _, val := range vals {
583+
if glob.MustCompile(val, '/').Match(string(action)) {
584+
matchTimes++
585+
break
586+
}
587+
}
588+
default:
589+
log.Warn("package event unsupported condition %q", cond)
358590
}
359591
}
360592
return matchTimes == len(evt.Acts())

0 commit comments

Comments
 (0)