gitea源码

notifier.go 39KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058
  1. // Copyright 2019 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package webhook
  4. import (
  5. "context"
  6. actions_model "code.gitea.io/gitea/models/actions"
  7. git_model "code.gitea.io/gitea/models/git"
  8. issues_model "code.gitea.io/gitea/models/issues"
  9. "code.gitea.io/gitea/models/organization"
  10. packages_model "code.gitea.io/gitea/models/packages"
  11. "code.gitea.io/gitea/models/perm"
  12. access_model "code.gitea.io/gitea/models/perm/access"
  13. repo_model "code.gitea.io/gitea/models/repo"
  14. user_model "code.gitea.io/gitea/models/user"
  15. "code.gitea.io/gitea/modules/git"
  16. "code.gitea.io/gitea/modules/gitrepo"
  17. "code.gitea.io/gitea/modules/httplib"
  18. "code.gitea.io/gitea/modules/log"
  19. "code.gitea.io/gitea/modules/repository"
  20. "code.gitea.io/gitea/modules/setting"
  21. api "code.gitea.io/gitea/modules/structs"
  22. webhook_module "code.gitea.io/gitea/modules/webhook"
  23. "code.gitea.io/gitea/services/convert"
  24. notify_service "code.gitea.io/gitea/services/notify"
  25. )
  26. func init() {
  27. notify_service.RegisterNotifier(NewNotifier())
  28. }
  29. type webhookNotifier struct {
  30. notify_service.NullNotifier
  31. }
  32. var _ notify_service.Notifier = &webhookNotifier{}
  33. // NewNotifier create a new webhookNotifier notifier
  34. func NewNotifier() notify_service.Notifier {
  35. return &webhookNotifier{}
  36. }
  37. func (m *webhookNotifier) IssueClearLabels(ctx context.Context, doer *user_model.User, issue *issues_model.Issue) {
  38. if err := issue.LoadPoster(ctx); err != nil {
  39. log.Error("LoadPoster: %v", err)
  40. return
  41. }
  42. if err := issue.LoadRepo(ctx); err != nil {
  43. log.Error("LoadRepo: %v", err)
  44. return
  45. }
  46. permission, _ := access_model.GetUserRepoPermission(ctx, issue.Repo, issue.Poster)
  47. var err error
  48. if issue.IsPull {
  49. if err = issue.LoadPullRequest(ctx); err != nil {
  50. log.Error("LoadPullRequest: %v", err)
  51. return
  52. }
  53. err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventPullRequestLabel, &api.PullRequestPayload{
  54. Action: api.HookIssueLabelCleared,
  55. Index: issue.Index,
  56. PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, doer),
  57. Repository: convert.ToRepo(ctx, issue.Repo, permission),
  58. Sender: convert.ToUser(ctx, doer, nil),
  59. })
  60. } else {
  61. err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssueLabel, &api.IssuePayload{
  62. Action: api.HookIssueLabelCleared,
  63. Index: issue.Index,
  64. Issue: convert.ToAPIIssue(ctx, doer, issue),
  65. Repository: convert.ToRepo(ctx, issue.Repo, permission),
  66. Sender: convert.ToUser(ctx, doer, nil),
  67. })
  68. }
  69. if err != nil {
  70. log.Error("PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
  71. }
  72. }
  73. func (m *webhookNotifier) ForkRepository(ctx context.Context, doer *user_model.User, oldRepo, repo *repo_model.Repository) {
  74. oldPermission, _ := access_model.GetUserRepoPermission(ctx, oldRepo, doer)
  75. permission, _ := access_model.GetUserRepoPermission(ctx, repo, doer)
  76. // forked webhook
  77. if err := PrepareWebhooks(ctx, EventSource{Repository: oldRepo}, webhook_module.HookEventFork, &api.ForkPayload{
  78. Forkee: convert.ToRepo(ctx, oldRepo, oldPermission),
  79. Repo: convert.ToRepo(ctx, repo, permission),
  80. Sender: convert.ToUser(ctx, doer, nil),
  81. }); err != nil {
  82. log.Error("PrepareWebhooks [repo_id: %d]: %v", oldRepo.ID, err)
  83. }
  84. u := repo.MustOwner(ctx)
  85. // Add to hook queue for created repo after session commit.
  86. if u.IsOrganization() {
  87. if err := PrepareWebhooks(ctx, EventSource{Repository: repo}, webhook_module.HookEventRepository, &api.RepositoryPayload{
  88. Action: api.HookRepoCreated,
  89. Repository: convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm.AccessModeOwner}),
  90. Organization: convert.ToUser(ctx, u, nil),
  91. Sender: convert.ToUser(ctx, doer, nil),
  92. }); err != nil {
  93. log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err)
  94. }
  95. }
  96. }
  97. func (m *webhookNotifier) CreateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) {
  98. // Add to hook queue for created repo after session commit.
  99. if err := PrepareWebhooks(ctx, EventSource{Repository: repo}, webhook_module.HookEventRepository, &api.RepositoryPayload{
  100. Action: api.HookRepoCreated,
  101. Repository: convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm.AccessModeOwner}),
  102. Organization: convert.ToUser(ctx, u, nil),
  103. Sender: convert.ToUser(ctx, doer, nil),
  104. }); err != nil {
  105. log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err)
  106. }
  107. }
  108. func (m *webhookNotifier) DeleteRepository(ctx context.Context, doer *user_model.User, repo *repo_model.Repository) {
  109. if err := PrepareWebhooks(ctx, EventSource{Repository: repo}, webhook_module.HookEventRepository, &api.RepositoryPayload{
  110. Action: api.HookRepoDeleted,
  111. Repository: convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm.AccessModeOwner}),
  112. Organization: convert.ToUser(ctx, repo.MustOwner(ctx), nil),
  113. Sender: convert.ToUser(ctx, doer, nil),
  114. }); err != nil {
  115. log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err)
  116. }
  117. }
  118. func (m *webhookNotifier) MigrateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) {
  119. // Add to hook queue for created repo after session commit.
  120. if err := PrepareWebhooks(ctx, EventSource{Repository: repo}, webhook_module.HookEventRepository, &api.RepositoryPayload{
  121. Action: api.HookRepoCreated,
  122. Repository: convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm.AccessModeOwner}),
  123. Organization: convert.ToUser(ctx, u, nil),
  124. Sender: convert.ToUser(ctx, doer, nil),
  125. }); err != nil {
  126. log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err)
  127. }
  128. }
  129. func (m *webhookNotifier) IssueChangeAssignee(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, assignee *user_model.User, removed bool, comment *issues_model.Comment) {
  130. if issue.IsPull {
  131. permission, _ := access_model.GetUserRepoPermission(ctx, issue.Repo, doer)
  132. if err := issue.LoadPullRequest(ctx); err != nil {
  133. log.Error("LoadPullRequest failed: %v", err)
  134. return
  135. }
  136. apiPullRequest := &api.PullRequestPayload{
  137. Index: issue.Index,
  138. PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, doer),
  139. Repository: convert.ToRepo(ctx, issue.Repo, permission),
  140. Sender: convert.ToUser(ctx, doer, nil),
  141. }
  142. if removed {
  143. apiPullRequest.Action = api.HookIssueUnassigned
  144. } else {
  145. apiPullRequest.Action = api.HookIssueAssigned
  146. }
  147. // Assignee comment triggers a webhook
  148. if err := PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventPullRequestAssign, apiPullRequest); err != nil {
  149. log.Error("PrepareWebhooks [is_pull: %v, remove_assignee: %v]: %v", issue.IsPull, removed, err)
  150. return
  151. }
  152. } else {
  153. permission, _ := access_model.GetUserRepoPermission(ctx, issue.Repo, doer)
  154. apiIssue := &api.IssuePayload{
  155. Index: issue.Index,
  156. Issue: convert.ToAPIIssue(ctx, doer, issue),
  157. Repository: convert.ToRepo(ctx, issue.Repo, permission),
  158. Sender: convert.ToUser(ctx, doer, nil),
  159. }
  160. if removed {
  161. apiIssue.Action = api.HookIssueUnassigned
  162. } else {
  163. apiIssue.Action = api.HookIssueAssigned
  164. }
  165. // Assignee comment triggers a webhook
  166. if err := PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssueAssign, apiIssue); err != nil {
  167. log.Error("PrepareWebhooks [is_pull: %v, remove_assignee: %v]: %v", issue.IsPull, removed, err)
  168. return
  169. }
  170. }
  171. }
  172. func (m *webhookNotifier) IssueChangeTitle(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldTitle string) {
  173. permission, _ := access_model.GetUserRepoPermission(ctx, issue.Repo, issue.Poster)
  174. var err error
  175. if issue.IsPull {
  176. if err = issue.LoadPullRequest(ctx); err != nil {
  177. log.Error("LoadPullRequest failed: %v", err)
  178. return
  179. }
  180. err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventPullRequest, &api.PullRequestPayload{
  181. Action: api.HookIssueEdited,
  182. Index: issue.Index,
  183. Changes: &api.ChangesPayload{
  184. Title: &api.ChangesFromPayload{
  185. From: oldTitle,
  186. },
  187. },
  188. PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, doer),
  189. Repository: convert.ToRepo(ctx, issue.Repo, permission),
  190. Sender: convert.ToUser(ctx, doer, nil),
  191. })
  192. } else {
  193. err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssues, &api.IssuePayload{
  194. Action: api.HookIssueEdited,
  195. Index: issue.Index,
  196. Changes: &api.ChangesPayload{
  197. Title: &api.ChangesFromPayload{
  198. From: oldTitle,
  199. },
  200. },
  201. Issue: convert.ToAPIIssue(ctx, doer, issue),
  202. Repository: convert.ToRepo(ctx, issue.Repo, permission),
  203. Sender: convert.ToUser(ctx, doer, nil),
  204. })
  205. }
  206. if err != nil {
  207. log.Error("PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
  208. }
  209. }
  210. func (m *webhookNotifier) IssueChangeStatus(ctx context.Context, doer *user_model.User, commitID string, issue *issues_model.Issue, actionComment *issues_model.Comment, isClosed bool) {
  211. permission, _ := access_model.GetUserRepoPermission(ctx, issue.Repo, issue.Poster)
  212. var err error
  213. if issue.IsPull {
  214. if err = issue.LoadPullRequest(ctx); err != nil {
  215. log.Error("LoadPullRequest: %v", err)
  216. return
  217. }
  218. // Merge pull request calls issue.changeStatus so we need to handle separately.
  219. apiPullRequest := &api.PullRequestPayload{
  220. Index: issue.Index,
  221. PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, doer),
  222. Repository: convert.ToRepo(ctx, issue.Repo, permission),
  223. Sender: convert.ToUser(ctx, doer, nil),
  224. CommitID: commitID,
  225. }
  226. if isClosed {
  227. apiPullRequest.Action = api.HookIssueClosed
  228. } else {
  229. apiPullRequest.Action = api.HookIssueReOpened
  230. }
  231. err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventPullRequest, apiPullRequest)
  232. } else {
  233. apiIssue := &api.IssuePayload{
  234. Index: issue.Index,
  235. Issue: convert.ToAPIIssue(ctx, doer, issue),
  236. Repository: convert.ToRepo(ctx, issue.Repo, permission),
  237. Sender: convert.ToUser(ctx, doer, nil),
  238. CommitID: commitID,
  239. }
  240. if isClosed {
  241. apiIssue.Action = api.HookIssueClosed
  242. } else {
  243. apiIssue.Action = api.HookIssueReOpened
  244. }
  245. err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssues, apiIssue)
  246. }
  247. if err != nil {
  248. log.Error("PrepareWebhooks [is_pull: %v, is_closed: %v]: %v", issue.IsPull, isClosed, err)
  249. }
  250. }
  251. func (m *webhookNotifier) NewIssue(ctx context.Context, issue *issues_model.Issue, mentions []*user_model.User) {
  252. if err := issue.LoadRepo(ctx); err != nil {
  253. log.Error("issue.LoadRepo: %v", err)
  254. return
  255. }
  256. if err := issue.LoadPoster(ctx); err != nil {
  257. log.Error("issue.LoadPoster: %v", err)
  258. return
  259. }
  260. permission, _ := access_model.GetUserRepoPermission(ctx, issue.Repo, issue.Poster)
  261. if err := PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssues, &api.IssuePayload{
  262. Action: api.HookIssueOpened,
  263. Index: issue.Index,
  264. Issue: convert.ToAPIIssue(ctx, issue.Poster, issue),
  265. Repository: convert.ToRepo(ctx, issue.Repo, permission),
  266. Sender: convert.ToUser(ctx, issue.Poster, nil),
  267. }); err != nil {
  268. log.Error("PrepareWebhooks: %v", err)
  269. }
  270. }
  271. func (m *webhookNotifier) DeleteIssue(ctx context.Context, doer *user_model.User, issue *issues_model.Issue) {
  272. permission, _ := access_model.GetUserRepoPermission(ctx, issue.Repo, doer)
  273. if issue.IsPull {
  274. if err := issue.LoadPullRequest(ctx); err != nil {
  275. log.Error("LoadPullRequest: %v", err)
  276. return
  277. }
  278. if err := PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventPullRequest, &api.PullRequestPayload{
  279. Action: api.HookIssueDeleted,
  280. Index: issue.Index,
  281. PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, doer),
  282. Repository: convert.ToRepo(ctx, issue.Repo, permission),
  283. Sender: convert.ToUser(ctx, doer, nil),
  284. }); err != nil {
  285. log.Error("PrepareWebhooks: %v", err)
  286. }
  287. } else {
  288. if err := issue.LoadRepo(ctx); err != nil {
  289. log.Error("issue.LoadRepo: %v", err)
  290. return
  291. }
  292. if err := issue.LoadPoster(ctx); err != nil {
  293. log.Error("issue.LoadPoster: %v", err)
  294. return
  295. }
  296. if err := PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssues, &api.IssuePayload{
  297. Action: api.HookIssueDeleted,
  298. Index: issue.Index,
  299. Issue: convert.ToAPIIssue(ctx, issue.Poster, issue),
  300. Repository: convert.ToRepo(ctx, issue.Repo, permission),
  301. Sender: convert.ToUser(ctx, doer, nil),
  302. }); err != nil {
  303. log.Error("PrepareWebhooks: %v", err)
  304. }
  305. }
  306. }
  307. func (m *webhookNotifier) NewPullRequest(ctx context.Context, pull *issues_model.PullRequest, mentions []*user_model.User) {
  308. if err := pull.LoadIssue(ctx); err != nil {
  309. log.Error("pull.LoadIssue: %v", err)
  310. return
  311. }
  312. if err := pull.Issue.LoadRepo(ctx); err != nil {
  313. log.Error("pull.Issue.LoadRepo: %v", err)
  314. return
  315. }
  316. if err := pull.Issue.LoadPoster(ctx); err != nil {
  317. log.Error("pull.Issue.LoadPoster: %v", err)
  318. return
  319. }
  320. permission, _ := access_model.GetUserRepoPermission(ctx, pull.Issue.Repo, pull.Issue.Poster)
  321. if err := PrepareWebhooks(ctx, EventSource{Repository: pull.Issue.Repo}, webhook_module.HookEventPullRequest, &api.PullRequestPayload{
  322. Action: api.HookIssueOpened,
  323. Index: pull.Issue.Index,
  324. PullRequest: convert.ToAPIPullRequest(ctx, pull, pull.Issue.Poster),
  325. Repository: convert.ToRepo(ctx, pull.Issue.Repo, permission),
  326. Sender: convert.ToUser(ctx, pull.Issue.Poster, nil),
  327. }); err != nil {
  328. log.Error("PrepareWebhooks: %v", err)
  329. }
  330. }
  331. func (m *webhookNotifier) IssueChangeContent(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldContent string) {
  332. if err := issue.LoadRepo(ctx); err != nil {
  333. log.Error("LoadRepo: %v", err)
  334. return
  335. }
  336. permission, _ := access_model.GetUserRepoPermission(ctx, issue.Repo, issue.Poster)
  337. var err error
  338. if issue.IsPull {
  339. if err := issue.LoadPullRequest(ctx); err != nil {
  340. log.Error("LoadPullRequest: %v", err)
  341. return
  342. }
  343. err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventPullRequest, &api.PullRequestPayload{
  344. Action: api.HookIssueEdited,
  345. Index: issue.Index,
  346. Changes: &api.ChangesPayload{
  347. Body: &api.ChangesFromPayload{
  348. From: oldContent,
  349. },
  350. },
  351. PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, doer),
  352. Repository: convert.ToRepo(ctx, issue.Repo, permission),
  353. Sender: convert.ToUser(ctx, doer, nil),
  354. })
  355. } else {
  356. err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssues, &api.IssuePayload{
  357. Action: api.HookIssueEdited,
  358. Index: issue.Index,
  359. Changes: &api.ChangesPayload{
  360. Body: &api.ChangesFromPayload{
  361. From: oldContent,
  362. },
  363. },
  364. Issue: convert.ToAPIIssue(ctx, doer, issue),
  365. Repository: convert.ToRepo(ctx, issue.Repo, permission),
  366. Sender: convert.ToUser(ctx, doer, nil),
  367. })
  368. }
  369. if err != nil {
  370. log.Error("PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
  371. }
  372. }
  373. func (m *webhookNotifier) UpdateComment(ctx context.Context, doer *user_model.User, c *issues_model.Comment, oldContent string) {
  374. if err := c.LoadPoster(ctx); err != nil {
  375. log.Error("LoadPoster: %v", err)
  376. return
  377. }
  378. if err := c.LoadIssue(ctx); err != nil {
  379. log.Error("LoadIssue: %v", err)
  380. return
  381. }
  382. if err := c.Issue.LoadAttributes(ctx); err != nil {
  383. log.Error("LoadAttributes: %v", err)
  384. return
  385. }
  386. var eventType webhook_module.HookEventType
  387. var pullRequest *api.PullRequest
  388. if c.Issue.IsPull {
  389. eventType = webhook_module.HookEventPullRequestComment
  390. pullRequest = convert.ToAPIPullRequest(ctx, c.Issue.PullRequest, doer)
  391. } else {
  392. eventType = webhook_module.HookEventIssueComment
  393. }
  394. permission, _ := access_model.GetUserRepoPermission(ctx, c.Issue.Repo, doer)
  395. if err := PrepareWebhooks(ctx, EventSource{Repository: c.Issue.Repo}, eventType, &api.IssueCommentPayload{
  396. Action: api.HookIssueCommentEdited,
  397. Issue: convert.ToAPIIssue(ctx, doer, c.Issue),
  398. PullRequest: pullRequest,
  399. Comment: convert.ToAPIComment(ctx, c.Issue.Repo, c),
  400. Changes: &api.ChangesPayload{
  401. Body: &api.ChangesFromPayload{
  402. From: oldContent,
  403. },
  404. },
  405. Repository: convert.ToRepo(ctx, c.Issue.Repo, permission),
  406. Sender: convert.ToUser(ctx, doer, nil),
  407. IsPull: c.Issue.IsPull,
  408. }); err != nil {
  409. log.Error("PrepareWebhooks [comment_id: %d]: %v", c.ID, err)
  410. }
  411. }
  412. func (m *webhookNotifier) CreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository,
  413. issue *issues_model.Issue, comment *issues_model.Comment, mentions []*user_model.User,
  414. ) {
  415. var eventType webhook_module.HookEventType
  416. var pullRequest *api.PullRequest
  417. if issue.IsPull {
  418. eventType = webhook_module.HookEventPullRequestComment
  419. if err := issue.LoadPullRequest(ctx); err != nil {
  420. log.Error("LoadPullRequest: %v", err)
  421. return
  422. }
  423. pullRequest = convert.ToAPIPullRequest(ctx, issue.PullRequest, doer)
  424. } else {
  425. eventType = webhook_module.HookEventIssueComment
  426. }
  427. permission, _ := access_model.GetUserRepoPermission(ctx, repo, doer)
  428. if err := PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, eventType, &api.IssueCommentPayload{
  429. Action: api.HookIssueCommentCreated,
  430. Issue: convert.ToAPIIssue(ctx, doer, issue),
  431. PullRequest: pullRequest,
  432. Comment: convert.ToAPIComment(ctx, repo, comment),
  433. Repository: convert.ToRepo(ctx, repo, permission),
  434. Sender: convert.ToUser(ctx, doer, nil),
  435. IsPull: issue.IsPull,
  436. }); err != nil {
  437. log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err)
  438. }
  439. }
  440. func (m *webhookNotifier) DeleteComment(ctx context.Context, doer *user_model.User, comment *issues_model.Comment) {
  441. var err error
  442. if err = comment.LoadPoster(ctx); err != nil {
  443. log.Error("LoadPoster: %v", err)
  444. return
  445. }
  446. comment.Issue = nil // reload issue to ensure it has the latest data, especially the number of comments
  447. if err = comment.LoadIssue(ctx); err != nil {
  448. log.Error("LoadIssue: %v", err)
  449. return
  450. }
  451. if err = comment.Issue.LoadAttributes(ctx); err != nil {
  452. log.Error("LoadAttributes: %v", err)
  453. return
  454. }
  455. var eventType webhook_module.HookEventType
  456. var pullRequest *api.PullRequest
  457. if comment.Issue.IsPull {
  458. eventType = webhook_module.HookEventPullRequestComment
  459. pullRequest = convert.ToAPIPullRequest(ctx, comment.Issue.PullRequest, doer)
  460. } else {
  461. eventType = webhook_module.HookEventIssueComment
  462. }
  463. permission, _ := access_model.GetUserRepoPermission(ctx, comment.Issue.Repo, doer)
  464. if err := PrepareWebhooks(ctx, EventSource{Repository: comment.Issue.Repo}, eventType, &api.IssueCommentPayload{
  465. Action: api.HookIssueCommentDeleted,
  466. Issue: convert.ToAPIIssue(ctx, doer, comment.Issue),
  467. PullRequest: pullRequest,
  468. Comment: convert.ToAPIComment(ctx, comment.Issue.Repo, comment),
  469. Repository: convert.ToRepo(ctx, comment.Issue.Repo, permission),
  470. Sender: convert.ToUser(ctx, doer, nil),
  471. IsPull: comment.Issue.IsPull,
  472. }); err != nil {
  473. log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err)
  474. }
  475. }
  476. func (m *webhookNotifier) NewWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page, comment string) {
  477. // Add to hook queue for created wiki page.
  478. if err := PrepareWebhooks(ctx, EventSource{Repository: repo}, webhook_module.HookEventWiki, &api.WikiPayload{
  479. Action: api.HookWikiCreated,
  480. Repository: convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm.AccessModeOwner}),
  481. Sender: convert.ToUser(ctx, doer, nil),
  482. Page: page,
  483. Comment: comment,
  484. }); err != nil {
  485. log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err)
  486. }
  487. }
  488. func (m *webhookNotifier) EditWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page, comment string) {
  489. // Add to hook queue for edit wiki page.
  490. if err := PrepareWebhooks(ctx, EventSource{Repository: repo}, webhook_module.HookEventWiki, &api.WikiPayload{
  491. Action: api.HookWikiEdited,
  492. Repository: convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm.AccessModeOwner}),
  493. Sender: convert.ToUser(ctx, doer, nil),
  494. Page: page,
  495. Comment: comment,
  496. }); err != nil {
  497. log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err)
  498. }
  499. }
  500. func (m *webhookNotifier) DeleteWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, page string) {
  501. // Add to hook queue for edit wiki page.
  502. if err := PrepareWebhooks(ctx, EventSource{Repository: repo}, webhook_module.HookEventWiki, &api.WikiPayload{
  503. Action: api.HookWikiDeleted,
  504. Repository: convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm.AccessModeOwner}),
  505. Sender: convert.ToUser(ctx, doer, nil),
  506. Page: page,
  507. }); err != nil {
  508. log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err)
  509. }
  510. }
  511. func (m *webhookNotifier) IssueChangeLabels(ctx context.Context, doer *user_model.User, issue *issues_model.Issue,
  512. addedLabels, removedLabels []*issues_model.Label,
  513. ) {
  514. var err error
  515. if err = issue.LoadRepo(ctx); err != nil {
  516. log.Error("LoadRepo: %v", err)
  517. return
  518. }
  519. if err = issue.LoadPoster(ctx); err != nil {
  520. log.Error("LoadPoster: %v", err)
  521. return
  522. }
  523. permission, _ := access_model.GetUserRepoPermission(ctx, issue.Repo, issue.Poster)
  524. if issue.IsPull {
  525. if err = issue.LoadPullRequest(ctx); err != nil {
  526. log.Error("loadPullRequest: %v", err)
  527. return
  528. }
  529. if err = issue.PullRequest.LoadIssue(ctx); err != nil {
  530. log.Error("LoadIssue: %v", err)
  531. return
  532. }
  533. err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventPullRequestLabel, &api.PullRequestPayload{
  534. Action: api.HookIssueLabelUpdated,
  535. Index: issue.Index,
  536. PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, doer),
  537. Repository: convert.ToRepo(ctx, issue.Repo, access_model.Permission{AccessMode: perm.AccessModeOwner}),
  538. Sender: convert.ToUser(ctx, doer, nil),
  539. })
  540. } else {
  541. err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssueLabel, &api.IssuePayload{
  542. Action: api.HookIssueLabelUpdated,
  543. Index: issue.Index,
  544. Issue: convert.ToAPIIssue(ctx, doer, issue),
  545. Repository: convert.ToRepo(ctx, issue.Repo, permission),
  546. Sender: convert.ToUser(ctx, doer, nil),
  547. })
  548. }
  549. if err != nil {
  550. log.Error("PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
  551. }
  552. }
  553. func (m *webhookNotifier) IssueChangeMilestone(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldMilestoneID int64) {
  554. var hookAction api.HookIssueAction
  555. var err error
  556. if issue.MilestoneID > 0 {
  557. hookAction = api.HookIssueMilestoned
  558. } else {
  559. hookAction = api.HookIssueDemilestoned
  560. }
  561. if err = issue.LoadAttributes(ctx); err != nil {
  562. log.Error("issue.LoadAttributes failed: %v", err)
  563. return
  564. }
  565. permission, _ := access_model.GetUserRepoPermission(ctx, issue.Repo, doer)
  566. if issue.IsPull {
  567. err = issue.PullRequest.LoadIssue(ctx)
  568. if err != nil {
  569. log.Error("LoadIssue: %v", err)
  570. return
  571. }
  572. err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventPullRequestMilestone, &api.PullRequestPayload{
  573. Action: hookAction,
  574. Index: issue.Index,
  575. PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, doer),
  576. Repository: convert.ToRepo(ctx, issue.Repo, permission),
  577. Sender: convert.ToUser(ctx, doer, nil),
  578. })
  579. } else {
  580. err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssueMilestone, &api.IssuePayload{
  581. Action: hookAction,
  582. Index: issue.Index,
  583. Issue: convert.ToAPIIssue(ctx, doer, issue),
  584. Repository: convert.ToRepo(ctx, issue.Repo, permission),
  585. Sender: convert.ToUser(ctx, doer, nil),
  586. })
  587. }
  588. if err != nil {
  589. log.Error("PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
  590. }
  591. }
  592. func (m *webhookNotifier) PushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) {
  593. apiPusher := convert.ToUser(ctx, pusher, nil)
  594. apiCommits, apiHeadCommit, err := commits.ToAPIPayloadCommits(ctx, repo)
  595. if err != nil {
  596. log.Error("commits.ToAPIPayloadCommits failed: %v", err)
  597. return
  598. }
  599. if err := PrepareWebhooks(ctx, EventSource{Repository: repo}, webhook_module.HookEventPush, &api.PushPayload{
  600. Ref: opts.RefFullName.String(),
  601. Before: opts.OldCommitID,
  602. After: opts.NewCommitID,
  603. CompareURL: setting.AppURL + commits.CompareURL,
  604. Commits: apiCommits,
  605. TotalCommits: commits.Len,
  606. HeadCommit: apiHeadCommit,
  607. Repo: convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm.AccessModeOwner}),
  608. Pusher: apiPusher,
  609. Sender: apiPusher,
  610. }); err != nil {
  611. log.Error("PrepareWebhooks: %v", err)
  612. }
  613. }
  614. func (m *webhookNotifier) AutoMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) {
  615. // just redirect to the MergePullRequest
  616. m.MergePullRequest(ctx, doer, pr)
  617. }
  618. func (*webhookNotifier) MergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) {
  619. // Reload pull request information.
  620. if err := pr.LoadAttributes(ctx); err != nil {
  621. log.Error("LoadAttributes: %v", err)
  622. return
  623. }
  624. if err := pr.LoadIssue(ctx); err != nil {
  625. log.Error("LoadIssue: %v", err)
  626. return
  627. }
  628. if err := pr.Issue.LoadRepo(ctx); err != nil {
  629. log.Error("pr.Issue.LoadRepo: %v", err)
  630. return
  631. }
  632. permission, err := access_model.GetUserRepoPermission(ctx, pr.Issue.Repo, doer)
  633. if err != nil {
  634. log.Error("models.GetUserRepoPermission: %v", err)
  635. return
  636. }
  637. // Merge pull request calls issue.changeStatus so we need to handle separately.
  638. apiPullRequest := &api.PullRequestPayload{
  639. Index: pr.Issue.Index,
  640. PullRequest: convert.ToAPIPullRequest(ctx, pr, doer),
  641. Repository: convert.ToRepo(ctx, pr.Issue.Repo, permission),
  642. Sender: convert.ToUser(ctx, doer, nil),
  643. Action: api.HookIssueClosed,
  644. }
  645. if err := PrepareWebhooks(ctx, EventSource{Repository: pr.Issue.Repo}, webhook_module.HookEventPullRequest, apiPullRequest); err != nil {
  646. log.Error("PrepareWebhooks: %v", err)
  647. }
  648. }
  649. func (m *webhookNotifier) PullRequestChangeTargetBranch(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest, oldBranch string) {
  650. if err := pr.LoadIssue(ctx); err != nil {
  651. log.Error("LoadIssue: %v", err)
  652. return
  653. }
  654. issue := pr.Issue
  655. mode, _ := access_model.GetUserRepoPermission(ctx, issue.Repo, issue.Poster)
  656. if err := PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventPullRequest, &api.PullRequestPayload{
  657. Action: api.HookIssueEdited,
  658. Index: issue.Index,
  659. Changes: &api.ChangesPayload{
  660. Ref: &api.ChangesFromPayload{
  661. From: oldBranch,
  662. },
  663. },
  664. PullRequest: convert.ToAPIPullRequest(ctx, pr, doer),
  665. Repository: convert.ToRepo(ctx, issue.Repo, mode),
  666. Sender: convert.ToUser(ctx, doer, nil),
  667. }); err != nil {
  668. log.Error("PrepareWebhooks [pr: %d]: %v", pr.ID, err)
  669. }
  670. }
  671. func (m *webhookNotifier) PullRequestReview(ctx context.Context, pr *issues_model.PullRequest, review *issues_model.Review, comment *issues_model.Comment, mentions []*user_model.User) {
  672. var reviewHookType webhook_module.HookEventType
  673. switch review.Type {
  674. case issues_model.ReviewTypeApprove:
  675. reviewHookType = webhook_module.HookEventPullRequestReviewApproved
  676. case issues_model.ReviewTypeComment:
  677. reviewHookType = webhook_module.HookEventPullRequestReviewComment
  678. case issues_model.ReviewTypeReject:
  679. reviewHookType = webhook_module.HookEventPullRequestReviewRejected
  680. default:
  681. // unsupported review webhook type here
  682. log.Error("Unsupported review webhook type")
  683. return
  684. }
  685. if err := pr.LoadIssue(ctx); err != nil {
  686. log.Error("LoadIssue: %v", err)
  687. return
  688. }
  689. permission, err := access_model.GetUserRepoPermission(ctx, review.Issue.Repo, review.Issue.Poster)
  690. if err != nil {
  691. log.Error("models.GetUserRepoPermission: %v", err)
  692. return
  693. }
  694. if err := PrepareWebhooks(ctx, EventSource{Repository: review.Issue.Repo}, reviewHookType, &api.PullRequestPayload{
  695. Action: api.HookIssueReviewed,
  696. Index: review.Issue.Index,
  697. PullRequest: convert.ToAPIPullRequest(ctx, pr, review.Reviewer),
  698. RequestedReviewer: convert.ToUser(ctx, review.Reviewer, nil),
  699. Repository: convert.ToRepo(ctx, review.Issue.Repo, permission),
  700. Sender: convert.ToUser(ctx, review.Reviewer, nil),
  701. Review: &api.ReviewPayload{
  702. Type: string(reviewHookType),
  703. Content: review.Content,
  704. },
  705. }); err != nil {
  706. log.Error("PrepareWebhooks: %v", err)
  707. }
  708. }
  709. func (m *webhookNotifier) PullRequestReviewRequest(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, reviewer *user_model.User, isRequest bool, comment *issues_model.Comment) {
  710. if !issue.IsPull {
  711. log.Warn("PullRequestReviewRequest: issue is not a pull request: %v", issue.ID)
  712. return
  713. }
  714. permission, _ := access_model.GetUserRepoPermission(ctx, issue.Repo, doer)
  715. if err := issue.LoadPullRequest(ctx); err != nil {
  716. log.Error("LoadPullRequest failed: %v", err)
  717. return
  718. }
  719. apiPullRequest := &api.PullRequestPayload{
  720. Index: issue.Index,
  721. PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, doer),
  722. RequestedReviewer: convert.ToUser(ctx, reviewer, nil),
  723. Repository: convert.ToRepo(ctx, issue.Repo, permission),
  724. Sender: convert.ToUser(ctx, doer, nil),
  725. }
  726. if isRequest {
  727. apiPullRequest.Action = api.HookIssueReviewRequested
  728. } else {
  729. apiPullRequest.Action = api.HookIssueReviewRequestRemoved
  730. }
  731. if err := PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventPullRequestReviewRequest, apiPullRequest); err != nil {
  732. log.Error("PrepareWebhooks [review_requested: %v]: %v", isRequest, err)
  733. return
  734. }
  735. }
  736. func (m *webhookNotifier) CreateRef(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, refFullName git.RefName, refID string) {
  737. apiPusher := convert.ToUser(ctx, pusher, nil)
  738. apiRepo := convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm.AccessModeNone})
  739. if err := PrepareWebhooks(ctx, EventSource{Repository: repo}, webhook_module.HookEventCreate, &api.CreatePayload{
  740. Ref: refFullName.ShortName(), // FIXME: should it be a full ref name? But it will break the existing webhooks?
  741. Sha: refID,
  742. RefType: string(refFullName.RefType()),
  743. Repo: apiRepo,
  744. Sender: apiPusher,
  745. }); err != nil {
  746. log.Error("PrepareWebhooks: %v", err)
  747. }
  748. }
  749. func (m *webhookNotifier) PullRequestSynchronized(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) {
  750. if err := pr.LoadIssue(ctx); err != nil {
  751. log.Error("LoadIssue: %v", err)
  752. return
  753. }
  754. if err := pr.Issue.LoadAttributes(ctx); err != nil {
  755. log.Error("LoadAttributes: %v", err)
  756. return
  757. }
  758. if err := PrepareWebhooks(ctx, EventSource{Repository: pr.Issue.Repo}, webhook_module.HookEventPullRequestSync, &api.PullRequestPayload{
  759. Action: api.HookIssueSynchronized,
  760. Index: pr.Issue.Index,
  761. PullRequest: convert.ToAPIPullRequest(ctx, pr, doer),
  762. Repository: convert.ToRepo(ctx, pr.Issue.Repo, access_model.Permission{AccessMode: perm.AccessModeOwner}),
  763. Sender: convert.ToUser(ctx, doer, nil),
  764. }); err != nil {
  765. log.Error("PrepareWebhooks [pull_id: %v]: %v", pr.ID, err)
  766. }
  767. }
  768. func (m *webhookNotifier) DeleteRef(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, refFullName git.RefName) {
  769. apiPusher := convert.ToUser(ctx, pusher, nil)
  770. apiRepo := convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm.AccessModeOwner})
  771. if err := PrepareWebhooks(ctx, EventSource{Repository: repo}, webhook_module.HookEventDelete, &api.DeletePayload{
  772. Ref: refFullName.ShortName(), // FIXME: should it be a full ref name? But it will break the existing webhooks?
  773. RefType: string(refFullName.RefType()),
  774. PusherType: api.PusherTypeUser,
  775. Repo: apiRepo,
  776. Sender: apiPusher,
  777. }); err != nil {
  778. log.Error("PrepareWebhooks.(delete %s): %v", refFullName.RefType(), err)
  779. }
  780. }
  781. func sendReleaseHook(ctx context.Context, doer *user_model.User, rel *repo_model.Release, action api.HookReleaseAction) {
  782. if err := rel.LoadAttributes(ctx); err != nil {
  783. log.Error("LoadAttributes: %v", err)
  784. return
  785. }
  786. permission, _ := access_model.GetUserRepoPermission(ctx, rel.Repo, doer)
  787. if err := PrepareWebhooks(ctx, EventSource{Repository: rel.Repo}, webhook_module.HookEventRelease, &api.ReleasePayload{
  788. Action: action,
  789. Release: convert.ToAPIRelease(ctx, rel.Repo, rel),
  790. Repository: convert.ToRepo(ctx, rel.Repo, permission),
  791. Sender: convert.ToUser(ctx, doer, nil),
  792. }); err != nil {
  793. log.Error("PrepareWebhooks: %v", err)
  794. }
  795. }
  796. func (m *webhookNotifier) NewRelease(ctx context.Context, rel *repo_model.Release) {
  797. sendReleaseHook(ctx, rel.Publisher, rel, api.HookReleasePublished)
  798. }
  799. func (m *webhookNotifier) UpdateRelease(ctx context.Context, doer *user_model.User, rel *repo_model.Release) {
  800. sendReleaseHook(ctx, doer, rel, api.HookReleaseUpdated)
  801. }
  802. func (m *webhookNotifier) DeleteRelease(ctx context.Context, doer *user_model.User, rel *repo_model.Release) {
  803. sendReleaseHook(ctx, doer, rel, api.HookReleaseDeleted)
  804. }
  805. func (m *webhookNotifier) SyncPushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) {
  806. apiPusher := convert.ToUser(ctx, pusher, nil)
  807. apiCommits, apiHeadCommit, err := commits.ToAPIPayloadCommits(ctx, repo)
  808. if err != nil {
  809. log.Error("commits.ToAPIPayloadCommits failed: %v", err)
  810. return
  811. }
  812. if err := PrepareWebhooks(ctx, EventSource{Repository: repo}, webhook_module.HookEventPush, &api.PushPayload{
  813. Ref: opts.RefFullName.String(),
  814. Before: opts.OldCommitID,
  815. After: opts.NewCommitID,
  816. CompareURL: setting.AppURL + commits.CompareURL,
  817. Commits: apiCommits,
  818. TotalCommits: commits.Len,
  819. HeadCommit: apiHeadCommit,
  820. Repo: convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm.AccessModeOwner}),
  821. Pusher: apiPusher,
  822. Sender: apiPusher,
  823. }); err != nil {
  824. log.Error("PrepareWebhooks: %v", err)
  825. }
  826. }
  827. func (m *webhookNotifier) CreateCommitStatus(ctx context.Context, repo *repo_model.Repository, commit *repository.PushCommit, sender *user_model.User, status *git_model.CommitStatus) {
  828. apiSender := convert.ToUser(ctx, sender, nil)
  829. apiCommit, err := repository.ToAPIPayloadCommit(ctx, map[string]*user_model.User{}, repo, commit)
  830. if err != nil {
  831. log.Error("commits.ToAPIPayloadCommits failed: %v", err)
  832. return
  833. }
  834. // as a webhook url, target should be an absolute url. But for internal actions target url
  835. // the target url is a url path with no host and port to make it easy to be visited
  836. // from multiple hosts. So we need to convert it to an absolute url here.
  837. target := httplib.MakeAbsoluteURL(ctx, status.TargetURL)
  838. payload := api.CommitStatusPayload{
  839. Context: status.Context,
  840. CreatedAt: status.CreatedUnix.AsTime().UTC(),
  841. Description: status.Description,
  842. ID: status.ID,
  843. SHA: commit.Sha1,
  844. State: status.State.String(),
  845. TargetURL: target,
  846. Commit: apiCommit,
  847. Repo: convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm.AccessModeOwner}),
  848. Sender: apiSender,
  849. }
  850. if !status.UpdatedUnix.IsZero() {
  851. t := status.UpdatedUnix.AsTime().UTC()
  852. payload.UpdatedAt = &t
  853. }
  854. if err := PrepareWebhooks(ctx, EventSource{Repository: repo}, webhook_module.HookEventStatus, &payload); err != nil {
  855. log.Error("PrepareWebhooks: %v", err)
  856. }
  857. }
  858. func (m *webhookNotifier) SyncCreateRef(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, refFullName git.RefName, refID string) {
  859. m.CreateRef(ctx, pusher, repo, refFullName, refID)
  860. }
  861. func (m *webhookNotifier) SyncDeleteRef(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, refFullName git.RefName) {
  862. m.DeleteRef(ctx, pusher, repo, refFullName)
  863. }
  864. func (m *webhookNotifier) PackageCreate(ctx context.Context, doer *user_model.User, pd *packages_model.PackageDescriptor) {
  865. notifyPackage(ctx, doer, pd, api.HookPackageCreated)
  866. }
  867. func (m *webhookNotifier) PackageDelete(ctx context.Context, doer *user_model.User, pd *packages_model.PackageDescriptor) {
  868. notifyPackage(ctx, doer, pd, api.HookPackageDeleted)
  869. }
  870. func notifyPackage(ctx context.Context, sender *user_model.User, pd *packages_model.PackageDescriptor, action api.HookPackageAction) {
  871. source := EventSource{
  872. Repository: pd.Repository,
  873. Owner: pd.Owner,
  874. }
  875. apiPackage, err := convert.ToPackage(ctx, pd, sender)
  876. if err != nil {
  877. log.Error("Error converting package: %v", err)
  878. return
  879. }
  880. var org *api.Organization
  881. if pd.Owner.IsOrganization() {
  882. org = convert.ToOrganization(ctx, organization.OrgFromUser(pd.Owner))
  883. }
  884. if err := PrepareWebhooks(ctx, source, webhook_module.HookEventPackage, &api.PackagePayload{
  885. Action: action,
  886. Package: apiPackage,
  887. Organization: org,
  888. Sender: convert.ToUser(ctx, sender, nil),
  889. }); err != nil {
  890. log.Error("PrepareWebhooks: %v", err)
  891. }
  892. }
  893. func (*webhookNotifier) WorkflowJobStatusUpdate(ctx context.Context, repo *repo_model.Repository, sender *user_model.User, job *actions_model.ActionRunJob, task *actions_model.ActionTask) {
  894. source := EventSource{
  895. Repository: repo,
  896. Owner: repo.Owner,
  897. }
  898. var org *api.Organization
  899. if repo.Owner.IsOrganization() {
  900. org = convert.ToOrganization(ctx, organization.OrgFromUser(repo.Owner))
  901. }
  902. status, _ := convert.ToActionsStatus(job.Status)
  903. convertedJob, err := convert.ToActionWorkflowJob(ctx, repo, task, job)
  904. if err != nil {
  905. log.Error("ToActionWorkflowJob: %v", err)
  906. return
  907. }
  908. if err := PrepareWebhooks(ctx, source, webhook_module.HookEventWorkflowJob, &api.WorkflowJobPayload{
  909. Action: status,
  910. WorkflowJob: convertedJob,
  911. Organization: org,
  912. Repo: convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm.AccessModeOwner}),
  913. Sender: convert.ToUser(ctx, sender, nil),
  914. }); err != nil {
  915. log.Error("PrepareWebhooks: %v", err)
  916. }
  917. }
  918. func (*webhookNotifier) WorkflowRunStatusUpdate(ctx context.Context, repo *repo_model.Repository, sender *user_model.User, run *actions_model.ActionRun) {
  919. source := EventSource{
  920. Repository: repo,
  921. Owner: repo.Owner,
  922. }
  923. var org *api.Organization
  924. if repo.Owner.IsOrganization() {
  925. org = convert.ToOrganization(ctx, organization.OrgFromUser(repo.Owner))
  926. }
  927. status := convert.ToWorkflowRunAction(run.Status)
  928. gitRepo, err := gitrepo.OpenRepository(ctx, repo)
  929. if err != nil {
  930. log.Error("OpenRepository: %v", err)
  931. return
  932. }
  933. defer gitRepo.Close()
  934. convertedWorkflow, err := convert.GetActionWorkflow(ctx, gitRepo, repo, run.WorkflowID)
  935. if err != nil {
  936. log.Error("GetActionWorkflow: %v", err)
  937. return
  938. }
  939. convertedRun, err := convert.ToActionWorkflowRun(ctx, repo, run)
  940. if err != nil {
  941. log.Error("ToActionWorkflowRun: %v", err)
  942. return
  943. }
  944. if err := PrepareWebhooks(ctx, source, webhook_module.HookEventWorkflowRun, &api.WorkflowRunPayload{
  945. Action: status,
  946. Workflow: convertedWorkflow,
  947. WorkflowRun: convertedRun,
  948. Organization: org,
  949. Repo: convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm.AccessModeOwner}),
  950. Sender: convert.ToUser(ctx, sender, nil),
  951. }); err != nil {
  952. log.Error("PrepareWebhooks: %v", err)
  953. }
  954. }