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

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