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: