You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

notifier.go 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757
  1. // Copyright 2022 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package actions
  4. import (
  5. "context"
  6. "code.gitea.io/gitea/models/db"
  7. issues_model "code.gitea.io/gitea/models/issues"
  8. packages_model "code.gitea.io/gitea/models/packages"
  9. perm_model "code.gitea.io/gitea/models/perm"
  10. access_model "code.gitea.io/gitea/models/perm/access"
  11. repo_model "code.gitea.io/gitea/models/repo"
  12. user_model "code.gitea.io/gitea/models/user"
  13. "code.gitea.io/gitea/modules/git"
  14. "code.gitea.io/gitea/modules/log"
  15. "code.gitea.io/gitea/modules/repository"
  16. "code.gitea.io/gitea/modules/setting"
  17. api "code.gitea.io/gitea/modules/structs"
  18. webhook_module "code.gitea.io/gitea/modules/webhook"
  19. "code.gitea.io/gitea/services/convert"
  20. notify_service "code.gitea.io/gitea/services/notify"
  21. )
  22. type actionsNotifier struct {
  23. notify_service.NullNotifier
  24. }
  25. var _ notify_service.Notifier = &actionsNotifier{}
  26. // NewNotifier create a new actionsNotifier notifier
  27. func NewNotifier() notify_service.Notifier {
  28. return &actionsNotifier{}
  29. }
  30. // NewIssue notifies issue created event
  31. func (n *actionsNotifier) NewIssue(ctx context.Context, issue *issues_model.Issue, _ []*user_model.User) {
  32. ctx = withMethod(ctx, "NewIssue")
  33. if err := issue.LoadRepo(ctx); err != nil {
  34. log.Error("issue.LoadRepo: %v", err)
  35. return
  36. }
  37. if err := issue.LoadPoster(ctx); err != nil {
  38. log.Error("issue.LoadPoster: %v", err)
  39. return
  40. }
  41. permission, _ := access_model.GetUserRepoPermission(ctx, issue.Repo, issue.Poster)
  42. newNotifyInputFromIssue(issue, webhook_module.HookEventIssues).WithPayload(&api.IssuePayload{
  43. Action: api.HookIssueOpened,
  44. Index: issue.Index,
  45. Issue: convert.ToAPIIssue(ctx, issue),
  46. Repository: convert.ToRepo(ctx, issue.Repo, permission),
  47. Sender: convert.ToUser(ctx, issue.Poster, nil),
  48. }).Notify(withMethod(ctx, "NewIssue"))
  49. }
  50. // IssueChangeContent notifies change content of issue
  51. func (n *actionsNotifier) IssueChangeContent(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldContent string) {
  52. ctx = withMethod(ctx, "IssueChangeContent")
  53. var err error
  54. if err = issue.LoadRepo(ctx); err != nil {
  55. log.Error("LoadRepo: %v", err)
  56. return
  57. }
  58. permission, _ := access_model.GetUserRepoPermission(ctx, issue.Repo, issue.Poster)
  59. if issue.IsPull {
  60. if err = issue.LoadPullRequest(ctx); err != nil {
  61. log.Error("loadPullRequest: %v", err)
  62. return
  63. }
  64. newNotifyInputFromIssue(issue, webhook_module.HookEventPullRequest).
  65. WithDoer(doer).
  66. WithPayload(&api.PullRequestPayload{
  67. Action: api.HookIssueEdited,
  68. Index: issue.Index,
  69. PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil),
  70. Repository: convert.ToRepo(ctx, issue.Repo, access_model.Permission{AccessMode: perm_model.AccessModeNone}),
  71. Sender: convert.ToUser(ctx, doer, nil),
  72. }).
  73. WithPullRequest(issue.PullRequest).
  74. Notify(ctx)
  75. return
  76. }
  77. newNotifyInputFromIssue(issue, webhook_module.HookEventIssues).
  78. WithDoer(doer).
  79. WithPayload(&api.IssuePayload{
  80. Action: api.HookIssueEdited,
  81. Index: issue.Index,
  82. Issue: convert.ToAPIIssue(ctx, issue),
  83. Repository: convert.ToRepo(ctx, issue.Repo, permission),
  84. Sender: convert.ToUser(ctx, doer, nil),
  85. }).
  86. Notify(ctx)
  87. }
  88. // IssueChangeStatus notifies close or reopen issue to notifiers
  89. func (n *actionsNotifier) IssueChangeStatus(ctx context.Context, doer *user_model.User, commitID string, issue *issues_model.Issue, _ *issues_model.Comment, isClosed bool) {
  90. ctx = withMethod(ctx, "IssueChangeStatus")
  91. permission, _ := access_model.GetUserRepoPermission(ctx, issue.Repo, issue.Poster)
  92. if issue.IsPull {
  93. if err := issue.LoadPullRequest(ctx); err != nil {
  94. log.Error("LoadPullRequest: %v", err)
  95. return
  96. }
  97. // Merge pull request calls issue.changeStatus so we need to handle separately.
  98. apiPullRequest := &api.PullRequestPayload{
  99. Index: issue.Index,
  100. PullRequest: convert.ToAPIPullRequest(db.DefaultContext, issue.PullRequest, nil),
  101. Repository: convert.ToRepo(ctx, issue.Repo, permission),
  102. Sender: convert.ToUser(ctx, doer, nil),
  103. CommitID: commitID,
  104. }
  105. if isClosed {
  106. apiPullRequest.Action = api.HookIssueClosed
  107. } else {
  108. apiPullRequest.Action = api.HookIssueReOpened
  109. }
  110. newNotifyInputFromIssue(issue, webhook_module.HookEventPullRequest).
  111. WithDoer(doer).
  112. WithPayload(apiPullRequest).
  113. WithPullRequest(issue.PullRequest).
  114. Notify(ctx)
  115. return
  116. }
  117. apiIssue := &api.IssuePayload{
  118. Index: issue.Index,
  119. Issue: convert.ToAPIIssue(ctx, issue),
  120. Repository: convert.ToRepo(ctx, issue.Repo, permission),
  121. Sender: convert.ToUser(ctx, doer, nil),
  122. }
  123. if isClosed {
  124. apiIssue.Action = api.HookIssueClosed
  125. } else {
  126. apiIssue.Action = api.HookIssueReOpened
  127. }
  128. newNotifyInputFromIssue(issue, webhook_module.HookEventIssues).
  129. WithDoer(doer).
  130. WithPayload(apiIssue).
  131. Notify(ctx)
  132. }
  133. // IssueChangeAssignee notifies assigned or unassigned to notifiers
  134. func (n *actionsNotifier) IssueChangeAssignee(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, assignee *user_model.User, removed bool, comment *issues_model.Comment) {
  135. ctx = withMethod(ctx, "IssueChangeAssignee")
  136. var action api.HookIssueAction
  137. if removed {
  138. action = api.HookIssueUnassigned
  139. } else {
  140. action = api.HookIssueAssigned
  141. }
  142. hookEvent := webhook_module.HookEventIssueAssign
  143. if issue.IsPull {
  144. hookEvent = webhook_module.HookEventPullRequestAssign
  145. }
  146. notifyIssueChange(ctx, doer, issue, hookEvent, action)
  147. }
  148. // IssueChangeMilestone notifies assignee to notifiers
  149. func (n *actionsNotifier) IssueChangeMilestone(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldMilestoneID int64) {
  150. ctx = withMethod(ctx, "IssueChangeMilestone")
  151. var action api.HookIssueAction
  152. if issue.MilestoneID > 0 {
  153. action = api.HookIssueMilestoned
  154. } else {
  155. action = api.HookIssueDemilestoned
  156. }
  157. hookEvent := webhook_module.HookEventIssueMilestone
  158. if issue.IsPull {
  159. hookEvent = webhook_module.HookEventPullRequestMilestone
  160. }
  161. notifyIssueChange(ctx, doer, issue, hookEvent, action)
  162. }
  163. func (n *actionsNotifier) IssueChangeLabels(ctx context.Context, doer *user_model.User, issue *issues_model.Issue,
  164. _, _ []*issues_model.Label,
  165. ) {
  166. ctx = withMethod(ctx, "IssueChangeLabels")
  167. hookEvent := webhook_module.HookEventIssueLabel
  168. if issue.IsPull {
  169. hookEvent = webhook_module.HookEventPullRequestLabel
  170. }
  171. notifyIssueChange(ctx, doer, issue, hookEvent, api.HookIssueLabelUpdated)
  172. }
  173. func notifyIssueChange(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, event webhook_module.HookEventType, action api.HookIssueAction) {
  174. var err error
  175. if err = issue.LoadRepo(ctx); err != nil {
  176. log.Error("LoadRepo: %v", err)
  177. return
  178. }
  179. if err = issue.LoadPoster(ctx); err != nil {
  180. log.Error("LoadPoster: %v", err)
  181. return
  182. }
  183. if issue.IsPull {
  184. if err = issue.LoadPullRequest(ctx); err != nil {
  185. log.Error("loadPullRequest: %v", err)
  186. return
  187. }
  188. newNotifyInputFromIssue(issue, event).
  189. WithDoer(doer).
  190. WithPayload(&api.PullRequestPayload{
  191. Action: action,
  192. Index: issue.Index,
  193. PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil),
  194. Repository: convert.ToRepo(ctx, issue.Repo, access_model.Permission{AccessMode: perm_model.AccessModeNone}),
  195. Sender: convert.ToUser(ctx, doer, nil),
  196. }).
  197. WithPullRequest(issue.PullRequest).
  198. Notify(ctx)
  199. return
  200. }
  201. permission, _ := access_model.GetUserRepoPermission(ctx, issue.Repo, issue.Poster)
  202. newNotifyInputFromIssue(issue, event).
  203. WithDoer(doer).
  204. WithPayload(&api.IssuePayload{
  205. Action: action,
  206. Index: issue.Index,
  207. Issue: convert.ToAPIIssue(ctx, issue),
  208. Repository: convert.ToRepo(ctx, issue.Repo, permission),
  209. Sender: convert.ToUser(ctx, doer, nil),
  210. }).
  211. Notify(ctx)
  212. }
  213. // CreateIssueComment notifies comment on an issue to notifiers
  214. func (n *actionsNotifier) CreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository,
  215. issue *issues_model.Issue, comment *issues_model.Comment, _ []*user_model.User,
  216. ) {
  217. ctx = withMethod(ctx, "CreateIssueComment")
  218. if issue.IsPull {
  219. notifyIssueCommentChange(ctx, doer, comment, "", webhook_module.HookEventPullRequestComment, api.HookIssueCommentCreated)
  220. return
  221. }
  222. notifyIssueCommentChange(ctx, doer, comment, "", webhook_module.HookEventIssueComment, api.HookIssueCommentCreated)
  223. }
  224. func (n *actionsNotifier) UpdateComment(ctx context.Context, doer *user_model.User, c *issues_model.Comment, oldContent string) {
  225. ctx = withMethod(ctx, "UpdateComment")
  226. if err := c.LoadIssue(ctx); err != nil {
  227. log.Error("LoadIssue: %v", err)
  228. return
  229. }
  230. if c.Issue.IsPull {
  231. notifyIssueCommentChange(ctx, doer, c, oldContent, webhook_module.HookEventPullRequestComment, api.HookIssueCommentEdited)
  232. return
  233. }
  234. notifyIssueCommentChange(ctx, doer, c, oldContent, webhook_module.HookEventIssueComment, api.HookIssueCommentEdited)
  235. }
  236. func (n *actionsNotifier) DeleteComment(ctx context.Context, doer *user_model.User, comment *issues_model.Comment) {
  237. ctx = withMethod(ctx, "DeleteComment")
  238. if err := comment.LoadIssue(ctx); err != nil {
  239. log.Error("LoadIssue: %v", err)
  240. return
  241. }
  242. if comment.Issue.IsPull {
  243. notifyIssueCommentChange(ctx, doer, comment, "", webhook_module.HookEventPullRequestComment, api.HookIssueCommentDeleted)
  244. return
  245. }
  246. notifyIssueCommentChange(ctx, doer, comment, "", webhook_module.HookEventIssueComment, api.HookIssueCommentDeleted)
  247. }
  248. func notifyIssueCommentChange(ctx context.Context, doer *user_model.User, comment *issues_model.Comment, oldContent string, event webhook_module.HookEventType, action api.HookIssueCommentAction) {
  249. if err := comment.LoadIssue(ctx); err != nil {
  250. log.Error("LoadIssue: %v", err)
  251. return
  252. }
  253. if err := comment.Issue.LoadAttributes(ctx); err != nil {
  254. log.Error("LoadAttributes: %v", err)
  255. return
  256. }
  257. permission, _ := access_model.GetUserRepoPermission(ctx, comment.Issue.Repo, doer)
  258. payload := &api.IssueCommentPayload{
  259. Action: action,
  260. Issue: convert.ToAPIIssue(ctx, comment.Issue),
  261. Comment: convert.ToAPIComment(ctx, comment.Issue.Repo, comment),
  262. Repository: convert.ToRepo(ctx, comment.Issue.Repo, permission),
  263. Sender: convert.ToUser(ctx, doer, nil),
  264. IsPull: comment.Issue.IsPull,
  265. }
  266. if action == api.HookIssueCommentEdited {
  267. payload.Changes = &api.ChangesPayload{
  268. Body: &api.ChangesFromPayload{
  269. From: oldContent,
  270. },
  271. }
  272. }
  273. if comment.Issue.IsPull {
  274. if err := comment.Issue.LoadPullRequest(ctx); err != nil {
  275. log.Error("LoadPullRequest: %v", err)
  276. return
  277. }
  278. newNotifyInputFromIssue(comment.Issue, event).
  279. WithDoer(doer).
  280. WithPayload(payload).
  281. WithPullRequest(comment.Issue.PullRequest).
  282. Notify(ctx)
  283. return
  284. }
  285. newNotifyInputFromIssue(comment.Issue, event).
  286. WithDoer(doer).
  287. WithPayload(payload).
  288. Notify(ctx)
  289. }
  290. func (n *actionsNotifier) NewPullRequest(ctx context.Context, pull *issues_model.PullRequest, _ []*user_model.User) {
  291. ctx = withMethod(ctx, "NewPullRequest")
  292. if err := pull.LoadIssue(ctx); err != nil {
  293. log.Error("pull.LoadIssue: %v", err)
  294. return
  295. }
  296. if err := pull.Issue.LoadRepo(ctx); err != nil {
  297. log.Error("pull.Issue.LoadRepo: %v", err)
  298. return
  299. }
  300. if err := pull.Issue.LoadPoster(ctx); err != nil {
  301. log.Error("pull.Issue.LoadPoster: %v", err)
  302. return
  303. }
  304. permission, _ := access_model.GetUserRepoPermission(ctx, pull.Issue.Repo, pull.Issue.Poster)
  305. newNotifyInputFromIssue(pull.Issue, webhook_module.HookEventPullRequest).
  306. WithPayload(&api.PullRequestPayload{
  307. Action: api.HookIssueOpened,
  308. Index: pull.Issue.Index,
  309. PullRequest: convert.ToAPIPullRequest(ctx, pull, nil),
  310. Repository: convert.ToRepo(ctx, pull.Issue.Repo, permission),
  311. Sender: convert.ToUser(ctx, pull.Issue.Poster, nil),
  312. }).
  313. WithPullRequest(pull).
  314. Notify(ctx)
  315. }
  316. func (n *actionsNotifier) CreateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) {
  317. ctx = withMethod(ctx, "CreateRepository")
  318. newNotifyInput(repo, doer, webhook_module.HookEventRepository).WithPayload(&api.RepositoryPayload{
  319. Action: api.HookRepoCreated,
  320. Repository: convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm_model.AccessModeOwner}),
  321. Organization: convert.ToUser(ctx, u, nil),
  322. Sender: convert.ToUser(ctx, doer, nil),
  323. }).Notify(ctx)
  324. }
  325. func (n *actionsNotifier) ForkRepository(ctx context.Context, doer *user_model.User, oldRepo, repo *repo_model.Repository) {
  326. ctx = withMethod(ctx, "ForkRepository")
  327. oldPermission, _ := access_model.GetUserRepoPermission(ctx, oldRepo, doer)
  328. permission, _ := access_model.GetUserRepoPermission(ctx, repo, doer)
  329. // forked webhook
  330. newNotifyInput(oldRepo, doer, webhook_module.HookEventFork).WithPayload(&api.ForkPayload{
  331. Forkee: convert.ToRepo(ctx, oldRepo, oldPermission),
  332. Repo: convert.ToRepo(ctx, repo, permission),
  333. Sender: convert.ToUser(ctx, doer, nil),
  334. }).Notify(ctx)
  335. u := repo.MustOwner(ctx)
  336. // Add to hook queue for created repo after session commit.
  337. if u.IsOrganization() {
  338. newNotifyInput(repo, doer, webhook_module.HookEventRepository).
  339. WithRef(oldRepo.DefaultBranch).
  340. WithPayload(&api.RepositoryPayload{
  341. Action: api.HookRepoCreated,
  342. Repository: convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm_model.AccessModeOwner}),
  343. Organization: convert.ToUser(ctx, u, nil),
  344. Sender: convert.ToUser(ctx, doer, nil),
  345. }).Notify(ctx)
  346. }
  347. }
  348. func (n *actionsNotifier) PullRequestReview(ctx context.Context, pr *issues_model.PullRequest, review *issues_model.Review, _ *issues_model.Comment, _ []*user_model.User) {
  349. ctx = withMethod(ctx, "PullRequestReview")
  350. var reviewHookType webhook_module.HookEventType
  351. switch review.Type {
  352. case issues_model.ReviewTypeApprove:
  353. reviewHookType = webhook_module.HookEventPullRequestReviewApproved
  354. case issues_model.ReviewTypeComment:
  355. reviewHookType = webhook_module.HookEventPullRequestReviewComment
  356. case issues_model.ReviewTypeReject:
  357. reviewHookType = webhook_module.HookEventPullRequestReviewRejected
  358. default:
  359. // unsupported review webhook type here
  360. log.Error("Unsupported review webhook type")
  361. return
  362. }
  363. if err := pr.LoadIssue(ctx); err != nil {
  364. log.Error("pr.LoadIssue: %v", err)
  365. return
  366. }
  367. permission, err := access_model.GetUserRepoPermission(ctx, review.Issue.Repo, review.Issue.Poster)
  368. if err != nil {
  369. log.Error("models.GetUserRepoPermission: %v", err)
  370. return
  371. }
  372. newNotifyInput(review.Issue.Repo, review.Reviewer, reviewHookType).
  373. WithRef(review.CommitID).
  374. WithPayload(&api.PullRequestPayload{
  375. Action: api.HookIssueReviewed,
  376. Index: review.Issue.Index,
  377. PullRequest: convert.ToAPIPullRequest(db.DefaultContext, pr, nil),
  378. Repository: convert.ToRepo(ctx, review.Issue.Repo, permission),
  379. Sender: convert.ToUser(ctx, review.Reviewer, nil),
  380. Review: &api.ReviewPayload{
  381. Type: string(reviewHookType),
  382. Content: review.Content,
  383. },
  384. }).Notify(ctx)
  385. }
  386. func (n *actionsNotifier) PullRequestReviewRequest(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, reviewer *user_model.User, isRequest bool, comment *issues_model.Comment) {
  387. if !issue.IsPull {
  388. log.Warn("PullRequestReviewRequest: issue is not a pull request: %v", issue.ID)
  389. return
  390. }
  391. ctx = withMethod(ctx, "PullRequestReviewRequest")
  392. permission, _ := access_model.GetUserRepoPermission(ctx, issue.Repo, doer)
  393. if err := issue.LoadPullRequest(ctx); err != nil {
  394. log.Error("LoadPullRequest failed: %v", err)
  395. return
  396. }
  397. var action api.HookIssueAction
  398. if isRequest {
  399. action = api.HookIssueReviewRequested
  400. } else {
  401. action = api.HookIssueReviewRequestRemoved
  402. }
  403. newNotifyInputFromIssue(issue, webhook_module.HookEventPullRequestReviewRequest).
  404. WithDoer(doer).
  405. WithPayload(&api.PullRequestPayload{
  406. Action: action,
  407. Index: issue.Index,
  408. PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil),
  409. RequestedReviewer: convert.ToUser(ctx, reviewer, nil),
  410. Repository: convert.ToRepo(ctx, issue.Repo, permission),
  411. Sender: convert.ToUser(ctx, doer, nil),
  412. }).
  413. WithPullRequest(issue.PullRequest).
  414. Notify(ctx)
  415. }
  416. func (*actionsNotifier) MergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) {
  417. ctx = withMethod(ctx, "MergePullRequest")
  418. // Reload pull request information.
  419. if err := pr.LoadAttributes(ctx); err != nil {
  420. log.Error("LoadAttributes: %v", err)
  421. return
  422. }
  423. if err := pr.LoadIssue(ctx); err != nil {
  424. log.Error("LoadAttributes: %v", err)
  425. return
  426. }
  427. if err := pr.Issue.LoadRepo(db.DefaultContext); err != nil {
  428. log.Error("pr.Issue.LoadRepo: %v", err)
  429. return
  430. }
  431. permission, err := access_model.GetUserRepoPermission(ctx, pr.Issue.Repo, doer)
  432. if err != nil {
  433. log.Error("models.GetUserRepoPermission: %v", err)
  434. return
  435. }
  436. // Merge pull request calls issue.changeStatus so we need to handle separately.
  437. apiPullRequest := &api.PullRequestPayload{
  438. Index: pr.Issue.Index,
  439. PullRequest: convert.ToAPIPullRequest(db.DefaultContext, pr, nil),
  440. Repository: convert.ToRepo(ctx, pr.Issue.Repo, permission),
  441. Sender: convert.ToUser(ctx, doer, nil),
  442. Action: api.HookIssueClosed,
  443. }
  444. newNotifyInput(pr.Issue.Repo, doer, webhook_module.HookEventPullRequest).
  445. WithRef(pr.MergedCommitID).
  446. WithPayload(apiPullRequest).
  447. WithPullRequest(pr).
  448. Notify(ctx)
  449. }
  450. func (n *actionsNotifier) PushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) {
  451. commitID, _ := git.NewIDFromString(opts.NewCommitID)
  452. if commitID.IsZero() {
  453. log.Trace("new commitID is empty")
  454. return
  455. }
  456. ctx = withMethod(ctx, "PushCommits")
  457. apiPusher := convert.ToUser(ctx, pusher, nil)
  458. apiCommits, apiHeadCommit, err := commits.ToAPIPayloadCommits(ctx, repo.RepoPath(), repo.HTMLURL())
  459. if err != nil {
  460. log.Error("commits.ToAPIPayloadCommits failed: %v", err)
  461. return
  462. }
  463. newNotifyInput(repo, pusher, webhook_module.HookEventPush).
  464. WithRef(opts.RefFullName.String()).
  465. WithPayload(&api.PushPayload{
  466. Ref: opts.RefFullName.String(),
  467. Before: opts.OldCommitID,
  468. After: opts.NewCommitID,
  469. CompareURL: setting.AppURL + commits.CompareURL,
  470. Commits: apiCommits,
  471. HeadCommit: apiHeadCommit,
  472. Repo: convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm_model.AccessModeOwner}),
  473. Pusher: apiPusher,
  474. Sender: apiPusher,
  475. }).
  476. Notify(ctx)
  477. }
  478. func (n *actionsNotifier) CreateRef(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, refFullName git.RefName, refID string) {
  479. ctx = withMethod(ctx, "CreateRef")
  480. apiPusher := convert.ToUser(ctx, pusher, nil)
  481. apiRepo := convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm_model.AccessModeNone})
  482. newNotifyInput(repo, pusher, webhook_module.HookEventCreate).
  483. WithRef(refFullName.String()).
  484. WithPayload(&api.CreatePayload{
  485. Ref: refFullName.String(),
  486. Sha: refID,
  487. RefType: refFullName.RefType(),
  488. Repo: apiRepo,
  489. Sender: apiPusher,
  490. }).
  491. Notify(ctx)
  492. }
  493. func (n *actionsNotifier) DeleteRef(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, refFullName git.RefName) {
  494. ctx = withMethod(ctx, "DeleteRef")
  495. apiPusher := convert.ToUser(ctx, pusher, nil)
  496. apiRepo := convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm_model.AccessModeNone})
  497. newNotifyInput(repo, pusher, webhook_module.HookEventDelete).
  498. WithPayload(&api.DeletePayload{
  499. Ref: refFullName.String(),
  500. RefType: refFullName.RefType(),
  501. PusherType: api.PusherTypeUser,
  502. Repo: apiRepo,
  503. Sender: apiPusher,
  504. }).
  505. Notify(ctx)
  506. }
  507. func (n *actionsNotifier) SyncPushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) {
  508. ctx = withMethod(ctx, "SyncPushCommits")
  509. apiPusher := convert.ToUser(ctx, pusher, nil)
  510. apiCommits, apiHeadCommit, err := commits.ToAPIPayloadCommits(db.DefaultContext, repo.RepoPath(), repo.HTMLURL())
  511. if err != nil {
  512. log.Error("commits.ToAPIPayloadCommits failed: %v", err)
  513. return
  514. }
  515. newNotifyInput(repo, pusher, webhook_module.HookEventPush).
  516. WithRef(opts.RefFullName.String()).
  517. WithPayload(&api.PushPayload{
  518. Ref: opts.RefFullName.String(),
  519. Before: opts.OldCommitID,
  520. After: opts.NewCommitID,
  521. CompareURL: setting.AppURL + commits.CompareURL,
  522. Commits: apiCommits,
  523. TotalCommits: commits.Len,
  524. HeadCommit: apiHeadCommit,
  525. Repo: convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm_model.AccessModeOwner}),
  526. Pusher: apiPusher,
  527. Sender: apiPusher,
  528. }).
  529. Notify(ctx)
  530. }
  531. func (n *actionsNotifier) SyncCreateRef(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, refFullName git.RefName, refID string) {
  532. ctx = withMethod(ctx, "SyncCreateRef")
  533. n.CreateRef(ctx, pusher, repo, refFullName, refID)
  534. }
  535. func (n *actionsNotifier) SyncDeleteRef(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, refFullName git.RefName) {
  536. ctx = withMethod(ctx, "SyncDeleteRef")
  537. n.DeleteRef(ctx, pusher, repo, refFullName)
  538. }
  539. func (n *actionsNotifier) NewRelease(ctx context.Context, rel *repo_model.Release) {
  540. ctx = withMethod(ctx, "NewRelease")
  541. notifyRelease(ctx, rel.Publisher, rel, api.HookReleasePublished)
  542. }
  543. func (n *actionsNotifier) UpdateRelease(ctx context.Context, doer *user_model.User, rel *repo_model.Release) {
  544. ctx = withMethod(ctx, "UpdateRelease")
  545. notifyRelease(ctx, doer, rel, api.HookReleaseUpdated)
  546. }
  547. func (n *actionsNotifier) DeleteRelease(ctx context.Context, doer *user_model.User, rel *repo_model.Release) {
  548. if rel.IsTag {
  549. // has sent same action in `PushCommits`, so skip it.
  550. return
  551. }
  552. ctx = withMethod(ctx, "DeleteRelease")
  553. notifyRelease(ctx, doer, rel, api.HookReleaseDeleted)
  554. }
  555. func (n *actionsNotifier) PackageCreate(ctx context.Context, doer *user_model.User, pd *packages_model.PackageDescriptor) {
  556. ctx = withMethod(ctx, "PackageCreate")
  557. notifyPackage(ctx, doer, pd, api.HookPackageCreated)
  558. }
  559. func (n *actionsNotifier) PackageDelete(ctx context.Context, doer *user_model.User, pd *packages_model.PackageDescriptor) {
  560. ctx = withMethod(ctx, "PackageDelete")
  561. notifyPackage(ctx, doer, pd, api.HookPackageDeleted)
  562. }
  563. func (n *actionsNotifier) AutoMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) {
  564. ctx = withMethod(ctx, "AutoMergePullRequest")
  565. n.MergePullRequest(ctx, doer, pr)
  566. }
  567. func (n *actionsNotifier) PullRequestSynchronized(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) {
  568. ctx = withMethod(ctx, "PullRequestSynchronized")
  569. if err := pr.LoadIssue(ctx); err != nil {
  570. log.Error("LoadAttributes: %v", err)
  571. return
  572. }
  573. if err := pr.Issue.LoadRepo(db.DefaultContext); err != nil {
  574. log.Error("pr.Issue.LoadRepo: %v", err)
  575. return
  576. }
  577. newNotifyInput(pr.Issue.Repo, doer, webhook_module.HookEventPullRequestSync).
  578. WithPayload(&api.PullRequestPayload{
  579. Action: api.HookIssueSynchronized,
  580. Index: pr.Issue.Index,
  581. PullRequest: convert.ToAPIPullRequest(ctx, pr, nil),
  582. Repository: convert.ToRepo(ctx, pr.Issue.Repo, access_model.Permission{AccessMode: perm_model.AccessModeNone}),
  583. Sender: convert.ToUser(ctx, doer, nil),
  584. }).
  585. WithPullRequest(pr).
  586. Notify(ctx)
  587. }
  588. func (n *actionsNotifier) PullRequestChangeTargetBranch(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest, oldBranch string) {
  589. ctx = withMethod(ctx, "PullRequestChangeTargetBranch")
  590. if err := pr.LoadIssue(ctx); err != nil {
  591. log.Error("LoadAttributes: %v", err)
  592. return
  593. }
  594. if err := pr.Issue.LoadRepo(db.DefaultContext); err != nil {
  595. log.Error("pr.Issue.LoadRepo: %v", err)
  596. return
  597. }
  598. permission, _ := access_model.GetUserRepoPermission(ctx, pr.Issue.Repo, pr.Issue.Poster)
  599. newNotifyInput(pr.Issue.Repo, doer, webhook_module.HookEventPullRequest).
  600. WithPayload(&api.PullRequestPayload{
  601. Action: api.HookIssueEdited,
  602. Index: pr.Issue.Index,
  603. Changes: &api.ChangesPayload{
  604. Ref: &api.ChangesFromPayload{
  605. From: oldBranch,
  606. },
  607. },
  608. PullRequest: convert.ToAPIPullRequest(ctx, pr, nil),
  609. Repository: convert.ToRepo(ctx, pr.Issue.Repo, permission),
  610. Sender: convert.ToUser(ctx, doer, nil),
  611. }).
  612. WithPullRequest(pr).
  613. Notify(ctx)
  614. }
  615. func (n *actionsNotifier) NewWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page, comment string) {
  616. ctx = withMethod(ctx, "NewWikiPage")
  617. newNotifyInput(repo, doer, webhook_module.HookEventWiki).WithPayload(&api.WikiPayload{
  618. Action: api.HookWikiCreated,
  619. Repository: convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm_model.AccessModeOwner}),
  620. Sender: convert.ToUser(ctx, doer, nil),
  621. Page: page,
  622. Comment: comment,
  623. }).Notify(ctx)
  624. }
  625. func (n *actionsNotifier) EditWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page, comment string) {
  626. ctx = withMethod(ctx, "EditWikiPage")
  627. newNotifyInput(repo, doer, webhook_module.HookEventWiki).WithPayload(&api.WikiPayload{
  628. Action: api.HookWikiEdited,
  629. Repository: convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm_model.AccessModeOwner}),
  630. Sender: convert.ToUser(ctx, doer, nil),
  631. Page: page,
  632. Comment: comment,
  633. }).Notify(ctx)
  634. }
  635. func (n *actionsNotifier) DeleteWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page string) {
  636. ctx = withMethod(ctx, "DeleteWikiPage")
  637. newNotifyInput(repo, doer, webhook_module.HookEventWiki).WithPayload(&api.WikiPayload{
  638. Action: api.HookWikiDeleted,
  639. Repository: convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm_model.AccessModeOwner}),
  640. Sender: convert.ToUser(ctx, doer, nil),
  641. Page: page,
  642. }).Notify(ctx)
  643. }
  644. // MigrateRepository is used to detect workflows after a repository has been migrated
  645. func (n *actionsNotifier) MigrateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) {
  646. ctx = withMethod(ctx, "MigrateRepository")
  647. newNotifyInput(repo, doer, webhook_module.HookEventRepository).WithPayload(&api.RepositoryPayload{
  648. Action: api.HookRepoCreated,
  649. Repository: convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm_model.AccessModeOwner}),
  650. Organization: convert.ToUser(ctx, u, nil),
  651. Sender: convert.ToUser(ctx, doer, nil),
  652. }).Notify(ctx)
  653. }