From 6840258c9593c0b8ffaf88af0e239d03ed2314d2 Mon Sep 17 00:00:00 2001 From: ChristopherHX Date: Mon, 27 Mar 2023 10:27:40 +0200 Subject: [PATCH] Use GitHub Actions compatible globbing for `branches`, `tag`, `path` filter (#22804) Replaces the current globbing library with a https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet compatible one. This adds support for - `paths-ignore`, `tags-ignore` and `branches-ignore` filters. - negative patterns in `paths`, `tags` and `branches` filters - using both `tags` and `paths` filter on the push event Original PR https://gitea.com/gitea/act/pulls/13. nektos/act PR https://github.com/nektos/act/pull/1618 for the workflowpattern package (It can take some months for it to appear in https://gitea.com/gitea/act) Related to https://github.com/go-gitea/gitea/issues/13539 --- modules/actions/workflows.go | 146 ++++++++++++++++++++++++++--------- 1 file changed, 109 insertions(+), 37 deletions(-) diff --git a/modules/actions/workflows.go b/modules/actions/workflows.go index 738026142b..1b8b6cc7ef 100644 --- a/modules/actions/workflows.go +++ b/modules/actions/workflows.go @@ -16,6 +16,7 @@ import ( "github.com/gobwas/glob" "github.com/nektos/act/pkg/jobparser" "github.com/nektos/act/pkg/model" + "github.com/nektos/act/pkg/workflowpattern" ) func ListWorkflows(commit *git.Commit) (git.Entries, error) { @@ -152,40 +153,94 @@ func matchPushEvent(commit *git.Commit, pushPayload *api.PushPayload, evt *jobpa } matchTimes := 0 + hasBranchFilter := false + hasTagFilter := false + refName := git.RefName(pushPayload.Ref) // all acts conditions should be satisfied for cond, vals := range evt.Acts { switch cond { - case "branches", "tags": - refShortName := git.RefName(pushPayload.Ref).ShortName() - for _, val := range vals { - if glob.MustCompile(val, '/').Match(refShortName) { - matchTimes++ - break - } + case "branches": + hasBranchFilter = true + if !refName.IsBranch() { + break + } + patterns, err := workflowpattern.CompilePatterns(vals...) + if err != nil { + break + } + if !workflowpattern.Skip(patterns, []string{refName.ShortName()}, &workflowpattern.EmptyTraceWriter{}) { + matchTimes++ + } + case "branches-ignore": + hasBranchFilter = true + if !refName.IsBranch() { + break + } + patterns, err := workflowpattern.CompilePatterns(vals...) + if err != nil { + break + } + if !workflowpattern.Filter(patterns, []string{refName.ShortName()}, &workflowpattern.EmptyTraceWriter{}) { + matchTimes++ + } + case "tags": + hasTagFilter = true + if !refName.IsTag() { + break + } + patterns, err := workflowpattern.CompilePatterns(vals...) + if err != nil { + break + } + if !workflowpattern.Skip(patterns, []string{refName.ShortName()}, &workflowpattern.EmptyTraceWriter{}) { + matchTimes++ + } + case "tags-ignore": + hasTagFilter = true + if !refName.IsTag() { + break + } + patterns, err := workflowpattern.CompilePatterns(vals...) + if err != nil { + break + } + if !workflowpattern.Filter(patterns, []string{refName.ShortName()}, &workflowpattern.EmptyTraceWriter{}) { + matchTimes++ } 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 - } + patterns, err := workflowpattern.CompilePatterns(vals...) + if err != nil { + break + } + if !workflowpattern.Skip(patterns, filesChanged, &workflowpattern.EmptyTraceWriter{}) { + matchTimes++ + } + } + case "paths-ignore": + filesChanged, err := commit.GetFilesChangedSinceCommit(pushPayload.Before) + if err != nil { + log.Error("GetFilesChangedSinceCommit [commit_sha1: %s]: %v", commit.ID.String(), err) + } else { + patterns, err := workflowpattern.CompilePatterns(vals...) + if err != nil { + break + } + if !workflowpattern.Filter(patterns, filesChanged, &workflowpattern.EmptyTraceWriter{}) { + matchTimes++ } } default: log.Warn("push event unsupported condition %q", cond) } } + // if both branch and tag filter are defined in the workflow only one needs to match + if hasBranchFilter && hasTagFilter { + matchTimes++ + } return matchTimes == len(evt.Acts) } @@ -237,30 +292,47 @@ func matchPullRequestEvent(commit *git.Commit, prPayload *api.PullRequestPayload } } case "branches": - refShortName := git.RefName(prPayload.PullRequest.Base.Ref).ShortName() - for _, val := range vals { - if glob.MustCompile(val, '/').Match(refShortName) { - matchTimes++ - break - } + refName := git.RefName(prPayload.PullRequest.Base.Ref) + patterns, err := workflowpattern.CompilePatterns(vals...) + if err != nil { + break + } + if !workflowpattern.Skip(patterns, []string{refName.ShortName()}, &workflowpattern.EmptyTraceWriter{}) { + matchTimes++ + } + case "branches-ignore": + refName := git.RefName(prPayload.PullRequest.Base.Ref) + patterns, err := workflowpattern.CompilePatterns(vals...) + if err != nil { + break + } + if !workflowpattern.Filter(patterns, []string{refName.ShortName()}, &workflowpattern.EmptyTraceWriter{}) { + matchTimes++ } 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 - } + patterns, err := workflowpattern.CompilePatterns(vals...) + if err != nil { + break + } + if !workflowpattern.Skip(patterns, filesChanged, &workflowpattern.EmptyTraceWriter{}) { + matchTimes++ + } + } + case "paths-ignore": + filesChanged, err := commit.GetFilesChangedSinceCommit(prPayload.PullRequest.Base.Ref) + if err != nil { + log.Error("GetFilesChangedSinceCommit [commit_sha1: %s]: %v", commit.ID.String(), err) + } else { + patterns, err := workflowpattern.CompilePatterns(vals...) + if err != nil { + break + } + if !workflowpattern.Filter(patterns, filesChanged, &workflowpattern.EmptyTraceWriter{}) { + matchTimes++ } } default: