Use GitHub Actions compatible globbing for branches, tag, path filter (#22804) (#23740)

Backport #22804 by @ChristopherHX

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

Co-authored-by: ChristopherHX <christopher.homberger@web.de>
This commit is contained in:
Giteabot 2023-03-27 14:01:46 -04:00 committed by GitHub
parent 62afc0a727
commit 35039b8563
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -16,6 +16,7 @@ import (
"github.com/gobwas/glob" "github.com/gobwas/glob"
"github.com/nektos/act/pkg/jobparser" "github.com/nektos/act/pkg/jobparser"
"github.com/nektos/act/pkg/model" "github.com/nektos/act/pkg/model"
"github.com/nektos/act/pkg/workflowpattern"
) )
func ListWorkflows(commit *git.Commit) (git.Entries, error) { func ListWorkflows(commit *git.Commit) (git.Entries, error) {
@ -136,40 +137,94 @@ func matchPushEvent(commit *git.Commit, pushPayload *api.PushPayload, evt *jobpa
} }
matchTimes := 0 matchTimes := 0
hasBranchFilter := false
hasTagFilter := false
refName := git.RefName(pushPayload.Ref)
// all acts conditions should be satisfied // all acts conditions should be satisfied
for cond, vals := range evt.Acts { for cond, vals := range evt.Acts {
switch cond { switch cond {
case "branches", "tags": case "branches":
refShortName := git.RefName(pushPayload.Ref).ShortName() hasBranchFilter = true
for _, val := range vals { if !refName.IsBranch() {
if glob.MustCompile(val, '/').Match(refShortName) { break
matchTimes++ }
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": case "paths":
filesChanged, err := commit.GetFilesChangedSinceCommit(pushPayload.Before) filesChanged, err := commit.GetFilesChangedSinceCommit(pushPayload.Before)
if err != nil { if err != nil {
log.Error("GetFilesChangedSinceCommit [commit_sha1: %s]: %v", commit.ID.String(), err) log.Error("GetFilesChangedSinceCommit [commit_sha1: %s]: %v", commit.ID.String(), err)
} else { } else {
for _, val := range vals { patterns, err := workflowpattern.CompilePatterns(vals...)
matched := false if err != nil {
for _, file := range filesChanged { break
if glob.MustCompile(val, '/').Match(file) { }
matched = true if !workflowpattern.Skip(patterns, filesChanged, &workflowpattern.EmptyTraceWriter{}) {
break matchTimes++
} }
} }
if matched { case "paths-ignore":
matchTimes++ filesChanged, err := commit.GetFilesChangedSinceCommit(pushPayload.Before)
break 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: default:
log.Warn("push event unsupported condition %q", cond) 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) return matchTimes == len(evt.Acts)
} }
@ -221,30 +276,47 @@ func matchPullRequestEvent(commit *git.Commit, prPayload *api.PullRequestPayload
} }
} }
case "branches": case "branches":
refShortName := git.RefName(prPayload.PullRequest.Base.Ref).ShortName() refName := git.RefName(prPayload.PullRequest.Base.Ref)
for _, val := range vals { patterns, err := workflowpattern.CompilePatterns(vals...)
if glob.MustCompile(val, '/').Match(refShortName) { if err != nil {
matchTimes++ break
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": case "paths":
filesChanged, err := commit.GetFilesChangedSinceCommit(prPayload.PullRequest.Base.Ref) filesChanged, err := commit.GetFilesChangedSinceCommit(prPayload.PullRequest.Base.Ref)
if err != nil { if err != nil {
log.Error("GetFilesChangedSinceCommit [commit_sha1: %s]: %v", commit.ID.String(), err) log.Error("GetFilesChangedSinceCommit [commit_sha1: %s]: %v", commit.ID.String(), err)
} else { } else {
for _, val := range vals { patterns, err := workflowpattern.CompilePatterns(vals...)
matched := false if err != nil {
for _, file := range filesChanged { break
if glob.MustCompile(val, '/').Match(file) { }
matched = true if !workflowpattern.Skip(patterns, filesChanged, &workflowpattern.EmptyTraceWriter{}) {
break matchTimes++
} }
} }
if matched { case "paths-ignore":
matchTimes++ filesChanged, err := commit.GetFilesChangedSinceCommit(prPayload.PullRequest.Base.Ref)
break 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: default: