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.

webhook.go 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  1. // Copyright 2019 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package webhook
  5. import (
  6. "code.gitea.io/gitea/models"
  7. "code.gitea.io/gitea/modules/git"
  8. "code.gitea.io/gitea/modules/log"
  9. "code.gitea.io/gitea/modules/notification/base"
  10. "code.gitea.io/gitea/modules/setting"
  11. api "code.gitea.io/gitea/modules/structs"
  12. webhook_module "code.gitea.io/gitea/modules/webhook"
  13. )
  14. type webhookNotifier struct {
  15. base.NullNotifier
  16. }
  17. var (
  18. _ base.Notifier = &webhookNotifier{}
  19. )
  20. // NewNotifier create a new webhookNotifier notifier
  21. func NewNotifier() base.Notifier {
  22. return &webhookNotifier{}
  23. }
  24. func (m *webhookNotifier) NotifyIssueClearLabels(doer *models.User, issue *models.Issue) {
  25. if err := issue.LoadPoster(); err != nil {
  26. log.Error("loadPoster: %v", err)
  27. return
  28. }
  29. if err := issue.LoadRepo(); err != nil {
  30. log.Error("LoadRepo: %v", err)
  31. return
  32. }
  33. mode, _ := models.AccessLevel(issue.Poster, issue.Repo)
  34. var err error
  35. if issue.IsPull {
  36. if err = issue.LoadPullRequest(); err != nil {
  37. log.Error("LoadPullRequest: %v", err)
  38. return
  39. }
  40. err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventPullRequest, &api.PullRequestPayload{
  41. Action: api.HookIssueLabelCleared,
  42. Index: issue.Index,
  43. PullRequest: issue.PullRequest.APIFormat(),
  44. Repository: issue.Repo.APIFormat(mode),
  45. Sender: doer.APIFormat(),
  46. })
  47. } else {
  48. err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventIssues, &api.IssuePayload{
  49. Action: api.HookIssueLabelCleared,
  50. Index: issue.Index,
  51. Issue: issue.APIFormat(),
  52. Repository: issue.Repo.APIFormat(mode),
  53. Sender: doer.APIFormat(),
  54. })
  55. }
  56. if err != nil {
  57. log.Error("PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
  58. }
  59. }
  60. func (m *webhookNotifier) NotifyForkRepository(doer *models.User, oldRepo, repo *models.Repository) {
  61. oldMode, _ := models.AccessLevel(doer, oldRepo)
  62. mode, _ := models.AccessLevel(doer, repo)
  63. // forked webhook
  64. if err := webhook_module.PrepareWebhooks(oldRepo, models.HookEventFork, &api.ForkPayload{
  65. Forkee: oldRepo.APIFormat(oldMode),
  66. Repo: repo.APIFormat(mode),
  67. Sender: doer.APIFormat(),
  68. }); err != nil {
  69. log.Error("PrepareWebhooks [repo_id: %d]: %v", oldRepo.ID, err)
  70. }
  71. u := repo.MustOwner()
  72. // Add to hook queue for created repo after session commit.
  73. if u.IsOrganization() {
  74. if err := webhook_module.PrepareWebhooks(repo, models.HookEventRepository, &api.RepositoryPayload{
  75. Action: api.HookRepoCreated,
  76. Repository: repo.APIFormat(models.AccessModeOwner),
  77. Organization: u.APIFormat(),
  78. Sender: doer.APIFormat(),
  79. }); err != nil {
  80. log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err)
  81. }
  82. }
  83. }
  84. func (m *webhookNotifier) NotifyCreateRepository(doer *models.User, u *models.User, repo *models.Repository) {
  85. // Add to hook queue for created repo after session commit.
  86. if u.IsOrganization() {
  87. if err := webhook_module.PrepareWebhooks(repo, models.HookEventRepository, &api.RepositoryPayload{
  88. Action: api.HookRepoCreated,
  89. Repository: repo.APIFormat(models.AccessModeOwner),
  90. Organization: u.APIFormat(),
  91. Sender: doer.APIFormat(),
  92. }); err != nil {
  93. log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err)
  94. }
  95. }
  96. }
  97. func (m *webhookNotifier) NotifyDeleteRepository(doer *models.User, repo *models.Repository) {
  98. u := repo.MustOwner()
  99. if u.IsOrganization() {
  100. if err := webhook_module.PrepareWebhooks(repo, models.HookEventRepository, &api.RepositoryPayload{
  101. Action: api.HookRepoDeleted,
  102. Repository: repo.APIFormat(models.AccessModeOwner),
  103. Organization: u.APIFormat(),
  104. Sender: doer.APIFormat(),
  105. }); err != nil {
  106. log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err)
  107. }
  108. }
  109. }
  110. func (m *webhookNotifier) NotifyIssueChangeAssignee(doer *models.User, issue *models.Issue, assignee *models.User, removed bool, comment *models.Comment) {
  111. if issue.IsPull {
  112. mode, _ := models.AccessLevelUnit(doer, issue.Repo, models.UnitTypePullRequests)
  113. if err := issue.LoadPullRequest(); err != nil {
  114. log.Error("LoadPullRequest failed: %v", err)
  115. return
  116. }
  117. issue.PullRequest.Issue = issue
  118. apiPullRequest := &api.PullRequestPayload{
  119. Index: issue.Index,
  120. PullRequest: issue.PullRequest.APIFormat(),
  121. Repository: issue.Repo.APIFormat(mode),
  122. Sender: doer.APIFormat(),
  123. }
  124. if removed {
  125. apiPullRequest.Action = api.HookIssueUnassigned
  126. } else {
  127. apiPullRequest.Action = api.HookIssueAssigned
  128. }
  129. // Assignee comment triggers a webhook
  130. if err := webhook_module.PrepareWebhooks(issue.Repo, models.HookEventPullRequest, apiPullRequest); err != nil {
  131. log.Error("PrepareWebhooks [is_pull: %v, remove_assignee: %v]: %v", issue.IsPull, removed, err)
  132. return
  133. }
  134. } else {
  135. mode, _ := models.AccessLevelUnit(doer, issue.Repo, models.UnitTypeIssues)
  136. apiIssue := &api.IssuePayload{
  137. Index: issue.Index,
  138. Issue: issue.APIFormat(),
  139. Repository: issue.Repo.APIFormat(mode),
  140. Sender: doer.APIFormat(),
  141. }
  142. if removed {
  143. apiIssue.Action = api.HookIssueUnassigned
  144. } else {
  145. apiIssue.Action = api.HookIssueAssigned
  146. }
  147. // Assignee comment triggers a webhook
  148. if err := webhook_module.PrepareWebhooks(issue.Repo, models.HookEventIssues, apiIssue); err != nil {
  149. log.Error("PrepareWebhooks [is_pull: %v, remove_assignee: %v]: %v", issue.IsPull, removed, err)
  150. return
  151. }
  152. }
  153. }
  154. func (m *webhookNotifier) NotifyIssueChangeTitle(doer *models.User, issue *models.Issue, oldTitle string) {
  155. mode, _ := models.AccessLevel(issue.Poster, issue.Repo)
  156. var err error
  157. if issue.IsPull {
  158. if err = issue.LoadPullRequest(); err != nil {
  159. log.Error("LoadPullRequest failed: %v", err)
  160. return
  161. }
  162. issue.PullRequest.Issue = issue
  163. err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventPullRequest, &api.PullRequestPayload{
  164. Action: api.HookIssueEdited,
  165. Index: issue.Index,
  166. Changes: &api.ChangesPayload{
  167. Title: &api.ChangesFromPayload{
  168. From: oldTitle,
  169. },
  170. },
  171. PullRequest: issue.PullRequest.APIFormat(),
  172. Repository: issue.Repo.APIFormat(mode),
  173. Sender: doer.APIFormat(),
  174. })
  175. } else {
  176. err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventIssues, &api.IssuePayload{
  177. Action: api.HookIssueEdited,
  178. Index: issue.Index,
  179. Changes: &api.ChangesPayload{
  180. Title: &api.ChangesFromPayload{
  181. From: oldTitle,
  182. },
  183. },
  184. Issue: issue.APIFormat(),
  185. Repository: issue.Repo.APIFormat(mode),
  186. Sender: issue.Poster.APIFormat(),
  187. })
  188. }
  189. if err != nil {
  190. log.Error("PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
  191. }
  192. }
  193. func (m *webhookNotifier) NotifyIssueChangeStatus(doer *models.User, issue *models.Issue, isClosed bool) {
  194. mode, _ := models.AccessLevel(issue.Poster, issue.Repo)
  195. var err error
  196. if issue.IsPull {
  197. if err = issue.LoadPullRequest(); err != nil {
  198. log.Error("LoadPullRequest: %v", err)
  199. return
  200. }
  201. // Merge pull request calls issue.changeStatus so we need to handle separately.
  202. apiPullRequest := &api.PullRequestPayload{
  203. Index: issue.Index,
  204. PullRequest: issue.PullRequest.APIFormat(),
  205. Repository: issue.Repo.APIFormat(mode),
  206. Sender: doer.APIFormat(),
  207. }
  208. if isClosed {
  209. apiPullRequest.Action = api.HookIssueClosed
  210. } else {
  211. apiPullRequest.Action = api.HookIssueReOpened
  212. }
  213. err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventPullRequest, apiPullRequest)
  214. } else {
  215. apiIssue := &api.IssuePayload{
  216. Index: issue.Index,
  217. Issue: issue.APIFormat(),
  218. Repository: issue.Repo.APIFormat(mode),
  219. Sender: doer.APIFormat(),
  220. }
  221. if isClosed {
  222. apiIssue.Action = api.HookIssueClosed
  223. } else {
  224. apiIssue.Action = api.HookIssueReOpened
  225. }
  226. err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventIssues, apiIssue)
  227. }
  228. if err != nil {
  229. log.Error("PrepareWebhooks [is_pull: %v, is_closed: %v]: %v", issue.IsPull, isClosed, err)
  230. }
  231. }
  232. func (m *webhookNotifier) NotifyNewIssue(issue *models.Issue) {
  233. if err := issue.LoadRepo(); err != nil {
  234. log.Error("issue.LoadRepo: %v", err)
  235. return
  236. }
  237. if err := issue.LoadPoster(); err != nil {
  238. log.Error("issue.LoadPoster: %v", err)
  239. return
  240. }
  241. mode, _ := models.AccessLevel(issue.Poster, issue.Repo)
  242. if err := webhook_module.PrepareWebhooks(issue.Repo, models.HookEventIssues, &api.IssuePayload{
  243. Action: api.HookIssueOpened,
  244. Index: issue.Index,
  245. Issue: issue.APIFormat(),
  246. Repository: issue.Repo.APIFormat(mode),
  247. Sender: issue.Poster.APIFormat(),
  248. }); err != nil {
  249. log.Error("PrepareWebhooks: %v", err)
  250. }
  251. }
  252. func (m *webhookNotifier) NotifyNewPullRequest(pull *models.PullRequest) {
  253. if err := pull.LoadIssue(); err != nil {
  254. log.Error("pull.LoadIssue: %v", err)
  255. return
  256. }
  257. if err := pull.Issue.LoadRepo(); err != nil {
  258. log.Error("pull.Issue.LoadRepo: %v", err)
  259. return
  260. }
  261. if err := pull.Issue.LoadPoster(); err != nil {
  262. log.Error("pull.Issue.LoadPoster: %v", err)
  263. return
  264. }
  265. mode, _ := models.AccessLevel(pull.Issue.Poster, pull.Issue.Repo)
  266. if err := webhook_module.PrepareWebhooks(pull.Issue.Repo, models.HookEventPullRequest, &api.PullRequestPayload{
  267. Action: api.HookIssueOpened,
  268. Index: pull.Issue.Index,
  269. PullRequest: pull.APIFormat(),
  270. Repository: pull.Issue.Repo.APIFormat(mode),
  271. Sender: pull.Issue.Poster.APIFormat(),
  272. }); err != nil {
  273. log.Error("PrepareWebhooks: %v", err)
  274. }
  275. }
  276. func (m *webhookNotifier) NotifyIssueChangeContent(doer *models.User, issue *models.Issue, oldContent string) {
  277. mode, _ := models.AccessLevel(issue.Poster, issue.Repo)
  278. var err error
  279. if issue.IsPull {
  280. issue.PullRequest.Issue = issue
  281. err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventPullRequest, &api.PullRequestPayload{
  282. Action: api.HookIssueEdited,
  283. Index: issue.Index,
  284. Changes: &api.ChangesPayload{
  285. Body: &api.ChangesFromPayload{
  286. From: oldContent,
  287. },
  288. },
  289. PullRequest: issue.PullRequest.APIFormat(),
  290. Repository: issue.Repo.APIFormat(mode),
  291. Sender: doer.APIFormat(),
  292. })
  293. } else {
  294. err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventIssues, &api.IssuePayload{
  295. Action: api.HookIssueEdited,
  296. Index: issue.Index,
  297. Changes: &api.ChangesPayload{
  298. Body: &api.ChangesFromPayload{
  299. From: oldContent,
  300. },
  301. },
  302. Issue: issue.APIFormat(),
  303. Repository: issue.Repo.APIFormat(mode),
  304. Sender: doer.APIFormat(),
  305. })
  306. }
  307. if err != nil {
  308. log.Error("PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
  309. }
  310. }
  311. func (m *webhookNotifier) NotifyUpdateComment(doer *models.User, c *models.Comment, oldContent string) {
  312. if err := c.LoadPoster(); err != nil {
  313. log.Error("LoadPoster: %v", err)
  314. return
  315. }
  316. if err := c.LoadIssue(); err != nil {
  317. log.Error("LoadIssue: %v", err)
  318. return
  319. }
  320. if err := c.Issue.LoadAttributes(); err != nil {
  321. log.Error("LoadAttributes: %v", err)
  322. return
  323. }
  324. mode, _ := models.AccessLevel(doer, c.Issue.Repo)
  325. if err := webhook_module.PrepareWebhooks(c.Issue.Repo, models.HookEventIssueComment, &api.IssueCommentPayload{
  326. Action: api.HookIssueCommentEdited,
  327. Issue: c.Issue.APIFormat(),
  328. Comment: c.APIFormat(),
  329. Changes: &api.ChangesPayload{
  330. Body: &api.ChangesFromPayload{
  331. From: oldContent,
  332. },
  333. },
  334. Repository: c.Issue.Repo.APIFormat(mode),
  335. Sender: doer.APIFormat(),
  336. IsPull: c.Issue.IsPull,
  337. }); err != nil {
  338. log.Error("PrepareWebhooks [comment_id: %d]: %v", c.ID, err)
  339. }
  340. }
  341. func (m *webhookNotifier) NotifyCreateIssueComment(doer *models.User, repo *models.Repository,
  342. issue *models.Issue, comment *models.Comment) {
  343. mode, _ := models.AccessLevel(doer, repo)
  344. if err := webhook_module.PrepareWebhooks(repo, models.HookEventIssueComment, &api.IssueCommentPayload{
  345. Action: api.HookIssueCommentCreated,
  346. Issue: issue.APIFormat(),
  347. Comment: comment.APIFormat(),
  348. Repository: repo.APIFormat(mode),
  349. Sender: doer.APIFormat(),
  350. IsPull: issue.IsPull,
  351. }); err != nil {
  352. log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err)
  353. }
  354. }
  355. func (m *webhookNotifier) NotifyDeleteComment(doer *models.User, comment *models.Comment) {
  356. if err := comment.LoadPoster(); err != nil {
  357. log.Error("LoadPoster: %v", err)
  358. return
  359. }
  360. if err := comment.LoadIssue(); err != nil {
  361. log.Error("LoadIssue: %v", err)
  362. return
  363. }
  364. if err := comment.Issue.LoadAttributes(); err != nil {
  365. log.Error("LoadAttributes: %v", err)
  366. return
  367. }
  368. mode, _ := models.AccessLevel(doer, comment.Issue.Repo)
  369. if err := webhook_module.PrepareWebhooks(comment.Issue.Repo, models.HookEventIssueComment, &api.IssueCommentPayload{
  370. Action: api.HookIssueCommentDeleted,
  371. Issue: comment.Issue.APIFormat(),
  372. Comment: comment.APIFormat(),
  373. Repository: comment.Issue.Repo.APIFormat(mode),
  374. Sender: doer.APIFormat(),
  375. IsPull: comment.Issue.IsPull,
  376. }); err != nil {
  377. log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err)
  378. }
  379. }
  380. func (m *webhookNotifier) NotifyIssueChangeLabels(doer *models.User, issue *models.Issue,
  381. addedLabels []*models.Label, removedLabels []*models.Label) {
  382. var err error
  383. if err = issue.LoadRepo(); err != nil {
  384. log.Error("LoadRepo: %v", err)
  385. return
  386. }
  387. if err = issue.LoadPoster(); err != nil {
  388. log.Error("LoadPoster: %v", err)
  389. return
  390. }
  391. mode, _ := models.AccessLevel(issue.Poster, issue.Repo)
  392. if issue.IsPull {
  393. if err = issue.LoadPullRequest(); err != nil {
  394. log.Error("loadPullRequest: %v", err)
  395. return
  396. }
  397. if err = issue.PullRequest.LoadIssue(); err != nil {
  398. log.Error("LoadIssue: %v", err)
  399. return
  400. }
  401. err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventPullRequest, &api.PullRequestPayload{
  402. Action: api.HookIssueLabelUpdated,
  403. Index: issue.Index,
  404. PullRequest: issue.PullRequest.APIFormat(),
  405. Repository: issue.Repo.APIFormat(models.AccessModeNone),
  406. Sender: doer.APIFormat(),
  407. })
  408. } else {
  409. err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventIssues, &api.IssuePayload{
  410. Action: api.HookIssueLabelUpdated,
  411. Index: issue.Index,
  412. Issue: issue.APIFormat(),
  413. Repository: issue.Repo.APIFormat(mode),
  414. Sender: doer.APIFormat(),
  415. })
  416. }
  417. if err != nil {
  418. log.Error("PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
  419. }
  420. }
  421. func (m *webhookNotifier) NotifyIssueChangeMilestone(doer *models.User, issue *models.Issue, oldMilestoneID int64) {
  422. var hookAction api.HookIssueAction
  423. var err error
  424. if issue.MilestoneID > 0 {
  425. hookAction = api.HookIssueMilestoned
  426. } else {
  427. hookAction = api.HookIssueDemilestoned
  428. }
  429. if err = issue.LoadAttributes(); err != nil {
  430. log.Error("issue.LoadAttributes failed: %v", err)
  431. return
  432. }
  433. mode, _ := models.AccessLevel(doer, issue.Repo)
  434. if issue.IsPull {
  435. err = issue.PullRequest.LoadIssue()
  436. if err != nil {
  437. log.Error("LoadIssue: %v", err)
  438. return
  439. }
  440. err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventPullRequest, &api.PullRequestPayload{
  441. Action: hookAction,
  442. Index: issue.Index,
  443. PullRequest: issue.PullRequest.APIFormat(),
  444. Repository: issue.Repo.APIFormat(mode),
  445. Sender: doer.APIFormat(),
  446. })
  447. } else {
  448. err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventIssues, &api.IssuePayload{
  449. Action: hookAction,
  450. Index: issue.Index,
  451. Issue: issue.APIFormat(),
  452. Repository: issue.Repo.APIFormat(mode),
  453. Sender: doer.APIFormat(),
  454. })
  455. }
  456. if err != nil {
  457. log.Error("PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
  458. }
  459. }
  460. func (m *webhookNotifier) NotifyPushCommits(pusher *models.User, repo *models.Repository, refName, oldCommitID, newCommitID string, commits *models.PushCommits) {
  461. apiPusher := pusher.APIFormat()
  462. apiCommits, err := commits.ToAPIPayloadCommits(repo.RepoPath(), repo.HTMLURL())
  463. if err != nil {
  464. log.Error("commits.ToAPIPayloadCommits failed: %v", err)
  465. return
  466. }
  467. if err := webhook_module.PrepareWebhooks(repo, models.HookEventPush, &api.PushPayload{
  468. Ref: refName,
  469. Before: oldCommitID,
  470. After: newCommitID,
  471. CompareURL: setting.AppURL + commits.CompareURL,
  472. Commits: apiCommits,
  473. Repo: repo.APIFormat(models.AccessModeOwner),
  474. Pusher: apiPusher,
  475. Sender: apiPusher,
  476. }); err != nil {
  477. log.Error("PrepareWebhooks: %v", err)
  478. }
  479. }
  480. func (m *webhookNotifier) NotifyPullRequestReview(pr *models.PullRequest, review *models.Review, comment *models.Comment) {
  481. var reviewHookType models.HookEventType
  482. switch review.Type {
  483. case models.ReviewTypeApprove:
  484. reviewHookType = models.HookEventPullRequestApproved
  485. case models.ReviewTypeComment:
  486. reviewHookType = models.HookEventPullRequestComment
  487. case models.ReviewTypeReject:
  488. reviewHookType = models.HookEventPullRequestRejected
  489. default:
  490. // unsupported review webhook type here
  491. log.Error("Unsupported review webhook type")
  492. return
  493. }
  494. if err := pr.LoadIssue(); err != nil {
  495. log.Error("pr.LoadIssue: %v", err)
  496. return
  497. }
  498. mode, err := models.AccessLevel(review.Issue.Poster, review.Issue.Repo)
  499. if err != nil {
  500. log.Error("models.AccessLevel: %v", err)
  501. return
  502. }
  503. if err := webhook_module.PrepareWebhooks(review.Issue.Repo, reviewHookType, &api.PullRequestPayload{
  504. Action: api.HookIssueSynchronized,
  505. Index: review.Issue.Index,
  506. PullRequest: pr.APIFormat(),
  507. Repository: review.Issue.Repo.APIFormat(mode),
  508. Sender: review.Reviewer.APIFormat(),
  509. Review: &api.ReviewPayload{
  510. Type: string(reviewHookType),
  511. Content: review.Content,
  512. },
  513. }); err != nil {
  514. log.Error("PrepareWebhooks: %v", err)
  515. }
  516. }
  517. func (m *webhookNotifier) NotifyCreateRef(pusher *models.User, repo *models.Repository, refType, refFullName string) {
  518. apiPusher := pusher.APIFormat()
  519. apiRepo := repo.APIFormat(models.AccessModeNone)
  520. refName := git.RefEndName(refFullName)
  521. gitRepo, err := git.OpenRepository(repo.RepoPath())
  522. if err != nil {
  523. log.Error("OpenRepository[%s]: %v", repo.RepoPath(), err)
  524. return
  525. }
  526. shaSum, err := gitRepo.GetBranchCommitID(refName)
  527. if err != nil {
  528. log.Error("GetBranchCommitID[%s]: %v", refFullName, err)
  529. return
  530. }
  531. if err = webhook_module.PrepareWebhooks(repo, models.HookEventCreate, &api.CreatePayload{
  532. Ref: refName,
  533. Sha: shaSum,
  534. RefType: refType,
  535. Repo: apiRepo,
  536. Sender: apiPusher,
  537. }); err != nil {
  538. log.Error("PrepareWebhooks: %v", err)
  539. }
  540. }
  541. func (m *webhookNotifier) NotifyPullRequestSynchronized(doer *models.User, pr *models.PullRequest) {
  542. if err := pr.LoadIssue(); err != nil {
  543. log.Error("pr.LoadIssue: %v", err)
  544. return
  545. }
  546. if err := pr.Issue.LoadAttributes(); err != nil {
  547. log.Error("LoadAttributes: %v", err)
  548. return
  549. }
  550. if err := webhook_module.PrepareWebhooks(pr.Issue.Repo, models.HookEventPullRequest, &api.PullRequestPayload{
  551. Action: api.HookIssueSynchronized,
  552. Index: pr.Issue.Index,
  553. PullRequest: pr.Issue.PullRequest.APIFormat(),
  554. Repository: pr.Issue.Repo.APIFormat(models.AccessModeNone),
  555. Sender: doer.APIFormat(),
  556. }); err != nil {
  557. log.Error("PrepareWebhooks [pull_id: %v]: %v", pr.ID, err)
  558. }
  559. }
  560. func (m *webhookNotifier) NotifyDeleteRef(pusher *models.User, repo *models.Repository, refType, refFullName string) {
  561. apiPusher := pusher.APIFormat()
  562. apiRepo := repo.APIFormat(models.AccessModeNone)
  563. refName := git.RefEndName(refFullName)
  564. if err := webhook_module.PrepareWebhooks(repo, models.HookEventDelete, &api.DeletePayload{
  565. Ref: refName,
  566. RefType: "branch",
  567. PusherType: api.PusherTypeUser,
  568. Repo: apiRepo,
  569. Sender: apiPusher,
  570. }); err != nil {
  571. log.Error("PrepareWebhooks.(delete branch): %v", err)
  572. }
  573. }
  574. func sendReleaseHook(doer *models.User, rel *models.Release, action api.HookReleaseAction) {
  575. if err := rel.LoadAttributes(); err != nil {
  576. log.Error("LoadAttributes: %v", err)
  577. return
  578. }
  579. mode, _ := models.AccessLevel(rel.Publisher, rel.Repo)
  580. if err := webhook_module.PrepareWebhooks(rel.Repo, models.HookEventRelease, &api.ReleasePayload{
  581. Action: action,
  582. Release: rel.APIFormat(),
  583. Repository: rel.Repo.APIFormat(mode),
  584. Sender: rel.Publisher.APIFormat(),
  585. }); err != nil {
  586. log.Error("PrepareWebhooks: %v", err)
  587. }
  588. }
  589. func (m *webhookNotifier) NotifyNewRelease(rel *models.Release) {
  590. sendReleaseHook(rel.Publisher, rel, api.HookReleasePublished)
  591. }
  592. func (m *webhookNotifier) NotifyUpdateRelease(doer *models.User, rel *models.Release) {
  593. sendReleaseHook(doer, rel, api.HookReleaseUpdated)
  594. }
  595. func (m *webhookNotifier) NotifyDeleteRelease(doer *models.User, rel *models.Release) {
  596. sendReleaseHook(doer, rel, api.HookReleaseDeleted)
  597. }