From 2871ea08096cba15546f357d0ec473734ee9d8be Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 1 Feb 2023 13:32:46 +0800 Subject: [PATCH] Add more events details supports for actions (#22680) #21937 implemented only basic events based on name because of `act`'s limitation. So I sent a PR to parse all possible events details in https://gitea.com/gitea/act/pulls/11 and it merged. The ref documentation is https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows This PR depends on that and make more detail responses for `push` events and `pull_request` events. And it lefts more events there for future PRs. --------- Co-authored-by: Jason Song --- go.mod | 2 +- go.sum | 4 +- modules/actions/workflows.go | 154 +++++++++++++++++++++++++++- services/actions/notifier_helper.go | 2 +- 4 files changed, 154 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index 5ab0f4b27..b3d404032 100644 --- a/go.mod +++ b/go.mod @@ -284,7 +284,7 @@ replace github.com/shurcooL/vfsgen => github.com/lunny/vfsgen v0.0.0-20220105142 replace github.com/blevesearch/zapx/v15 v15.3.6 => github.com/zeripath/zapx/v15 v15.3.6-alignment-fix -replace github.com/nektos/act => gitea.com/gitea/act v0.234.0 +replace github.com/nektos/act => gitea.com/gitea/act v0.234.2-0.20230131074955-e46ede1b1744 exclude github.com/gofrs/uuid v3.2.0+incompatible diff --git a/go.sum b/go.sum index 12042dd6f..864ddff1c 100644 --- a/go.sum +++ b/go.sum @@ -70,8 +70,8 @@ codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570/go.mod h1:IIAjsi dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 h1:cliQ4HHsCo6xi2oWZYKWW4bly/Ory9FuTpFPRxj/mAg= git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078/go.mod h1:g/V2Hjas6Z1UHUp4yIx6bATpNzJ7DYtD0FG3+xARWxs= -gitea.com/gitea/act v0.234.0 h1:gWgMPMKdNcMrp/o2CF/SyVKiiJLBFl+xmzfvoHCpykU= -gitea.com/gitea/act v0.234.0/go.mod h1:2C/WbTalu1VPNgbVaZJaZDzlOtAKqkXJhdOClxkMy14= +gitea.com/gitea/act v0.234.2-0.20230131074955-e46ede1b1744 h1:cqzKmGlX0wynSXO04NILpL25eBGwogDrKpkkbwmIpj4= +gitea.com/gitea/act v0.234.2-0.20230131074955-e46ede1b1744/go.mod h1:2C/WbTalu1VPNgbVaZJaZDzlOtAKqkXJhdOClxkMy14= gitea.com/go-chi/binding v0.0.0-20221013104517-b29891619681 h1:MMSPgnVULVwV9kEBgvyEUhC9v/uviZ55hPJEMjpbNR4= gitea.com/go-chi/binding v0.0.0-20221013104517-b29891619681/go.mod h1:77TZu701zMXWJFvB8gvTbQ92zQ3DQq/H7l5wAEjQRKc= gitea.com/go-chi/cache v0.0.0-20210110083709-82c4c9ce2d5e/go.mod h1:k2V/gPDEtXGjjMGuBJiapffAXTv76H4snSmlJRLUhH0= diff --git a/modules/actions/workflows.go b/modules/actions/workflows.go index d340a1aa6..c1c8e71f5 100644 --- a/modules/actions/workflows.go +++ b/modules/actions/workflows.go @@ -10,8 +10,11 @@ import ( "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" + api "code.gitea.io/gitea/modules/structs" webhook_module "code.gitea.io/gitea/modules/webhook" + "github.com/gobwas/glob" + "github.com/nektos/act/pkg/jobparser" "github.com/nektos/act/pkg/model" ) @@ -41,7 +44,7 @@ func ListWorkflows(commit *git.Commit) (git.Entries, error) { return ret, nil } -func DetectWorkflows(commit *git.Commit, event webhook_module.HookEventType) (map[string][]byte, error) { +func DetectWorkflows(commit *git.Commit, triggedEvent webhook_module.HookEventType, payload api.Payloader) (map[string][]byte, error) { entries, err := ListWorkflows(commit) if err != nil { return nil, err @@ -63,13 +66,156 @@ func DetectWorkflows(commit *git.Commit, event webhook_module.HookEventType) (ma log.Warn("ignore invalid workflow %q: %v", entry.Name(), err) continue } - for _, e := range workflow.On() { - if e == event.Event() { + events, err := jobparser.ParseRawOn(&workflow.RawOn) + if err != nil { + log.Warn("ignore invalid workflow %q: %v", entry.Name(), err) + continue + } + for _, evt := range events { + if evt.Name != triggedEvent.Event() { + continue + } + + if detectMatched(commit, triggedEvent, payload, evt) { workflows[entry.Name()] = content - break } } } return workflows, nil } + +func detectMatched(commit *git.Commit, triggedEvent webhook_module.HookEventType, payload api.Payloader, evt *jobparser.Event) bool { + if len(evt.Acts) == 0 { + return true + } + + switch triggedEvent { + case webhook_module.HookEventCreate: + fallthrough + case webhook_module.HookEventDelete: + fallthrough + case webhook_module.HookEventFork: + log.Warn("unsupported event %q", triggedEvent.Event()) + return false + case webhook_module.HookEventPush: + pushPayload := payload.(*api.PushPayload) + matchTimes := 0 + // all acts conditions should be satisfied + for cond, vals := range evt.Acts { + switch cond { + case "branches", "tags": + for _, val := range vals { + if glob.MustCompile(val, '/').Match(pushPayload.Ref) { + matchTimes++ + break + } + } + case "paths": + filesChanged, err := commit.GetFilesChangedSinceCommit(pushPayload.Before) + if err != nil { + log.Error("GetFilesChangedSinceCommit [commit_sha1: %s]: %v", commit.ID.String(), err) + } else { + for _, val := range vals { + matched := false + for _, file := range filesChanged { + if glob.MustCompile(val, '/').Match(file) { + matched = true + break + } + } + if matched { + matchTimes++ + break + } + } + } + default: + log.Warn("unsupported condition %q", cond) + } + } + return matchTimes == len(evt.Acts) + + case webhook_module.HookEventIssues: + fallthrough + case webhook_module.HookEventIssueAssign: + fallthrough + case webhook_module.HookEventIssueLabel: + fallthrough + case webhook_module.HookEventIssueMilestone: + fallthrough + case webhook_module.HookEventIssueComment: + fallthrough + case webhook_module.HookEventPullRequest: + prPayload := payload.(*api.PullRequestPayload) + matchTimes := 0 + // all acts conditions should be satisfied + for cond, vals := range evt.Acts { + switch cond { + case "types": + for _, val := range vals { + if glob.MustCompile(val, '/').Match(string(prPayload.Action)) { + matchTimes++ + break + } + } + case "branches": + for _, val := range vals { + if glob.MustCompile(val, '/').Match(prPayload.PullRequest.Base.Ref) { + matchTimes++ + break + } + } + case "paths": + filesChanged, err := commit.GetFilesChangedSinceCommit(prPayload.PullRequest.Base.Ref) + if err != nil { + log.Error("GetFilesChangedSinceCommit [commit_sha1: %s]: %v", commit.ID.String(), err) + } else { + for _, val := range vals { + matched := false + for _, file := range filesChanged { + if glob.MustCompile(val, '/').Match(file) { + matched = true + break + } + } + if matched { + matchTimes++ + break + } + } + } + default: + log.Warn("unsupported condition %q", cond) + } + } + return matchTimes == len(evt.Acts) + case webhook_module.HookEventPullRequestAssign: + fallthrough + case webhook_module.HookEventPullRequestLabel: + fallthrough + case webhook_module.HookEventPullRequestMilestone: + fallthrough + case webhook_module.HookEventPullRequestComment: + fallthrough + case webhook_module.HookEventPullRequestReviewApproved: + fallthrough + case webhook_module.HookEventPullRequestReviewRejected: + fallthrough + case webhook_module.HookEventPullRequestReviewComment: + fallthrough + case webhook_module.HookEventPullRequestSync: + fallthrough + case webhook_module.HookEventWiki: + fallthrough + case webhook_module.HookEventRepository: + fallthrough + case webhook_module.HookEventRelease: + fallthrough + case webhook_module.HookEventPackage: + fallthrough + default: + log.Warn("unsupported event %q", triggedEvent.Event()) + } + return false +} diff --git a/services/actions/notifier_helper.go b/services/actions/notifier_helper.go index 9c9fc644c..5b8f6bfdf 100644 --- a/services/actions/notifier_helper.go +++ b/services/actions/notifier_helper.go @@ -137,7 +137,7 @@ func notify(ctx context.Context, input *notifyInput) error { return fmt.Errorf("gitRepo.GetCommit: %w", err) } - workflows, err := actions_module.DetectWorkflows(commit, input.Event) + workflows, err := actions_module.DetectWorkflows(commit, input.Event, input.Payload) if err != nil { return fmt.Errorf("DetectWorkflows: %w", err) }