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 19KB

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