mirror of
https://codeberg.org/forgejo/forgejo
synced 2025-07-02 03:32:54 +02:00
## Checklist - [x] go to the last cherry-pick PR (forgejo/forgejo#8040) to figure out how far it went: [gitea@d5bbaee64e](d5bbaee64e
) - [x] cherry-pick and open PR (forgejo/forgejo#8198) - [ ] have the PR pass the CI - end-to-end (specially important if there are actions related changes) - [ ] add `run-end-to-end` label - [ ] check the result - [ ] write release notes - [ ] assign reviewers - [ ] 48h later, last call - merge 1 hour after the last call ## Legend - ❓ - No decision about the commit has been made. - 🍒 - The commit has been cherry picked. - ⏩ - The commit has been skipped. - 💡 - The commit has been skipped, but should be ported to Forgejo. - ✍️ - The commit has been skipped, and a port to Forgejo already exists. ## Commits - 🍒 [`gitea`](17cfae82a5
) -> [`forgejo`](6397da88d3
) Hide href attribute of a tag if there is no target_url ([gitea#34556](https://github.com/go-gitea/gitea/pull/34556)) - 🍒 [`gitea`](b408bf2f0b
) -> [`forgejo`](46bc899d57
) Fix: skip paths check on tag push events in workflows ([gitea#34602](https://github.com/go-gitea/gitea/pull/34602)) - 🍒 [`gitea`](9165ea8713
) -> [`forgejo`](04332f31bf
) Only activity tab needs heatmap data loading ([gitea#34652](https://github.com/go-gitea/gitea/pull/34652)) - 🍒 [`gitea`](3f7dbbdaf1
) -> [`forgejo`](2a9019fd04
) Small fix in Pull Requests page ([gitea#34612](https://github.com/go-gitea/gitea/pull/34612)) - 🍒 [`gitea`](497b83b75d
) -> [`forgejo`](9a83cc7bad
) Fix migration pull request title too long ([gitea#34577](https://github.com/go-gitea/gitea/pull/34577)) ## TODO - 💡 [`gitea`](6b8b580218
) Refactor container and UI ([gitea#34736](https://github.com/go-gitea/gitea/pull/34736)) Packages: Fix for container, needs careful merge. ------ - 💡 [`gitea`](bbee652e29
) Prevent duplicate form submissions when creating forks ([gitea#34714](https://github.com/go-gitea/gitea/pull/34714)) Fork: Fix, needs careful merge. ------ - 💡 [`gitea`](d21ce9fa07
) Improve the performance when detecting the file editable ([gitea#34653](https://github.com/go-gitea/gitea/pull/34653)) LFS: Performance improvement - needs careful merge. ------ - 💡 [`gitea`](8fed27bf6a
) Fix various problems ([gitea#34708](https://github.com/go-gitea/gitea/pull/34708)) Various: Fixes, tests missing. ------ - 💡 [`gitea`](c9505a26b9
) Improve instance wide ssh commit signing ([gitea#34341](https://github.com/go-gitea/gitea/pull/34341)) CodeSign: Nice feature - needs careful merge. ------ - 💡 [`gitea`](fbc3796f9e
) Fix pull requests API convert panic when head repository is deleted. ([gitea#34685](https://github.com/go-gitea/gitea/pull/34685)) Pull: Fix, needs careful merge. ------ - 💡 [`gitea`](1610a63bfd
) Fix commit message rendering and some UI problems ([gitea#34680](https://github.com/go-gitea/gitea/pull/34680)) Various Fixes - needs carefull merge. ------ - 💡 [`gitea`](0082cb51fa
) Fix last admin check when syncing users ([gitea#34649](https://github.com/go-gitea/gitea/pull/34649)) oidc: fix "first user is always admin". Needs careful merge. ------ - 💡 [`gitea`](c6b2cbd75d
) Fix footnote jump behavior on the issue page. ([gitea#34621](https://github.com/go-gitea/gitea/pull/34621)) Issues: Fix Markdown rendering. Needs carefull merge ------ - 💡 [`gitea`](7a59f5a825
) Ignore "Close" error when uploading container blob ([gitea#34620](https://github.com/go-gitea/gitea/pull/34620)) No issue, no test. ------ - 💡 [`gitea`](6d0b24064a
) Keeping consistent between UI and API about combined commit status state and fix some bugs ([gitea#34562](https://github.com/go-gitea/gitea/pull/34562)) Next PR in Commit-Status story. ------ - 💡 [`gitea`](f6041441ee
) Refactor FindOrgOptions to use enum instead of bool, fix membership visibility ([gitea#34629](https://github.com/go-gitea/gitea/pull/34629)) Just for a common sense here: How should I consider refactorings? ------ - 💡 [`gitea`](cc942e2a86
) Fix GetUsersByEmails ([gitea#34643](https://github.com/go-gitea/gitea/pull/34643)) User: Seems to fix email validation - but seems not to be finished. ------ - 💡 [`gitea`](7fa5a88831
) Add `--color-logo` for text that should match logo color ([gitea#34639](https://github.com/go-gitea/gitea/pull/34639)) UI: Nice idea - can we adapt this? ------ - 💡 [`gitea`](47d69b7749
) Validate hex colors when creating/editing labels ([gitea#34623](https://github.com/go-gitea/gitea/pull/34623)) Label: Color validation but needs careful merge. ------ - 💡 [`gitea`](108db0b04f
) Fix possible pull request broken when leave the page immediately after clicking the update button ([gitea#34509](https://github.com/go-gitea/gitea/pull/34509)) Nice fix for a bug hard to trace down. Needs careful merge & think about whether a test is possible. ------ - 💡 [`gitea`](79cc369892
) Fix issue label delete incorrect labels webhook payload ([gitea#34575](https://github.com/go-gitea/gitea/pull/34575)) Small fix but would expect a test, showing what was fixed. ------ - 💡 [`gitea`](fe57ee3074
) fixed incorrect page navigation with up and down arrow on last item of dashboard repos ([gitea#34570](https://github.com/go-gitea/gitea/pull/34570)) Small & simple - but tests are missing. ------ - 💡 [`gitea`](4e471487fb
) Remove unnecessary duplicate code ([gitea#34552](https://github.com/go-gitea/gitea/pull/34552)) Fix arround "Split GetLatestCommitStatus". ------ - 💡 [`gitea`](c5e78fc7ad
) Do not mutate incoming options to SearchRepositoryByName ([gitea#34553](https://github.com/go-gitea/gitea/pull/34553)) Large refactoring to simplify options handling. But needs careful merge. ------ - 💡 [`gitea`](f48c0135a6
) Fix/improve avatar sync from LDAP ([gitea#34573](https://github.com/go-gitea/gitea/pull/34573)) Nice fix but needs test. ------ - 💡 [`gitea`](e8d8984f7c
) Fix some trivial problems ([gitea#34579](https://github.com/go-gitea/gitea/pull/34579)) Various fixes, tests missing. ------ ## Skipped - ⏩ [`gitea`](637070e07b
) Fix container range bug ([gitea#34725](https://github.com/go-gitea/gitea/pull/34725)) ------ - ⏩ [`gitea`](0d3e9956cd
) [skip ci] Updated translations via Crowdin ------ - ⏩ [`gitea`](28debdbe00
) [skip ci] Updated translations via Crowdin ------ - ⏩ [`gitea`](dcc9206a59
) Raise minimum Node.js version to 20, test on 24 ([gitea#34713](https://github.com/go-gitea/gitea/pull/34713)) ------ - ⏩ [`gitea`](bc28654b49
) [skip ci] Updated translations via Crowdin ------ - ⏩ [`gitea`](65986f423f
) Refactor embedded assets and drop unnecessary dependencies ([gitea#34692](https://github.com/go-gitea/gitea/pull/34692)) ------ - ⏩ [`gitea`](18bafcc378
) Bump minimum go version to 1.24.4 ([gitea#34699](https://github.com/go-gitea/gitea/pull/34699)) ------ - ⏩ [`gitea`](8d135ef5cf
) Update JS deps ([gitea#34701](https://github.com/go-gitea/gitea/pull/34701)) ------ - ⏩ [`gitea`](d5893ee260
) Fix markdown wrap ([gitea#34697](https://github.com/go-gitea/gitea/pull/34697)) - gitea UI specific specific ------ - ⏩ [`gitea`](06ccb3a1d4
) [skip ci] Updated translations via Crowdin ------ - ⏩ [`gitea`](94db956e31
) frontport changelog ([gitea#34689](https://github.com/go-gitea/gitea/pull/34689)) ------ - ⏩ [`gitea`](d5afdccde8
) [skip ci] Updated translations via Crowdin ------ - ⏩ [`gitea`](e9f5105e95
) Migrate to urfave v3 ([gitea#34510](https://github.com/go-gitea/gitea/pull/34510)) already in Forgejo - see https://codeberg.org/forgejo/forgejo/pulls/8035 ------ - ⏩ [`gitea`](2c341b6803
) [skip ci] Updated translations via Crowdin ------ - ⏩ [`gitea`](92e7e98c56
) Update x/crypto package and make builtin SSH use default parameters ([gitea#34667](https://github.com/go-gitea/gitea/pull/34667)) ------ - ⏩ [`gitea`](7b39c82587
) Fix "oras" OCI client compatibility ([gitea#34666](https://github.com/go-gitea/gitea/pull/34666)) Already in forgejo - see https://codeberg.org/forgejo/forgejo/issues/8070 ------ - ⏩ [`gitea`](1fe652cd26
) [skip ci] Updated translations via Crowdin ------ - ⏩ [`gitea`](a9a705f4db
) Fix missed merge commit sha and time when migrating from codecommit ([gitea#34645](https://github.com/go-gitea/gitea/pull/34645)) Migration: Seems to be an important fix, but no tests. As I know @earl-warren worked hard on migration, is this still relevant to us? ------ - ⏩ [`gitea`](1e0758a9f1
) [skip ci] Updated translations via Crowdin ------ - ⏩ [`gitea`](f6f6aedd4f
) Update JS deps, regenerate SVGs ([gitea#34640](https://github.com/go-gitea/gitea/pull/34640)) ------ - ⏩ [`gitea`](aa2b3b2b1f
) Misc CSS fixes ([gitea#34638](https://github.com/go-gitea/gitea/pull/34638)) - gitea UI specific specific ------ - ⏩ [`gitea`](b38f2d31fd
) add codecommit to supported services in api docs ([gitea#34626](https://github.com/go-gitea/gitea/pull/34626)) ------ - ⏩ [`gitea`](74a0178c6a
) add openssh-keygen to rootless image ([gitea#34625](https://github.com/go-gitea/gitea/pull/34625)) already in Forgejo - see https://codeberg.org/forgejo/forgejo/issues/6896 ------ - ⏩ [`gitea`](5b22af4373
) bump to alpine 3.22 ([gitea#34613](https://github.com/go-gitea/gitea/pull/34613)) ------ - ⏩ [`gitea`](9e0e107d23
) Fix notification count positioning for variable-width elements ([gitea#34597](https://github.com/go-gitea/gitea/pull/34597)) - gitea UI specific specific ------ - ⏩ [`gitea`](e5781cec75
) Fix margin issue in markup paragraph rendering ([gitea#34599](https://github.com/go-gitea/gitea/pull/34599)) - gitea UI specific specific ------ - ⏩ [`gitea`](375dab1111
) Make pull request and issue history more compact ([gitea#34588](https://github.com/go-gitea/gitea/pull/34588)) - gitea UI specific specific ------ - ⏩ [`gitea`](2a1585b32e
) Refactor some tests ([gitea#34580](https://github.com/go-gitea/gitea/pull/34580)) ------ <details> <summary><h2>Stats</h2></summary> <br> Between [`gitea@d5bbaee64e`](d5bbaee64e
) and [`gitea@6b8b580218`](6b8b580218
), **55** commits have been reviewed. We picked **5**, skipped **28** (of which **3** were already in Forgejo!), and decided to port **22**. </details> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: NorthRealm <155140859+NorthRealm@users.noreply.github.com> Co-authored-by: TheFox0x7 <thefox0x7@gmail.com> Co-authored-by: endo0911engineer <161911062+endo0911engineer@users.noreply.github.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com> Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8198 Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org> Co-authored-by: Michael Jerger <michael.jerger@meissa-gmbh.de> Co-committed-by: Michael Jerger <michael.jerger@meissa-gmbh.de>
718 lines
20 KiB
Go
718 lines
20 KiB
Go
// Copyright 2022 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package actions
|
|
|
|
import (
|
|
"bytes"
|
|
"io"
|
|
"strings"
|
|
|
|
"forgejo.org/modules/git"
|
|
"forgejo.org/modules/log"
|
|
api "forgejo.org/modules/structs"
|
|
webhook_module "forgejo.org/modules/webhook"
|
|
|
|
"github.com/gobwas/glob"
|
|
"github.com/nektos/act/pkg/jobparser"
|
|
"github.com/nektos/act/pkg/model"
|
|
"github.com/nektos/act/pkg/workflowpattern"
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
type DetectedWorkflow struct {
|
|
EntryName string
|
|
TriggerEvent *jobparser.Event
|
|
Content []byte
|
|
}
|
|
|
|
func init() {
|
|
model.OnDecodeNodeError = func(node yaml.Node, out any, err error) {
|
|
// Log the error instead of panic or fatal.
|
|
// It will be a big job to refactor act/pkg/model to return decode error,
|
|
// so we just log the error and return empty value, and improve it later.
|
|
log.Error("Failed to decode node %v into %T: %v", node, out, err)
|
|
}
|
|
}
|
|
|
|
func IsWorkflow(path string) bool {
|
|
if (!strings.HasSuffix(path, ".yaml")) && (!strings.HasSuffix(path, ".yml")) {
|
|
return false
|
|
}
|
|
|
|
return strings.HasPrefix(path, ".forgejo/workflows") || strings.HasPrefix(path, ".gitea/workflows") || strings.HasPrefix(path, ".github/workflows")
|
|
}
|
|
|
|
func ListWorkflows(commit *git.Commit) (git.Entries, error) {
|
|
tree, err := commit.SubTree(".forgejo/workflows")
|
|
if _, ok := err.(git.ErrNotExist); ok {
|
|
tree, err = commit.SubTree(".gitea/workflows")
|
|
}
|
|
if _, ok := err.(git.ErrNotExist); ok {
|
|
tree, err = commit.SubTree(".github/workflows")
|
|
}
|
|
if _, ok := err.(git.ErrNotExist); ok {
|
|
return nil, nil
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
entries, err := tree.ListEntriesRecursiveFast()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ret := make(git.Entries, 0, len(entries))
|
|
for _, entry := range entries {
|
|
if strings.HasSuffix(entry.Name(), ".yml") || strings.HasSuffix(entry.Name(), ".yaml") {
|
|
ret = append(ret, entry)
|
|
}
|
|
}
|
|
return ret, nil
|
|
}
|
|
|
|
func GetContentFromEntry(entry *git.TreeEntry) ([]byte, error) {
|
|
f, err := entry.Blob().DataAsync()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
content, err := io.ReadAll(f)
|
|
_ = f.Close()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return content, nil
|
|
}
|
|
|
|
func GetEventsFromContent(content []byte) ([]*jobparser.Event, error) {
|
|
workflow, err := model.ReadWorkflow(bytes.NewReader(content))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
events, err := jobparser.ParseRawOn(&workflow.RawOn)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return events, nil
|
|
}
|
|
|
|
func DetectWorkflows(
|
|
gitRepo *git.Repository,
|
|
commit *git.Commit,
|
|
triggedEvent webhook_module.HookEventType,
|
|
payload api.Payloader,
|
|
detectSchedule bool,
|
|
) ([]*DetectedWorkflow, []*DetectedWorkflow, error) {
|
|
entries, err := ListWorkflows(commit)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
workflows := make([]*DetectedWorkflow, 0, len(entries))
|
|
schedules := make([]*DetectedWorkflow, 0, len(entries))
|
|
for _, entry := range entries {
|
|
content, err := GetContentFromEntry(entry)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
// one workflow may have multiple events
|
|
events, err := GetEventsFromContent(content)
|
|
if err != nil {
|
|
log.Warn("ignore invalid workflow %q: %v", entry.Name(), err)
|
|
dwf := &DetectedWorkflow{
|
|
EntryName: entry.Name(),
|
|
TriggerEvent: &jobparser.Event{
|
|
Name: triggedEvent.Event(),
|
|
},
|
|
Content: content,
|
|
}
|
|
workflows = append(workflows, dwf)
|
|
continue
|
|
}
|
|
for _, evt := range events {
|
|
log.Trace("detect workflow %q for event %#v matching %q", entry.Name(), evt, triggedEvent)
|
|
if evt.IsSchedule() {
|
|
if detectSchedule {
|
|
dwf := &DetectedWorkflow{
|
|
EntryName: entry.Name(),
|
|
TriggerEvent: evt,
|
|
Content: content,
|
|
}
|
|
schedules = append(schedules, dwf)
|
|
}
|
|
} else if detectMatched(gitRepo, commit, triggedEvent, payload, evt) {
|
|
dwf := &DetectedWorkflow{
|
|
EntryName: entry.Name(),
|
|
TriggerEvent: evt,
|
|
Content: content,
|
|
}
|
|
workflows = append(workflows, dwf)
|
|
}
|
|
}
|
|
}
|
|
|
|
return workflows, schedules, nil
|
|
}
|
|
|
|
func DetectScheduledWorkflows(gitRepo *git.Repository, commit *git.Commit) ([]*DetectedWorkflow, error) {
|
|
entries, err := ListWorkflows(commit)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
wfs := make([]*DetectedWorkflow, 0, len(entries))
|
|
for _, entry := range entries {
|
|
content, err := GetContentFromEntry(entry)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// one workflow may have multiple events
|
|
events, err := GetEventsFromContent(content)
|
|
if err != nil {
|
|
log.Warn("ignore invalid workflow %q: %v", entry.Name(), err)
|
|
continue
|
|
}
|
|
for _, evt := range events {
|
|
if evt.IsSchedule() {
|
|
log.Trace("detect scheduled workflow: %q", entry.Name())
|
|
dwf := &DetectedWorkflow{
|
|
EntryName: entry.Name(),
|
|
TriggerEvent: evt,
|
|
Content: content,
|
|
}
|
|
wfs = append(wfs, dwf)
|
|
}
|
|
}
|
|
}
|
|
|
|
return wfs, nil
|
|
}
|
|
|
|
func detectMatched(gitRepo *git.Repository, commit *git.Commit, triggedEvent webhook_module.HookEventType, payload api.Payloader, evt *jobparser.Event) bool {
|
|
if !canGithubEventMatch(evt.Name, triggedEvent) {
|
|
return false
|
|
}
|
|
|
|
switch triggedEvent {
|
|
case // events with no activity types
|
|
webhook_module.HookEventWorkflowDispatch,
|
|
webhook_module.HookEventCreate,
|
|
webhook_module.HookEventDelete,
|
|
webhook_module.HookEventFork,
|
|
webhook_module.HookEventWiki,
|
|
webhook_module.HookEventSchedule:
|
|
if len(evt.Acts()) != 0 {
|
|
log.Warn("Ignore unsupported %s event arguments %v", triggedEvent, evt.Acts())
|
|
}
|
|
// no special filter parameters for these events, just return true if name matched
|
|
return true
|
|
|
|
case // push
|
|
webhook_module.HookEventPush:
|
|
return matchPushEvent(commit, payload.(*api.PushPayload), evt)
|
|
|
|
case // issues
|
|
webhook_module.HookEventIssues,
|
|
webhook_module.HookEventIssueAssign,
|
|
webhook_module.HookEventIssueLabel,
|
|
webhook_module.HookEventIssueMilestone:
|
|
return matchIssuesEvent(payload.(*api.IssuePayload), evt)
|
|
|
|
case // issue_comment
|
|
webhook_module.HookEventIssueComment,
|
|
// `pull_request_comment` is same as `issue_comment`
|
|
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_comment-use-issue_comment
|
|
webhook_module.HookEventPullRequestComment:
|
|
return matchIssueCommentEvent(payload.(*api.IssueCommentPayload), evt)
|
|
|
|
case // pull_request
|
|
webhook_module.HookEventPullRequest,
|
|
webhook_module.HookEventPullRequestSync,
|
|
webhook_module.HookEventPullRequestAssign,
|
|
webhook_module.HookEventPullRequestLabel,
|
|
webhook_module.HookEventPullRequestReviewRequest,
|
|
webhook_module.HookEventPullRequestMilestone:
|
|
return matchPullRequestEvent(gitRepo, commit, payload.(*api.PullRequestPayload), evt)
|
|
|
|
case // pull_request_review
|
|
webhook_module.HookEventPullRequestReviewApproved,
|
|
webhook_module.HookEventPullRequestReviewRejected:
|
|
return matchPullRequestReviewEvent(payload.(*api.PullRequestPayload), evt)
|
|
|
|
case // pull_request_review_comment
|
|
webhook_module.HookEventPullRequestReviewComment:
|
|
return matchPullRequestReviewCommentEvent(payload.(*api.PullRequestPayload), evt)
|
|
|
|
case // release
|
|
webhook_module.HookEventRelease:
|
|
return matchReleaseEvent(payload.(*api.ReleasePayload), evt)
|
|
|
|
case // registry_package
|
|
webhook_module.HookEventPackage:
|
|
return matchPackageEvent(payload.(*api.PackagePayload), evt)
|
|
|
|
default:
|
|
log.Warn("unsupported event %q", triggedEvent)
|
|
return false
|
|
}
|
|
}
|
|
|
|
func matchPushEvent(commit *git.Commit, pushPayload *api.PushPayload, evt *jobparser.Event) bool {
|
|
// with no special filter parameters
|
|
if len(evt.Acts()) == 0 {
|
|
return true
|
|
}
|
|
|
|
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":
|
|
hasBranchFilter = true
|
|
if !refName.IsBranch() {
|
|
break
|
|
}
|
|
patterns, err := workflowpattern.CompilePatterns(vals...)
|
|
if err != nil {
|
|
break
|
|
}
|
|
if !workflowpattern.Skip(patterns, []string{refName.BranchName()}, &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.BranchName()}, &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.TagName()}, &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.TagName()}, &workflowpattern.EmptyTraceWriter{}) {
|
|
matchTimes++
|
|
}
|
|
case "paths":
|
|
if refName.IsTag() {
|
|
matchTimes++
|
|
break
|
|
}
|
|
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.Skip(patterns, filesChanged, &workflowpattern.EmptyTraceWriter{}) {
|
|
matchTimes++
|
|
}
|
|
}
|
|
case "paths-ignore":
|
|
if refName.IsTag() {
|
|
matchTimes++
|
|
break
|
|
}
|
|
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())
|
|
}
|
|
|
|
func matchIssuesEvent(issuePayload *api.IssuePayload, evt *jobparser.Event) bool {
|
|
// with no special filter parameters
|
|
if len(evt.Acts()) == 0 {
|
|
return true
|
|
}
|
|
|
|
matchTimes := 0
|
|
// all acts conditions should be satisfied
|
|
for cond, vals := range evt.Acts() {
|
|
switch cond {
|
|
case "types":
|
|
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#issues
|
|
// Actions with the same name:
|
|
// opened, edited, closed, reopened, assigned, unassigned, milestoned, demilestoned
|
|
// Actions need to be converted:
|
|
// label_updated -> labeled
|
|
// label_cleared -> unlabeled
|
|
// Unsupported activity types:
|
|
// deleted, transferred, pinned, unpinned, locked, unlocked
|
|
|
|
action := issuePayload.Action
|
|
switch action {
|
|
case api.HookIssueLabelUpdated:
|
|
action = "labeled"
|
|
case api.HookIssueLabelCleared:
|
|
action = "unlabeled"
|
|
}
|
|
for _, val := range vals {
|
|
if glob.MustCompile(val, '/').Match(string(action)) {
|
|
matchTimes++
|
|
break
|
|
}
|
|
}
|
|
default:
|
|
log.Warn("issue event unsupported condition %q", cond)
|
|
}
|
|
}
|
|
return matchTimes == len(evt.Acts())
|
|
}
|
|
|
|
func matchPullRequestEvent(gitRepo *git.Repository, commit *git.Commit, prPayload *api.PullRequestPayload, evt *jobparser.Event) bool {
|
|
acts := evt.Acts()
|
|
activityTypeMatched := false
|
|
matchTimes := 0
|
|
|
|
if vals, ok := acts["types"]; !ok {
|
|
// defaultly, only pull request `opened`, `reopened` and `synchronized` will trigger workflow
|
|
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request
|
|
activityTypeMatched = prPayload.Action == api.HookIssueSynchronized || prPayload.Action == api.HookIssueOpened || prPayload.Action == api.HookIssueReOpened
|
|
} else {
|
|
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request
|
|
// Actions with the same name:
|
|
// opened, edited, closed, reopened, assigned, unassigned, review_requested, review_request_removed, milestoned, demilestoned
|
|
// Actions need to be converted:
|
|
// synchronized -> synchronize
|
|
// label_updated -> labeled
|
|
// label_cleared -> unlabeled
|
|
// Unsupported activity types:
|
|
// converted_to_draft, ready_for_review, locked, unlocked, auto_merge_enabled, auto_merge_disabled, enqueued, dequeued
|
|
|
|
action := prPayload.Action
|
|
switch action {
|
|
case api.HookIssueSynchronized:
|
|
action = "synchronize"
|
|
case api.HookIssueLabelUpdated:
|
|
action = "labeled"
|
|
case api.HookIssueLabelCleared:
|
|
action = "unlabeled"
|
|
}
|
|
log.Trace("matching pull_request %s with %v", action, vals)
|
|
for _, val := range vals {
|
|
if glob.MustCompile(val, '/').Match(string(action)) {
|
|
activityTypeMatched = true
|
|
matchTimes++
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
var (
|
|
headCommit = commit
|
|
err error
|
|
)
|
|
if evt.Name == GithubEventPullRequestTarget && (len(acts["paths"]) > 0 || len(acts["paths-ignore"]) > 0) {
|
|
headCommit, err = gitRepo.GetCommit(prPayload.PullRequest.Head.Sha)
|
|
if err != nil {
|
|
log.Error("GetCommit [ref: %s]: %v", prPayload.PullRequest.Head.Sha, err)
|
|
return false
|
|
}
|
|
}
|
|
|
|
// all acts conditions should be satisfied
|
|
for cond, vals := range acts {
|
|
switch cond {
|
|
case "types":
|
|
// types have been checked
|
|
continue
|
|
case "branches":
|
|
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 := headCommit.GetFilesChangedSinceCommit(prPayload.PullRequest.Base.Ref)
|
|
if err != nil {
|
|
log.Error("GetFilesChangedSinceCommit [commit_sha1: %s]: %v", headCommit.ID.String(), err)
|
|
} else {
|
|
patterns, err := workflowpattern.CompilePatterns(vals...)
|
|
if err != nil {
|
|
break
|
|
}
|
|
if !workflowpattern.Skip(patterns, filesChanged, &workflowpattern.EmptyTraceWriter{}) {
|
|
matchTimes++
|
|
}
|
|
}
|
|
case "paths-ignore":
|
|
filesChanged, err := headCommit.GetFilesChangedSinceCommit(prPayload.PullRequest.Base.Ref)
|
|
if err != nil {
|
|
log.Error("GetFilesChangedSinceCommit [commit_sha1: %s]: %v", headCommit.ID.String(), err)
|
|
} else {
|
|
patterns, err := workflowpattern.CompilePatterns(vals...)
|
|
if err != nil {
|
|
break
|
|
}
|
|
if !workflowpattern.Filter(patterns, filesChanged, &workflowpattern.EmptyTraceWriter{}) {
|
|
matchTimes++
|
|
}
|
|
}
|
|
default:
|
|
log.Warn("pull request event unsupported condition %q", cond)
|
|
}
|
|
}
|
|
return activityTypeMatched && matchTimes == len(evt.Acts())
|
|
}
|
|
|
|
func matchIssueCommentEvent(issueCommentPayload *api.IssueCommentPayload, evt *jobparser.Event) bool {
|
|
// with no special filter parameters
|
|
if len(evt.Acts()) == 0 {
|
|
return true
|
|
}
|
|
|
|
matchTimes := 0
|
|
// all acts conditions should be satisfied
|
|
for cond, vals := range evt.Acts() {
|
|
switch cond {
|
|
case "types":
|
|
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#issue_comment
|
|
// Actions with the same name:
|
|
// created, edited, deleted
|
|
// Actions need to be converted:
|
|
// NONE
|
|
// Unsupported activity types:
|
|
// NONE
|
|
|
|
for _, val := range vals {
|
|
if glob.MustCompile(val, '/').Match(string(issueCommentPayload.Action)) {
|
|
matchTimes++
|
|
break
|
|
}
|
|
}
|
|
default:
|
|
log.Warn("issue comment event unsupported condition %q", cond)
|
|
}
|
|
}
|
|
return matchTimes == len(evt.Acts())
|
|
}
|
|
|
|
func matchPullRequestReviewEvent(prPayload *api.PullRequestPayload, evt *jobparser.Event) bool {
|
|
// with no special filter parameters
|
|
if len(evt.Acts()) == 0 {
|
|
return true
|
|
}
|
|
|
|
matchTimes := 0
|
|
// all acts conditions should be satisfied
|
|
for cond, vals := range evt.Acts() {
|
|
switch cond {
|
|
case "types":
|
|
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_review
|
|
// Activity types with the same name:
|
|
// NONE
|
|
// Activity types need to be converted:
|
|
// reviewed -> submitted
|
|
// reviewed -> edited
|
|
// Unsupported activity types:
|
|
// dismissed
|
|
|
|
actions := make([]string, 0)
|
|
if prPayload.Action == api.HookIssueReviewed {
|
|
// the `reviewed` HookIssueAction can match the two activity types: `submitted` and `edited`
|
|
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_review
|
|
actions = append(actions, "submitted", "edited")
|
|
}
|
|
|
|
matched := false
|
|
for _, val := range vals {
|
|
for _, action := range actions {
|
|
if glob.MustCompile(val, '/').Match(action) {
|
|
matched = true
|
|
break
|
|
}
|
|
}
|
|
if matched {
|
|
break
|
|
}
|
|
}
|
|
if matched {
|
|
matchTimes++
|
|
}
|
|
default:
|
|
log.Warn("pull request review event unsupported condition %q", cond)
|
|
}
|
|
}
|
|
return matchTimes == len(evt.Acts())
|
|
}
|
|
|
|
func matchPullRequestReviewCommentEvent(prPayload *api.PullRequestPayload, evt *jobparser.Event) bool {
|
|
// with no special filter parameters
|
|
if len(evt.Acts()) == 0 {
|
|
return true
|
|
}
|
|
|
|
matchTimes := 0
|
|
// all acts conditions should be satisfied
|
|
for cond, vals := range evt.Acts() {
|
|
switch cond {
|
|
case "types":
|
|
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_review_comment
|
|
// Activity types with the same name:
|
|
// NONE
|
|
// Activity types need to be converted:
|
|
// reviewed -> created
|
|
// reviewed -> edited
|
|
// Unsupported activity types:
|
|
// deleted
|
|
|
|
actions := make([]string, 0)
|
|
if prPayload.Action == api.HookIssueReviewed {
|
|
// the `reviewed` HookIssueAction can match the two activity types: `created` and `edited`
|
|
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_review_comment
|
|
actions = append(actions, "created", "edited")
|
|
}
|
|
|
|
matched := false
|
|
for _, val := range vals {
|
|
for _, action := range actions {
|
|
if glob.MustCompile(val, '/').Match(action) {
|
|
matched = true
|
|
break
|
|
}
|
|
}
|
|
if matched {
|
|
break
|
|
}
|
|
}
|
|
if matched {
|
|
matchTimes++
|
|
}
|
|
default:
|
|
log.Warn("pull request review comment event unsupported condition %q", cond)
|
|
}
|
|
}
|
|
return matchTimes == len(evt.Acts())
|
|
}
|
|
|
|
func matchReleaseEvent(payload *api.ReleasePayload, evt *jobparser.Event) bool {
|
|
// with no special filter parameters
|
|
if len(evt.Acts()) == 0 {
|
|
return true
|
|
}
|
|
|
|
matchTimes := 0
|
|
// all acts conditions should be satisfied
|
|
for cond, vals := range evt.Acts() {
|
|
switch cond {
|
|
case "types":
|
|
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#release
|
|
// Activity types with the same name:
|
|
// published
|
|
// Activity types need to be converted:
|
|
// updated -> edited
|
|
// Unsupported activity types:
|
|
// unpublished, created, deleted, prereleased, released
|
|
|
|
action := payload.Action
|
|
if action == api.HookReleaseUpdated {
|
|
action = "edited"
|
|
}
|
|
for _, val := range vals {
|
|
if glob.MustCompile(val, '/').Match(string(action)) {
|
|
matchTimes++
|
|
break
|
|
}
|
|
}
|
|
default:
|
|
log.Warn("release event unsupported condition %q", cond)
|
|
}
|
|
}
|
|
return matchTimes == len(evt.Acts())
|
|
}
|
|
|
|
func matchPackageEvent(payload *api.PackagePayload, evt *jobparser.Event) bool {
|
|
// with no special filter parameters
|
|
if len(evt.Acts()) == 0 {
|
|
return true
|
|
}
|
|
|
|
matchTimes := 0
|
|
// all acts conditions should be satisfied
|
|
for cond, vals := range evt.Acts() {
|
|
switch cond {
|
|
case "types":
|
|
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#registry_package
|
|
// Activity types with the same name:
|
|
// NONE
|
|
// Activity types need to be converted:
|
|
// created -> published
|
|
// Unsupported activity types:
|
|
// updated
|
|
|
|
action := payload.Action
|
|
if action == api.HookPackageCreated {
|
|
action = "published"
|
|
}
|
|
for _, val := range vals {
|
|
if glob.MustCompile(val, '/').Match(string(action)) {
|
|
matchTimes++
|
|
break
|
|
}
|
|
}
|
|
default:
|
|
log.Warn("package event unsupported condition %q", cond)
|
|
}
|
|
}
|
|
return matchTimes == len(evt.Acts())
|
|
}
|