gitea源码

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756
  1. // Copyright 2022 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package actions
  4. import (
  5. "bytes"
  6. "io"
  7. "slices"
  8. "strings"
  9. "code.gitea.io/gitea/modules/git"
  10. "code.gitea.io/gitea/modules/glob"
  11. "code.gitea.io/gitea/modules/log"
  12. api "code.gitea.io/gitea/modules/structs"
  13. webhook_module "code.gitea.io/gitea/modules/webhook"
  14. "github.com/nektos/act/pkg/jobparser"
  15. "github.com/nektos/act/pkg/model"
  16. "github.com/nektos/act/pkg/workflowpattern"
  17. "gopkg.in/yaml.v3"
  18. )
  19. type DetectedWorkflow struct {
  20. EntryName string
  21. TriggerEvent *jobparser.Event
  22. Content []byte
  23. }
  24. func init() {
  25. model.OnDecodeNodeError = func(node yaml.Node, out any, err error) {
  26. // Log the error instead of panic or fatal.
  27. // It will be a big job to refactor act/pkg/model to return decode error,
  28. // so we just log the error and return empty value, and improve it later.
  29. log.Error("Failed to decode node %v into %T: %v", node, out, err)
  30. }
  31. }
  32. func IsWorkflow(path string) bool {
  33. if (!strings.HasSuffix(path, ".yaml")) && (!strings.HasSuffix(path, ".yml")) {
  34. return false
  35. }
  36. return strings.HasPrefix(path, ".gitea/workflows") || strings.HasPrefix(path, ".github/workflows")
  37. }
  38. func ListWorkflows(commit *git.Commit) (string, git.Entries, error) {
  39. rpath := ".gitea/workflows"
  40. tree, err := commit.SubTree(rpath)
  41. if _, ok := err.(git.ErrNotExist); ok {
  42. rpath = ".github/workflows"
  43. tree, err = commit.SubTree(rpath)
  44. }
  45. if _, ok := err.(git.ErrNotExist); ok {
  46. return "", nil, nil
  47. }
  48. if err != nil {
  49. return "", nil, err
  50. }
  51. entries, err := tree.ListEntriesRecursiveFast()
  52. if err != nil {
  53. return "", nil, err
  54. }
  55. ret := make(git.Entries, 0, len(entries))
  56. for _, entry := range entries {
  57. if strings.HasSuffix(entry.Name(), ".yml") || strings.HasSuffix(entry.Name(), ".yaml") {
  58. ret = append(ret, entry)
  59. }
  60. }
  61. return rpath, ret, nil
  62. }
  63. func GetContentFromEntry(entry *git.TreeEntry) ([]byte, error) {
  64. f, err := entry.Blob().DataAsync()
  65. if err != nil {
  66. return nil, err
  67. }
  68. content, err := io.ReadAll(f)
  69. _ = f.Close()
  70. if err != nil {
  71. return nil, err
  72. }
  73. return content, nil
  74. }
  75. func GetEventsFromContent(content []byte) ([]*jobparser.Event, error) {
  76. workflow, err := model.ReadWorkflow(bytes.NewReader(content))
  77. if err != nil {
  78. return nil, err
  79. }
  80. events, err := jobparser.ParseRawOn(&workflow.RawOn)
  81. if err != nil {
  82. return nil, err
  83. }
  84. return events, nil
  85. }
  86. func DetectWorkflows(
  87. gitRepo *git.Repository,
  88. commit *git.Commit,
  89. triggedEvent webhook_module.HookEventType,
  90. payload api.Payloader,
  91. detectSchedule bool,
  92. ) ([]*DetectedWorkflow, []*DetectedWorkflow, error) {
  93. _, entries, err := ListWorkflows(commit)
  94. if err != nil {
  95. return nil, nil, err
  96. }
  97. workflows := make([]*DetectedWorkflow, 0, len(entries))
  98. schedules := make([]*DetectedWorkflow, 0, len(entries))
  99. for _, entry := range entries {
  100. content, err := GetContentFromEntry(entry)
  101. if err != nil {
  102. return nil, nil, err
  103. }
  104. // one workflow may have multiple events
  105. events, err := GetEventsFromContent(content)
  106. if err != nil {
  107. log.Warn("ignore invalid workflow %q: %v", entry.Name(), err)
  108. continue
  109. }
  110. for _, evt := range events {
  111. log.Trace("detect workflow %q for event %#v matching %q", entry.Name(), evt, triggedEvent)
  112. if evt.IsSchedule() {
  113. if detectSchedule {
  114. dwf := &DetectedWorkflow{
  115. EntryName: entry.Name(),
  116. TriggerEvent: evt,
  117. Content: content,
  118. }
  119. schedules = append(schedules, dwf)
  120. }
  121. } else if detectMatched(gitRepo, commit, triggedEvent, payload, evt) {
  122. dwf := &DetectedWorkflow{
  123. EntryName: entry.Name(),
  124. TriggerEvent: evt,
  125. Content: content,
  126. }
  127. workflows = append(workflows, dwf)
  128. }
  129. }
  130. }
  131. return workflows, schedules, nil
  132. }
  133. func DetectScheduledWorkflows(gitRepo *git.Repository, commit *git.Commit) ([]*DetectedWorkflow, error) {
  134. _, entries, err := ListWorkflows(commit)
  135. if err != nil {
  136. return nil, err
  137. }
  138. wfs := make([]*DetectedWorkflow, 0, len(entries))
  139. for _, entry := range entries {
  140. content, err := GetContentFromEntry(entry)
  141. if err != nil {
  142. return nil, err
  143. }
  144. // one workflow may have multiple events
  145. events, err := GetEventsFromContent(content)
  146. if err != nil {
  147. log.Warn("ignore invalid workflow %q: %v", entry.Name(), err)
  148. continue
  149. }
  150. for _, evt := range events {
  151. if evt.IsSchedule() {
  152. log.Trace("detect scheduled workflow: %q", entry.Name())
  153. dwf := &DetectedWorkflow{
  154. EntryName: entry.Name(),
  155. TriggerEvent: evt,
  156. Content: content,
  157. }
  158. wfs = append(wfs, dwf)
  159. }
  160. }
  161. }
  162. return wfs, nil
  163. }
  164. func detectMatched(gitRepo *git.Repository, commit *git.Commit, triggedEvent webhook_module.HookEventType, payload api.Payloader, evt *jobparser.Event) bool {
  165. if !canGithubEventMatch(evt.Name, triggedEvent) {
  166. return false
  167. }
  168. switch triggedEvent {
  169. case // events with no activity types
  170. webhook_module.HookEventCreate,
  171. webhook_module.HookEventDelete,
  172. webhook_module.HookEventFork,
  173. webhook_module.HookEventWiki,
  174. webhook_module.HookEventSchedule:
  175. if len(evt.Acts()) != 0 {
  176. log.Warn("Ignore unsupported %s event arguments %v", triggedEvent, evt.Acts())
  177. }
  178. // no special filter parameters for these events, just return true if name matched
  179. return true
  180. case // push
  181. webhook_module.HookEventPush:
  182. return matchPushEvent(commit, payload.(*api.PushPayload), evt)
  183. case // issues
  184. webhook_module.HookEventIssues,
  185. webhook_module.HookEventIssueAssign,
  186. webhook_module.HookEventIssueLabel,
  187. webhook_module.HookEventIssueMilestone:
  188. return matchIssuesEvent(payload.(*api.IssuePayload), evt)
  189. case // issue_comment
  190. webhook_module.HookEventIssueComment,
  191. // `pull_request_comment` is same as `issue_comment`
  192. // See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_comment-use-issue_comment
  193. webhook_module.HookEventPullRequestComment:
  194. return matchIssueCommentEvent(payload.(*api.IssueCommentPayload), evt)
  195. case // pull_request
  196. webhook_module.HookEventPullRequest,
  197. webhook_module.HookEventPullRequestSync,
  198. webhook_module.HookEventPullRequestAssign,
  199. webhook_module.HookEventPullRequestLabel,
  200. webhook_module.HookEventPullRequestReviewRequest,
  201. webhook_module.HookEventPullRequestMilestone:
  202. return matchPullRequestEvent(gitRepo, commit, payload.(*api.PullRequestPayload), evt)
  203. case // pull_request_review
  204. webhook_module.HookEventPullRequestReviewApproved,
  205. webhook_module.HookEventPullRequestReviewRejected:
  206. return matchPullRequestReviewEvent(payload.(*api.PullRequestPayload), evt)
  207. case // pull_request_review_comment
  208. webhook_module.HookEventPullRequestReviewComment:
  209. return matchPullRequestReviewCommentEvent(payload.(*api.PullRequestPayload), evt)
  210. case // release
  211. webhook_module.HookEventRelease:
  212. return matchReleaseEvent(payload.(*api.ReleasePayload), evt)
  213. case // registry_package
  214. webhook_module.HookEventPackage:
  215. return matchPackageEvent(payload.(*api.PackagePayload), evt)
  216. case // workflow_run
  217. webhook_module.HookEventWorkflowRun:
  218. return matchWorkflowRunEvent(payload.(*api.WorkflowRunPayload), evt)
  219. default:
  220. log.Warn("unsupported event %q", triggedEvent)
  221. return false
  222. }
  223. }
  224. func matchPushEvent(commit *git.Commit, pushPayload *api.PushPayload, evt *jobparser.Event) bool {
  225. // with no special filter parameters
  226. if len(evt.Acts()) == 0 {
  227. return true
  228. }
  229. matchTimes := 0
  230. hasBranchFilter := false
  231. hasTagFilter := false
  232. refName := git.RefName(pushPayload.Ref)
  233. // all acts conditions should be satisfied
  234. for cond, vals := range evt.Acts() {
  235. switch cond {
  236. case "branches":
  237. hasBranchFilter = true
  238. if !refName.IsBranch() {
  239. break
  240. }
  241. patterns, err := workflowpattern.CompilePatterns(vals...)
  242. if err != nil {
  243. break
  244. }
  245. if !workflowpattern.Skip(patterns, []string{refName.BranchName()}, &workflowpattern.EmptyTraceWriter{}) {
  246. matchTimes++
  247. }
  248. case "branches-ignore":
  249. hasBranchFilter = true
  250. if !refName.IsBranch() {
  251. break
  252. }
  253. patterns, err := workflowpattern.CompilePatterns(vals...)
  254. if err != nil {
  255. break
  256. }
  257. if !workflowpattern.Filter(patterns, []string{refName.BranchName()}, &workflowpattern.EmptyTraceWriter{}) {
  258. matchTimes++
  259. }
  260. case "tags":
  261. hasTagFilter = true
  262. if !refName.IsTag() {
  263. break
  264. }
  265. patterns, err := workflowpattern.CompilePatterns(vals...)
  266. if err != nil {
  267. break
  268. }
  269. if !workflowpattern.Skip(patterns, []string{refName.TagName()}, &workflowpattern.EmptyTraceWriter{}) {
  270. matchTimes++
  271. }
  272. case "tags-ignore":
  273. hasTagFilter = true
  274. if !refName.IsTag() {
  275. break
  276. }
  277. patterns, err := workflowpattern.CompilePatterns(vals...)
  278. if err != nil {
  279. break
  280. }
  281. if !workflowpattern.Filter(patterns, []string{refName.TagName()}, &workflowpattern.EmptyTraceWriter{}) {
  282. matchTimes++
  283. }
  284. case "paths":
  285. if refName.IsTag() {
  286. matchTimes++
  287. break
  288. }
  289. filesChanged, err := commit.GetFilesChangedSinceCommit(pushPayload.Before)
  290. if err != nil {
  291. log.Error("GetFilesChangedSinceCommit [commit_sha1: %s]: %v", commit.ID.String(), err)
  292. } else {
  293. patterns, err := workflowpattern.CompilePatterns(vals...)
  294. if err != nil {
  295. break
  296. }
  297. if !workflowpattern.Skip(patterns, filesChanged, &workflowpattern.EmptyTraceWriter{}) {
  298. matchTimes++
  299. }
  300. }
  301. case "paths-ignore":
  302. if refName.IsTag() {
  303. matchTimes++
  304. break
  305. }
  306. filesChanged, err := commit.GetFilesChangedSinceCommit(pushPayload.Before)
  307. if err != nil {
  308. log.Error("GetFilesChangedSinceCommit [commit_sha1: %s]: %v", commit.ID.String(), err)
  309. } else {
  310. patterns, err := workflowpattern.CompilePatterns(vals...)
  311. if err != nil {
  312. break
  313. }
  314. if !workflowpattern.Filter(patterns, filesChanged, &workflowpattern.EmptyTraceWriter{}) {
  315. matchTimes++
  316. }
  317. }
  318. default:
  319. log.Warn("push event unsupported condition %q", cond)
  320. }
  321. }
  322. // if both branch and tag filter are defined in the workflow only one needs to match
  323. if hasBranchFilter && hasTagFilter {
  324. matchTimes++
  325. }
  326. return matchTimes == len(evt.Acts())
  327. }
  328. func matchIssuesEvent(issuePayload *api.IssuePayload, evt *jobparser.Event) bool {
  329. // with no special filter parameters
  330. if len(evt.Acts()) == 0 {
  331. return true
  332. }
  333. matchTimes := 0
  334. // all acts conditions should be satisfied
  335. for cond, vals := range evt.Acts() {
  336. switch cond {
  337. case "types":
  338. // See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#issues
  339. // Actions with the same name:
  340. // opened, edited, closed, reopened, assigned, unassigned, milestoned, demilestoned
  341. // Actions need to be converted:
  342. // label_updated -> labeled (when adding) or unlabeled (when removing)
  343. // label_cleared -> unlabeled
  344. // Unsupported activity types:
  345. // deleted, transferred, pinned, unpinned, locked, unlocked
  346. actions := []string{}
  347. switch issuePayload.Action {
  348. case api.HookIssueLabelUpdated:
  349. if len(issuePayload.Changes.AddedLabels) > 0 {
  350. actions = append(actions, "labeled")
  351. }
  352. if len(issuePayload.Changes.RemovedLabels) > 0 {
  353. actions = append(actions, "unlabeled")
  354. }
  355. case api.HookIssueLabelCleared:
  356. actions = append(actions, "unlabeled")
  357. default:
  358. actions = append(actions, string(issuePayload.Action))
  359. }
  360. for _, val := range vals {
  361. if slices.ContainsFunc(actions, glob.MustCompile(val, '/').Match) {
  362. matchTimes++
  363. break
  364. }
  365. }
  366. default:
  367. log.Warn("issue event unsupported condition %q", cond)
  368. }
  369. }
  370. return matchTimes == len(evt.Acts())
  371. }
  372. func matchPullRequestEvent(gitRepo *git.Repository, commit *git.Commit, prPayload *api.PullRequestPayload, evt *jobparser.Event) bool {
  373. acts := evt.Acts()
  374. activityTypeMatched := false
  375. matchTimes := 0
  376. if vals, ok := acts["types"]; !ok {
  377. // defaultly, only pull request `opened`, `reopened` and `synchronized` will trigger workflow
  378. // See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request
  379. activityTypeMatched = prPayload.Action == api.HookIssueSynchronized || prPayload.Action == api.HookIssueOpened || prPayload.Action == api.HookIssueReOpened
  380. } else {
  381. // See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request
  382. // Actions with the same name:
  383. // opened, edited, closed, reopened, assigned, unassigned, review_requested, review_request_removed, milestoned, demilestoned
  384. // Actions need to be converted:
  385. // synchronized -> synchronize
  386. // label_updated -> labeled
  387. // label_cleared -> unlabeled
  388. // Unsupported activity types:
  389. // converted_to_draft, ready_for_review, locked, unlocked, auto_merge_enabled, auto_merge_disabled, enqueued, dequeued
  390. action := prPayload.Action
  391. switch action {
  392. case api.HookIssueSynchronized:
  393. action = "synchronize"
  394. case api.HookIssueLabelUpdated:
  395. action = "labeled"
  396. case api.HookIssueLabelCleared:
  397. action = "unlabeled"
  398. }
  399. log.Trace("matching pull_request %s with %v", action, vals)
  400. for _, val := range vals {
  401. if glob.MustCompile(val, '/').Match(string(action)) {
  402. activityTypeMatched = true
  403. matchTimes++
  404. break
  405. }
  406. }
  407. }
  408. var (
  409. headCommit = commit
  410. err error
  411. )
  412. if evt.Name == GithubEventPullRequestTarget && (len(acts["paths"]) > 0 || len(acts["paths-ignore"]) > 0) {
  413. headCommit, err = gitRepo.GetCommit(prPayload.PullRequest.Head.Sha)
  414. if err != nil {
  415. log.Error("GetCommit [ref: %s]: %v", prPayload.PullRequest.Head.Sha, err)
  416. return false
  417. }
  418. }
  419. // all acts conditions should be satisfied
  420. for cond, vals := range acts {
  421. switch cond {
  422. case "types":
  423. // types have been checked
  424. continue
  425. case "branches":
  426. refName := git.RefName(prPayload.PullRequest.Base.Ref)
  427. patterns, err := workflowpattern.CompilePatterns(vals...)
  428. if err != nil {
  429. break
  430. }
  431. if !workflowpattern.Skip(patterns, []string{refName.ShortName()}, &workflowpattern.EmptyTraceWriter{}) {
  432. matchTimes++
  433. }
  434. case "branches-ignore":
  435. refName := git.RefName(prPayload.PullRequest.Base.Ref)
  436. patterns, err := workflowpattern.CompilePatterns(vals...)
  437. if err != nil {
  438. break
  439. }
  440. if !workflowpattern.Filter(patterns, []string{refName.ShortName()}, &workflowpattern.EmptyTraceWriter{}) {
  441. matchTimes++
  442. }
  443. case "paths":
  444. filesChanged, err := headCommit.GetFilesChangedSinceCommit(prPayload.PullRequest.MergeBase)
  445. if err != nil {
  446. log.Error("GetFilesChangedSinceCommit [commit_sha1: %s]: %v", headCommit.ID.String(), err)
  447. } else {
  448. patterns, err := workflowpattern.CompilePatterns(vals...)
  449. if err != nil {
  450. break
  451. }
  452. if !workflowpattern.Skip(patterns, filesChanged, &workflowpattern.EmptyTraceWriter{}) {
  453. matchTimes++
  454. }
  455. }
  456. case "paths-ignore":
  457. filesChanged, err := headCommit.GetFilesChangedSinceCommit(prPayload.PullRequest.MergeBase)
  458. if err != nil {
  459. log.Error("GetFilesChangedSinceCommit [commit_sha1: %s]: %v", headCommit.ID.String(), err)
  460. } else {
  461. patterns, err := workflowpattern.CompilePatterns(vals...)
  462. if err != nil {
  463. break
  464. }
  465. if !workflowpattern.Filter(patterns, filesChanged, &workflowpattern.EmptyTraceWriter{}) {
  466. matchTimes++
  467. }
  468. }
  469. default:
  470. log.Warn("pull request event unsupported condition %q", cond)
  471. }
  472. }
  473. return activityTypeMatched && matchTimes == len(evt.Acts())
  474. }
  475. func matchIssueCommentEvent(issueCommentPayload *api.IssueCommentPayload, evt *jobparser.Event) bool {
  476. // with no special filter parameters
  477. if len(evt.Acts()) == 0 {
  478. return true
  479. }
  480. matchTimes := 0
  481. // all acts conditions should be satisfied
  482. for cond, vals := range evt.Acts() {
  483. switch cond {
  484. case "types":
  485. // See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#issue_comment
  486. // Actions with the same name:
  487. // created, edited, deleted
  488. // Actions need to be converted:
  489. // NONE
  490. // Unsupported activity types:
  491. // NONE
  492. for _, val := range vals {
  493. if glob.MustCompile(val, '/').Match(string(issueCommentPayload.Action)) {
  494. matchTimes++
  495. break
  496. }
  497. }
  498. default:
  499. log.Warn("issue comment event unsupported condition %q", cond)
  500. }
  501. }
  502. return matchTimes == len(evt.Acts())
  503. }
  504. func matchPullRequestReviewEvent(prPayload *api.PullRequestPayload, evt *jobparser.Event) bool {
  505. // with no special filter parameters
  506. if len(evt.Acts()) == 0 {
  507. return true
  508. }
  509. matchTimes := 0
  510. // all acts conditions should be satisfied
  511. for cond, vals := range evt.Acts() {
  512. switch cond {
  513. case "types":
  514. // See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_review
  515. // Activity types with the same name:
  516. // NONE
  517. // Activity types need to be converted:
  518. // reviewed -> submitted
  519. // reviewed -> edited
  520. // Unsupported activity types:
  521. // dismissed
  522. actions := make([]string, 0)
  523. if prPayload.Action == api.HookIssueReviewed {
  524. // the `reviewed` HookIssueAction can match the two activity types: `submitted` and `edited`
  525. // See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_review
  526. actions = append(actions, "submitted", "edited")
  527. }
  528. for _, val := range vals {
  529. if slices.ContainsFunc(actions, glob.MustCompile(val, '/').Match) {
  530. matchTimes++
  531. break
  532. }
  533. }
  534. default:
  535. log.Warn("pull request review event unsupported condition %q", cond)
  536. }
  537. }
  538. return matchTimes == len(evt.Acts())
  539. }
  540. func matchPullRequestReviewCommentEvent(prPayload *api.PullRequestPayload, evt *jobparser.Event) bool {
  541. // with no special filter parameters
  542. if len(evt.Acts()) == 0 {
  543. return true
  544. }
  545. matchTimes := 0
  546. // all acts conditions should be satisfied
  547. for cond, vals := range evt.Acts() {
  548. switch cond {
  549. case "types":
  550. // See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_review_comment
  551. // Activity types with the same name:
  552. // NONE
  553. // Activity types need to be converted:
  554. // reviewed -> created
  555. // reviewed -> edited
  556. // Unsupported activity types:
  557. // deleted
  558. actions := make([]string, 0)
  559. if prPayload.Action == api.HookIssueReviewed {
  560. // the `reviewed` HookIssueAction can match the two activity types: `created` and `edited`
  561. // See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_review_comment
  562. actions = append(actions, "created", "edited")
  563. }
  564. for _, val := range vals {
  565. if slices.ContainsFunc(actions, glob.MustCompile(val, '/').Match) {
  566. matchTimes++
  567. break
  568. }
  569. }
  570. default:
  571. log.Warn("pull request review comment event unsupported condition %q", cond)
  572. }
  573. }
  574. return matchTimes == len(evt.Acts())
  575. }
  576. func matchReleaseEvent(payload *api.ReleasePayload, evt *jobparser.Event) bool {
  577. // with no special filter parameters
  578. if len(evt.Acts()) == 0 {
  579. return true
  580. }
  581. matchTimes := 0
  582. // all acts conditions should be satisfied
  583. for cond, vals := range evt.Acts() {
  584. switch cond {
  585. case "types":
  586. // See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#release
  587. // Activity types with the same name:
  588. // published
  589. // Activity types need to be converted:
  590. // updated -> edited
  591. // Unsupported activity types:
  592. // unpublished, created, deleted, prereleased, released
  593. action := payload.Action
  594. switch action {
  595. case api.HookReleaseUpdated:
  596. action = "edited"
  597. }
  598. for _, val := range vals {
  599. if glob.MustCompile(val, '/').Match(string(action)) {
  600. matchTimes++
  601. break
  602. }
  603. }
  604. default:
  605. log.Warn("release event unsupported condition %q", cond)
  606. }
  607. }
  608. return matchTimes == len(evt.Acts())
  609. }
  610. func matchPackageEvent(payload *api.PackagePayload, evt *jobparser.Event) bool {
  611. // with no special filter parameters
  612. if len(evt.Acts()) == 0 {
  613. return true
  614. }
  615. matchTimes := 0
  616. // all acts conditions should be satisfied
  617. for cond, vals := range evt.Acts() {
  618. switch cond {
  619. case "types":
  620. // See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#registry_package
  621. // Activity types with the same name:
  622. // NONE
  623. // Activity types need to be converted:
  624. // created -> published
  625. // Unsupported activity types:
  626. // updated
  627. action := payload.Action
  628. switch action {
  629. case api.HookPackageCreated:
  630. action = "published"
  631. }
  632. for _, val := range vals {
  633. if glob.MustCompile(val, '/').Match(string(action)) {
  634. matchTimes++
  635. break
  636. }
  637. }
  638. default:
  639. log.Warn("package event unsupported condition %q", cond)
  640. }
  641. }
  642. return matchTimes == len(evt.Acts())
  643. }
  644. func matchWorkflowRunEvent(payload *api.WorkflowRunPayload, evt *jobparser.Event) bool {
  645. // with no special filter parameters
  646. if len(evt.Acts()) == 0 {
  647. return true
  648. }
  649. matchTimes := 0
  650. // all acts conditions should be satisfied
  651. for cond, vals := range evt.Acts() {
  652. switch cond {
  653. case "types":
  654. action := payload.Action
  655. for _, val := range vals {
  656. if glob.MustCompile(val, '/').Match(action) {
  657. matchTimes++
  658. break
  659. }
  660. }
  661. case "workflows":
  662. workflow := payload.Workflow
  663. patterns, err := workflowpattern.CompilePatterns(vals...)
  664. if err != nil {
  665. break
  666. }
  667. if !workflowpattern.Skip(patterns, []string{workflow.Name}, &workflowpattern.EmptyTraceWriter{}) {
  668. matchTimes++
  669. }
  670. case "branches":
  671. patterns, err := workflowpattern.CompilePatterns(vals...)
  672. if err != nil {
  673. break
  674. }
  675. if !workflowpattern.Skip(patterns, []string{payload.WorkflowRun.HeadBranch}, &workflowpattern.EmptyTraceWriter{}) {
  676. matchTimes++
  677. }
  678. case "branches-ignore":
  679. patterns, err := workflowpattern.CompilePatterns(vals...)
  680. if err != nil {
  681. break
  682. }
  683. if !workflowpattern.Filter(patterns, []string{payload.WorkflowRun.HeadBranch}, &workflowpattern.EmptyTraceWriter{}) {
  684. matchTimes++
  685. }
  686. default:
  687. log.Warn("workflow run event unsupported condition %q", cond)
  688. }
  689. }
  690. return matchTimes == len(evt.Acts())
  691. }