Granular webhook events (#9626)

* Initial work

Signed-off-by: jolheiser <john.olheiser@gmail.com>

* Add PR reviews and API coverage

Signed-off-by: jolheiser <john.olheiser@gmail.com>

* Split up events

Signed-off-by: jolheiser <john.olheiser@gmail.com>

* Add migration and locale

Signed-off-by: jolheiser <john.olheiser@gmail.com>

* Format

Signed-off-by: jolheiser <john.olheiser@gmail.com>

* Revert IsPull

Signed-off-by: jolheiser <john.olheiser@gmail.com>

* Fix comments

Signed-off-by: jolheiser <john.olheiser@gmail.com>

* Fix tests

Signed-off-by: jolheiser <john.olheiser@gmail.com>

* Fix PR reviews

Signed-off-by: jolheiser <john.olheiser@gmail.com>

* Fix issue_comment

Signed-off-by: jolheiser <john.olheiser@gmail.com>

* Make fmt

Signed-off-by: jolheiser <john.olheiser@gmail.com>

* Migrations

Signed-off-by: jolheiser <john.olheiser@gmail.com>

* Backwards compatible API

Signed-off-by: jolheiser <john.olheiser@gmail.com>

* Fix feishu

Signed-off-by: jolheiser <john.olheiser@gmail.com>

* Move session commit

Signed-off-by: jolheiser <john.olheiser@gmail.com>

Co-authored-by: Lauris BH <lauris@nix.lv>
Co-authored-by: guillep2k <18600385+guillep2k@users.noreply.github.com>
pull/10622/head^2
John Olheiser 5 years ago committed by GitHub
parent 80db44267c
commit 3f1c0841cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      models/migrations/migrations.go
  2. 101
      models/migrations/v130.go
  3. 168
      models/webhook.go
  4. 6
      models/webhook_test.go
  5. 33
      modules/auth/repo_form.go
  6. 143
      modules/notification/webhook/webhook.go
  7. 2
      modules/structs/hook.go
  8. 6
      modules/webhook/deliver.go
  9. 11
      modules/webhook/dingtalk.go
  10. 19
      modules/webhook/discord.go
  11. 2
      modules/webhook/feishu.go
  12. 15
      modules/webhook/msteams.go
  13. 11
      modules/webhook/slack.go
  14. 11
      modules/webhook/telegram.go
  15. 41
      options/locale/locale_en-US.ini
  16. 35
      routers/api/v1/utils/hook.go
  17. 27
      routers/repo/webhook.go
  18. 120
      templates/repo/settings/webhook/settings.tmpl

@ -192,6 +192,8 @@ var migrations = []Migration{
NewMigration("fix merge base for pull requests", fixMergeBase), NewMigration("fix merge base for pull requests", fixMergeBase),
// v129 -> v130 // v129 -> v130
NewMigration("remove dependencies from deleted repositories", purgeUnusedDependencies), NewMigration("remove dependencies from deleted repositories", purgeUnusedDependencies),
// v130 -> v131
NewMigration("Expand webhooks for more granularity", expandWebhooks),
} }
// Migrate database to current version // Migrate database to current version

@ -0,0 +1,101 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package migrations
import (
"encoding/json"
"xorm.io/xorm"
)
func expandWebhooks(x *xorm.Engine) error {
type ChooseEvents struct {
Issues bool `json:"issues"`
IssueAssign bool `json:"issue_assign"`
IssueLabel bool `json:"issue_label"`
IssueMilestone bool `json:"issue_milestone"`
IssueComment bool `json:"issue_comment"`
PullRequest bool `json:"pull_request"`
PullRequestAssign bool `json:"pull_request_assign"`
PullRequestLabel bool `json:"pull_request_label"`
PullRequestMilestone bool `json:"pull_request_milestone"`
PullRequestComment bool `json:"pull_request_comment"`
PullRequestReview bool `json:"pull_request_review"`
PullRequestSync bool `json:"pull_request_sync"`
}
type Events struct {
PushOnly bool `json:"push_only"`
SendEverything bool `json:"send_everything"`
ChooseEvents bool `json:"choose_events"`
BranchFilter string `json:"branch_filter"`
Events ChooseEvents `json:"events"`
}
type Webhook struct {
ID int64
Events string
}
var events Events
var bytes []byte
var last int
const batchSize = 50
sess := x.NewSession()
defer sess.Close()
for {
if err := sess.Begin(); err != nil {
return err
}
var results = make([]Webhook, 0, batchSize)
err := x.OrderBy("id").
Limit(batchSize, last).
Find(&results)
if err != nil {
return err
}
if len(results) == 0 {
break
}
last += len(results)
for _, res := range results {
if err = json.Unmarshal([]byte(res.Events), &events); err != nil {
return err
}
if events.Events.Issues {
events.Events.IssueAssign = true
events.Events.IssueLabel = true
events.Events.IssueMilestone = true
events.Events.IssueComment = true
}
if events.Events.PullRequest {
events.Events.PullRequestAssign = true
events.Events.PullRequestLabel = true
events.Events.PullRequestMilestone = true
events.Events.PullRequestComment = true
events.Events.PullRequestReview = true
events.Events.PullRequestSync = true
}
if bytes, err = json.Marshal(&events); err != nil {
return err
}
_, err = sess.Exec("UPDATE webhook SET events = ? WHERE id = ?", string(bytes), res.ID)
if err != nil {
return err
}
}
if err := sess.Commit(); err != nil {
return err
}
}
return nil
}

@ -57,15 +57,24 @@ func IsValidHookContentType(name string) bool {
// HookEvents is a set of web hook events // HookEvents is a set of web hook events
type HookEvents struct { type HookEvents struct {
Create bool `json:"create"` Create bool `json:"create"`
Delete bool `json:"delete"` Delete bool `json:"delete"`
Fork bool `json:"fork"` Fork bool `json:"fork"`
Issues bool `json:"issues"` Issues bool `json:"issues"`
IssueComment bool `json:"issue_comment"` IssueAssign bool `json:"issue_assign"`
Push bool `json:"push"` IssueLabel bool `json:"issue_label"`
PullRequest bool `json:"pull_request"` IssueMilestone bool `json:"issue_milestone"`
Repository bool `json:"repository"` IssueComment bool `json:"issue_comment"`
Release bool `json:"release"` Push bool `json:"push"`
PullRequest bool `json:"pull_request"`
PullRequestAssign bool `json:"pull_request_assign"`
PullRequestLabel bool `json:"pull_request_label"`
PullRequestMilestone bool `json:"pull_request_milestone"`
PullRequestComment bool `json:"pull_request_comment"`
PullRequestReview bool `json:"pull_request_review"`
PullRequestSync bool `json:"pull_request_sync"`
Repository bool `json:"repository"`
Release bool `json:"release"`
} }
// HookEvent represents events that will delivery hook. // HookEvent represents events that will delivery hook.
@ -154,6 +163,24 @@ func (w *Webhook) HasIssuesEvent() bool {
(w.ChooseEvents && w.HookEvents.Issues) (w.ChooseEvents && w.HookEvents.Issues)
} }
// HasIssuesAssignEvent returns true if hook enabled issues assign event.
func (w *Webhook) HasIssuesAssignEvent() bool {
return w.SendEverything ||
(w.ChooseEvents && w.HookEvents.IssueAssign)
}
// HasIssuesLabelEvent returns true if hook enabled issues label event.
func (w *Webhook) HasIssuesLabelEvent() bool {
return w.SendEverything ||
(w.ChooseEvents && w.HookEvents.IssueLabel)
}
// HasIssuesMilestoneEvent returns true if hook enabled issues milestone event.
func (w *Webhook) HasIssuesMilestoneEvent() bool {
return w.SendEverything ||
(w.ChooseEvents && w.HookEvents.IssueMilestone)
}
// HasIssueCommentEvent returns true if hook enabled issue_comment event. // HasIssueCommentEvent returns true if hook enabled issue_comment event.
func (w *Webhook) HasIssueCommentEvent() bool { func (w *Webhook) HasIssueCommentEvent() bool {
return w.SendEverything || return w.SendEverything ||
@ -172,6 +199,54 @@ func (w *Webhook) HasPullRequestEvent() bool {
(w.ChooseEvents && w.HookEvents.PullRequest) (w.ChooseEvents && w.HookEvents.PullRequest)
} }
// HasPullRequestAssignEvent returns true if hook enabled pull request assign event.
func (w *Webhook) HasPullRequestAssignEvent() bool {
return w.SendEverything ||
(w.ChooseEvents && w.HookEvents.PullRequestAssign)
}
// HasPullRequestLabelEvent returns true if hook enabled pull request label event.
func (w *Webhook) HasPullRequestLabelEvent() bool {
return w.SendEverything ||
(w.ChooseEvents && w.HookEvents.PullRequestLabel)
}
// HasPullRequestMilestoneEvent returns true if hook enabled pull request milestone event.
func (w *Webhook) HasPullRequestMilestoneEvent() bool {
return w.SendEverything ||
(w.ChooseEvents && w.HookEvents.PullRequestMilestone)
}
// HasPullRequestCommentEvent returns true if hook enabled pull_request_comment event.
func (w *Webhook) HasPullRequestCommentEvent() bool {
return w.SendEverything ||
(w.ChooseEvents && w.HookEvents.PullRequestComment)
}
// HasPullRequestApprovedEvent returns true if hook enabled pull request review event.
func (w *Webhook) HasPullRequestApprovedEvent() bool {
return w.SendEverything ||
(w.ChooseEvents && w.HookEvents.PullRequestReview)
}
// HasPullRequestRejectedEvent returns true if hook enabled pull request review event.
func (w *Webhook) HasPullRequestRejectedEvent() bool {
return w.SendEverything ||
(w.ChooseEvents && w.HookEvents.PullRequestReview)
}
// HasPullRequestReviewCommentEvent returns true if hook enabled pull request review event.
func (w *Webhook) HasPullRequestReviewCommentEvent() bool {
return w.SendEverything ||
(w.ChooseEvents && w.HookEvents.PullRequestReview)
}
// HasPullRequestSyncEvent returns true if hook enabled pull request sync event.
func (w *Webhook) HasPullRequestSyncEvent() bool {
return w.SendEverything ||
(w.ChooseEvents && w.HookEvents.PullRequestSync)
}
// HasReleaseEvent returns if hook enabled release event. // HasReleaseEvent returns if hook enabled release event.
func (w *Webhook) HasReleaseEvent() bool { func (w *Webhook) HasReleaseEvent() bool {
return w.SendEverything || return w.SendEverything ||
@ -198,8 +273,19 @@ func (w *Webhook) EventCheckers() []struct {
{w.HasForkEvent, HookEventFork}, {w.HasForkEvent, HookEventFork},
{w.HasPushEvent, HookEventPush}, {w.HasPushEvent, HookEventPush},
{w.HasIssuesEvent, HookEventIssues}, {w.HasIssuesEvent, HookEventIssues},
{w.HasIssuesAssignEvent, HookEventIssueAssign},
{w.HasIssuesLabelEvent, HookEventIssueLabel},
{w.HasIssuesMilestoneEvent, HookEventIssueMilestone},
{w.HasIssueCommentEvent, HookEventIssueComment}, {w.HasIssueCommentEvent, HookEventIssueComment},
{w.HasPullRequestEvent, HookEventPullRequest}, {w.HasPullRequestEvent, HookEventPullRequest},
{w.HasPullRequestAssignEvent, HookEventPullRequestAssign},
{w.HasPullRequestLabelEvent, HookEventPullRequestLabel},
{w.HasPullRequestMilestoneEvent, HookEventPullRequestMilestone},
{w.HasPullRequestCommentEvent, HookEventPullRequestComment},
{w.HasPullRequestApprovedEvent, HookEventPullRequestReviewApproved},
{w.HasPullRequestRejectedEvent, HookEventPullRequestReviewRejected},
{w.HasPullRequestCommentEvent, HookEventPullRequestReviewComment},
{w.HasPullRequestSyncEvent, HookEventPullRequestSync},
{w.HasRepositoryEvent, HookEventRepository}, {w.HasRepositoryEvent, HookEventRepository},
{w.HasReleaseEvent, HookEventRelease}, {w.HasReleaseEvent, HookEventRelease},
} }
@ -498,20 +584,60 @@ type HookEventType string
// Types of hook events // Types of hook events
const ( const (
HookEventCreate HookEventType = "create" HookEventCreate HookEventType = "create"
HookEventDelete HookEventType = "delete" HookEventDelete HookEventType = "delete"
HookEventFork HookEventType = "fork" HookEventFork HookEventType = "fork"
HookEventPush HookEventType = "push" HookEventPush HookEventType = "push"
HookEventIssues HookEventType = "issues" HookEventIssues HookEventType = "issues"
HookEventIssueComment HookEventType = "issue_comment" HookEventIssueAssign HookEventType = "issue_assign"
HookEventPullRequest HookEventType = "pull_request" HookEventIssueLabel HookEventType = "issue_label"
HookEventRepository HookEventType = "repository" HookEventIssueMilestone HookEventType = "issue_milestone"
HookEventRelease HookEventType = "release" HookEventIssueComment HookEventType = "issue_comment"
HookEventPullRequestApproved HookEventType = "pull_request_approved" HookEventPullRequest HookEventType = "pull_request"
HookEventPullRequestRejected HookEventType = "pull_request_rejected" HookEventPullRequestAssign HookEventType = "pull_request_assign"
HookEventPullRequestComment HookEventType = "pull_request_comment" HookEventPullRequestLabel HookEventType = "pull_request_label"
HookEventPullRequestMilestone HookEventType = "pull_request_milestone"
HookEventPullRequestComment HookEventType = "pull_request_comment"
HookEventPullRequestReviewApproved HookEventType = "pull_request_review_approved"
HookEventPullRequestReviewRejected HookEventType = "pull_request_review_rejected"
HookEventPullRequestReviewComment HookEventType = "pull_request_review_comment"
HookEventPullRequestSync HookEventType = "pull_request_sync"
HookEventRepository HookEventType = "repository"
HookEventRelease HookEventType = "release"
) )
// Event returns the HookEventType as an event string
func (h HookEventType) Event() string {
switch h {
case HookEventCreate:
return "create"
case HookEventDelete:
return "delete"
case HookEventFork:
return "fork"
case HookEventPush:
return "push"
case HookEventIssues, HookEventIssueAssign, HookEventIssueLabel, HookEventIssueMilestone:
return "issues"
case HookEventPullRequest, HookEventPullRequestAssign, HookEventPullRequestLabel, HookEventPullRequestMilestone,
HookEventPullRequestSync:
return "pull_request"
case HookEventIssueComment, HookEventPullRequestComment:
return "issue_comment"
case HookEventPullRequestReviewApproved:
return "pull_request_approved"
case HookEventPullRequestReviewRejected:
return "pull_request_rejected"
case HookEventPullRequestReviewComment:
return "pull_request_comment"
case HookEventRepository:
return "repository"
case HookEventRelease:
return "release"
}
return ""
}
// HookRequest represents hook task request information. // HookRequest represents hook task request information.
type HookRequest struct { type HookRequest struct {
Headers map[string]string `json:"headers"` Headers map[string]string `json:"headers"`

@ -61,7 +61,11 @@ func TestWebhook_UpdateEvent(t *testing.T) {
} }
func TestWebhook_EventsArray(t *testing.T) { func TestWebhook_EventsArray(t *testing.T) {
assert.Equal(t, []string{"create", "delete", "fork", "push", "issues", "issue_comment", "pull_request", "repository", "release"}, assert.Equal(t, []string{"create", "delete", "fork", "push",
"issues", "issue_assign", "issue_label", "issue_milestone", "issue_comment",
"pull_request", "pull_request_assign", "pull_request_label", "pull_request_milestone",
"pull_request_comment", "pull_request_review_approved", "pull_request_review_rejected",
"pull_request_review_comment", "pull_request_sync", "repository", "release"},
(&Webhook{ (&Webhook{
HookEvent: &HookEvent{SendEverything: true}, HookEvent: &HookEvent{SendEverything: true},
}).EventsArray(), }).EventsArray(),

@ -190,18 +190,27 @@ func (f *ProtectBranchForm) Validate(ctx *macaron.Context, errs binding.Errors)
// WebhookForm form for changing web hook // WebhookForm form for changing web hook
type WebhookForm struct { type WebhookForm struct {
Events string Events string
Create bool Create bool
Delete bool Delete bool
Fork bool Fork bool
Issues bool Issues bool
IssueComment bool IssueAssign bool
Release bool IssueLabel bool
Push bool IssueMilestone bool
PullRequest bool IssueComment bool
Repository bool Release bool
Active bool Push bool
BranchFilter string `binding:"GlobPattern"` PullRequest bool
PullRequestAssign bool
PullRequestLabel bool
PullRequestMilestone bool
PullRequestComment bool
PullRequestReview bool
PullRequestSync bool
Repository bool
Active bool
BranchFilter string `binding:"GlobPattern"`
} }
// PushOnly if the hook will be triggered when push // PushOnly if the hook will be triggered when push

@ -48,7 +48,7 @@ func (m *webhookNotifier) NotifyIssueClearLabels(doer *models.User, issue *model
return return
} }
err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventPullRequest, &api.PullRequestPayload{ err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventPullRequestLabel, &api.PullRequestPayload{
Action: api.HookIssueLabelCleared, Action: api.HookIssueLabelCleared,
Index: issue.Index, Index: issue.Index,
PullRequest: convert.ToAPIPullRequest(issue.PullRequest), PullRequest: convert.ToAPIPullRequest(issue.PullRequest),
@ -56,7 +56,7 @@ func (m *webhookNotifier) NotifyIssueClearLabels(doer *models.User, issue *model
Sender: doer.APIFormat(), Sender: doer.APIFormat(),
}) })
} else { } else {
err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventIssues, &api.IssuePayload{ err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventIssueLabel, &api.IssuePayload{
Action: api.HookIssueLabelCleared, Action: api.HookIssueLabelCleared,
Index: issue.Index, Index: issue.Index,
Issue: convert.ToAPIIssue(issue), Issue: convert.ToAPIIssue(issue),
@ -147,7 +147,7 @@ func (m *webhookNotifier) NotifyIssueChangeAssignee(doer *models.User, issue *mo
apiPullRequest.Action = api.HookIssueAssigned apiPullRequest.Action = api.HookIssueAssigned
} }
// Assignee comment triggers a webhook // Assignee comment triggers a webhook
if err := webhook_module.PrepareWebhooks(issue.Repo, models.HookEventPullRequest, apiPullRequest); err != nil { if err := webhook_module.PrepareWebhooks(issue.Repo, models.HookEventPullRequestAssign, apiPullRequest); err != nil {
log.Error("PrepareWebhooks [is_pull: %v, remove_assignee: %v]: %v", issue.IsPull, removed, err) log.Error("PrepareWebhooks [is_pull: %v, remove_assignee: %v]: %v", issue.IsPull, removed, err)
return return
} }
@ -165,7 +165,7 @@ func (m *webhookNotifier) NotifyIssueChangeAssignee(doer *models.User, issue *mo
apiIssue.Action = api.HookIssueAssigned apiIssue.Action = api.HookIssueAssigned
} }
// Assignee comment triggers a webhook // Assignee comment triggers a webhook
if err := webhook_module.PrepareWebhooks(issue.Repo, models.HookEventIssues, apiIssue); err != nil { if err := webhook_module.PrepareWebhooks(issue.Repo, models.HookEventIssueAssign, apiIssue); err != nil {
log.Error("PrepareWebhooks [is_pull: %v, remove_assignee: %v]: %v", issue.IsPull, removed, err) log.Error("PrepareWebhooks [is_pull: %v, remove_assignee: %v]: %v", issue.IsPull, removed, err)
return return
} }
@ -338,34 +338,54 @@ func (m *webhookNotifier) NotifyIssueChangeContent(doer *models.User, issue *mod
} }
func (m *webhookNotifier) NotifyUpdateComment(doer *models.User, c *models.Comment, oldContent string) { func (m *webhookNotifier) NotifyUpdateComment(doer *models.User, c *models.Comment, oldContent string) {
if err := c.LoadPoster(); err != nil { var err error
if err = c.LoadPoster(); err != nil {
log.Error("LoadPoster: %v", err) log.Error("LoadPoster: %v", err)
return return
} }
if err := c.LoadIssue(); err != nil { if err = c.LoadIssue(); err != nil {
log.Error("LoadIssue: %v", err) log.Error("LoadIssue: %v", err)
return return
} }
if err := c.Issue.LoadAttributes(); err != nil { if err = c.Issue.LoadAttributes(); err != nil {
log.Error("LoadAttributes: %v", err) log.Error("LoadAttributes: %v", err)
return return
} }
mode, _ := models.AccessLevel(doer, c.Issue.Repo) mode, _ := models.AccessLevel(doer, c.Issue.Repo)
if err := webhook_module.PrepareWebhooks(c.Issue.Repo, models.HookEventIssueComment, &api.IssueCommentPayload{ if c.Issue.IsPull {
Action: api.HookIssueCommentEdited, err = webhook_module.PrepareWebhooks(c.Issue.Repo, models.HookEventPullRequestComment, &api.IssueCommentPayload{
Issue: convert.ToAPIIssue(c.Issue), Action: api.HookIssueCommentEdited,
Comment: c.APIFormat(), Issue: convert.ToAPIIssue(c.Issue),
Changes: &api.ChangesPayload{ Comment: c.APIFormat(),
Body: &api.ChangesFromPayload{ Changes: &api.ChangesPayload{
From: oldContent, Body: &api.ChangesFromPayload{
From: oldContent,
},
}, },
}, Repository: c.Issue.Repo.APIFormat(mode),
Repository: c.Issue.Repo.APIFormat(mode), Sender: doer.APIFormat(),
Sender: doer.APIFormat(), IsPull: true,
IsPull: c.Issue.IsPull, })
}); err != nil { } else {
err = webhook_module.PrepareWebhooks(c.Issue.Repo, models.HookEventIssueComment, &api.IssueCommentPayload{
Action: api.HookIssueCommentEdited,
Issue: convert.ToAPIIssue(c.Issue),
Comment: c.APIFormat(),
Changes: &api.ChangesPayload{
Body: &api.ChangesFromPayload{
From: oldContent,
},
},
Repository: c.Issue.Repo.APIFormat(mode),
Sender: doer.APIFormat(),
IsPull: false,
})
}
if err != nil {
log.Error("PrepareWebhooks [comment_id: %d]: %v", c.ID, err) log.Error("PrepareWebhooks [comment_id: %d]: %v", c.ID, err)
} }
} }
@ -373,45 +393,76 @@ func (m *webhookNotifier) NotifyUpdateComment(doer *models.User, c *models.Comme
func (m *webhookNotifier) NotifyCreateIssueComment(doer *models.User, repo *models.Repository, func (m *webhookNotifier) NotifyCreateIssueComment(doer *models.User, repo *models.Repository,
issue *models.Issue, comment *models.Comment) { issue *models.Issue, comment *models.Comment) {
mode, _ := models.AccessLevel(doer, repo) mode, _ := models.AccessLevel(doer, repo)
if err := webhook_module.PrepareWebhooks(repo, models.HookEventIssueComment, &api.IssueCommentPayload{
Action: api.HookIssueCommentCreated, var err error
Issue: convert.ToAPIIssue(issue), if issue.IsPull {
Comment: comment.APIFormat(), err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventPullRequestComment, &api.IssueCommentPayload{
Repository: repo.APIFormat(mode), Action: api.HookIssueCommentCreated,
Sender: doer.APIFormat(), Issue: convert.ToAPIIssue(issue),
IsPull: issue.IsPull, Comment: comment.APIFormat(),
}); err != nil { Repository: repo.APIFormat(mode),
Sender: doer.APIFormat(),
IsPull: true,
})
} else {
err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventIssueComment, &api.IssueCommentPayload{
Action: api.HookIssueCommentCreated,
Issue: convert.ToAPIIssue(issue),
Comment: comment.APIFormat(),
Repository: repo.APIFormat(mode),
Sender: doer.APIFormat(),
IsPull: false,
})
}
if err != nil {
log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err) log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err)
} }
} }
func (m *webhookNotifier) NotifyDeleteComment(doer *models.User, comment *models.Comment) { func (m *webhookNotifier) NotifyDeleteComment(doer *models.User, comment *models.Comment) {
if err := comment.LoadPoster(); err != nil { var err error
if err = comment.LoadPoster(); err != nil {
log.Error("LoadPoster: %v", err) log.Error("LoadPoster: %v", err)
return return
} }
if err := comment.LoadIssue(); err != nil { if err = comment.LoadIssue(); err != nil {
log.Error("LoadIssue: %v", err) log.Error("LoadIssue: %v", err)
return return
} }
if err := comment.Issue.LoadAttributes(); err != nil { if err = comment.Issue.LoadAttributes(); err != nil {
log.Error("LoadAttributes: %v", err) log.Error("LoadAttributes: %v", err)
return return
} }
mode, _ := models.AccessLevel(doer, comment.Issue.Repo) mode, _ := models.AccessLevel(doer, comment.Issue.Repo)
if err := webhook_module.PrepareWebhooks(comment.Issue.Repo, models.HookEventIssueComment, &api.IssueCommentPayload{ if comment.Issue.IsPull {
Action: api.HookIssueCommentDeleted, err = webhook_module.PrepareWebhooks(comment.Issue.Repo, models.HookEventPullRequestComment, &api.IssueCommentPayload{
Issue: convert.ToAPIIssue(comment.Issue), Action: api.HookIssueCommentDeleted,
Comment: comment.APIFormat(), Issue: convert.ToAPIIssue(comment.Issue),
Repository: comment.Issue.Repo.APIFormat(mode), Comment: comment.APIFormat(),
Sender: doer.APIFormat(), Repository: comment.Issue.Repo.APIFormat(mode),
IsPull: comment.Issue.IsPull, Sender: doer.APIFormat(),
}); err != nil { IsPull: true,
})
} else {
err = webhook_module.PrepareWebhooks(comment.Issue.Repo, models.HookEventIssueComment, &api.IssueCommentPayload{
Action: api.HookIssueCommentDeleted,
Issue: convert.ToAPIIssue(comment.Issue),
Comment: comment.APIFormat(),
Repository: comment.Issue.Repo.APIFormat(mode),
Sender: doer.APIFormat(),
IsPull: false,
})
}
if err != nil {
log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err) log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err)
} }
} }
func (m *webhookNotifier) NotifyIssueChangeLabels(doer *models.User, issue *models.Issue, func (m *webhookNotifier) NotifyIssueChangeLabels(doer *models.User, issue *models.Issue,
@ -438,7 +489,7 @@ func (m *webhookNotifier) NotifyIssueChangeLabels(doer *models.User, issue *mode
log.Error("LoadIssue: %v", err) log.Error("LoadIssue: %v", err)
return return
} }
err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventPullRequest, &api.PullRequestPayload{ err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventPullRequestLabel, &api.PullRequestPayload{
Action: api.HookIssueLabelUpdated, Action: api.HookIssueLabelUpdated,
Index: issue.Index, Index: issue.Index,
PullRequest: convert.ToAPIPullRequest(issue.PullRequest), PullRequest: convert.ToAPIPullRequest(issue.PullRequest),
@ -446,7 +497,7 @@ func (m *webhookNotifier) NotifyIssueChangeLabels(doer *models.User, issue *mode
Sender: doer.APIFormat(), Sender: doer.APIFormat(),
}) })
} else { } else {
err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventIssues, &api.IssuePayload{ err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventIssueLabel, &api.IssuePayload{
Action: api.HookIssueLabelUpdated, Action: api.HookIssueLabelUpdated,
Index: issue.Index, Index: issue.Index,
Issue: convert.ToAPIIssue(issue), Issue: convert.ToAPIIssue(issue),
@ -480,7 +531,7 @@ func (m *webhookNotifier) NotifyIssueChangeMilestone(doer *models.User, issue *m
log.Error("LoadIssue: %v", err) log.Error("LoadIssue: %v", err)
return return
} }
err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventPullRequest, &api.PullRequestPayload{ err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventPullRequestMilestone, &api.PullRequestPayload{
Action: hookAction, Action: hookAction,
Index: issue.Index, Index: issue.Index,
PullRequest: convert.ToAPIPullRequest(issue.PullRequest), PullRequest: convert.ToAPIPullRequest(issue.PullRequest),
@ -488,7 +539,7 @@ func (m *webhookNotifier) NotifyIssueChangeMilestone(doer *models.User, issue *m
Sender: doer.APIFormat(), Sender: doer.APIFormat(),
}) })
} else { } else {
err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventIssues, &api.IssuePayload{ err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventIssueMilestone, &api.IssuePayload{
Action: hookAction, Action: hookAction,
Index: issue.Index, Index: issue.Index,
Issue: convert.ToAPIIssue(issue), Issue: convert.ToAPIIssue(issue),
@ -597,11 +648,11 @@ func (m *webhookNotifier) NotifyPullRequestReview(pr *models.PullRequest, review
switch review.Type { switch review.Type {
case models.ReviewTypeApprove: case models.ReviewTypeApprove:
reviewHookType = models.HookEventPullRequestApproved reviewHookType = models.HookEventPullRequestReviewApproved
case models.ReviewTypeComment: case models.ReviewTypeComment:
reviewHookType = models.HookEventPullRequestComment reviewHookType = models.HookEventPullRequestComment
case models.ReviewTypeReject: case models.ReviewTypeReject:
reviewHookType = models.HookEventPullRequestRejected reviewHookType = models.HookEventPullRequestReviewRejected
default: default:
// unsupported review webhook type here // unsupported review webhook type here
log.Error("Unsupported review webhook type") log.Error("Unsupported review webhook type")
@ -619,7 +670,7 @@ func (m *webhookNotifier) NotifyPullRequestReview(pr *models.PullRequest, review
return return
} }
if err := webhook_module.PrepareWebhooks(review.Issue.Repo, reviewHookType, &api.PullRequestPayload{ if err := webhook_module.PrepareWebhooks(review.Issue.Repo, reviewHookType, &api.PullRequestPayload{
Action: api.HookIssueSynchronized, Action: api.HookIssueReviewed,
Index: review.Issue.Index, Index: review.Issue.Index,
PullRequest: convert.ToAPIPullRequest(pr), PullRequest: convert.ToAPIPullRequest(pr),
Repository: review.Issue.Repo.APIFormat(mode), Repository: review.Issue.Repo.APIFormat(mode),
@ -673,7 +724,7 @@ func (m *webhookNotifier) NotifyPullRequestSynchronized(doer *models.User, pr *m
return return
} }
if err := webhook_module.PrepareWebhooks(pr.Issue.Repo, models.HookEventPullRequest, &api.PullRequestPayload{ if err := webhook_module.PrepareWebhooks(pr.Issue.Repo, models.HookEventPullRequestSync, &api.PullRequestPayload{
Action: api.HookIssueSynchronized, Action: api.HookIssueSynchronized,
Index: pr.Issue.Index, Index: pr.Issue.Index,
PullRequest: convert.ToAPIPullRequest(pr), PullRequest: convert.ToAPIPullRequest(pr),

@ -374,6 +374,8 @@ const (
HookIssueMilestoned HookIssueAction = "milestoned" HookIssueMilestoned HookIssueAction = "milestoned"
// HookIssueDemilestoned is an issue action for when a milestone is cleared on an issue. // HookIssueDemilestoned is an issue action for when a milestone is cleared on an issue.
HookIssueDemilestoned HookIssueAction = "demilestoned" HookIssueDemilestoned HookIssueAction = "demilestoned"
// HookIssueReviewed is an issue action for when a pull request is reviewed
HookIssueReviewed HookIssueAction = "reviewed"
) )
// IssuePayload represents the payload information that is sent along with an issue event. // IssuePayload represents the payload information that is sent along with an issue event.

@ -74,13 +74,13 @@ func Deliver(t *models.HookTask) error {
} }
req.Header.Add("X-Gitea-Delivery", t.UUID) req.Header.Add("X-Gitea-Delivery", t.UUID)
req.Header.Add("X-Gitea-Event", string(t.EventType)) req.Header.Add("X-Gitea-Event", t.EventType.Event())
req.Header.Add("X-Gitea-Signature", t.Signature) req.Header.Add("X-Gitea-Signature", t.Signature)
req.Header.Add("X-Gogs-Delivery", t.UUID) req.Header.Add("X-Gogs-Delivery", t.UUID)
req.Header.Add("X-Gogs-Event", string(t.EventType)) req.Header.Add("X-Gogs-Event", t.EventType.Event())
req.Header.Add("X-Gogs-Signature", t.Signature) req.Header.Add("X-Gogs-Signature", t.Signature)
req.Header["X-GitHub-Delivery"] = []string{t.UUID} req.Header["X-GitHub-Delivery"] = []string{t.UUID}
req.Header["X-GitHub-Event"] = []string{string(t.EventType)} req.Header["X-GitHub-Event"] = []string{t.EventType.Event()}
// Record delivery information. // Record delivery information.
t.RequestInfo = &models.HookRequest{ t.RequestInfo = &models.HookRequest{

@ -181,7 +181,7 @@ func getDingtalkPullRequestPayload(p *api.PullRequestPayload) (*DingtalkPayload,
func getDingtalkPullRequestApprovalPayload(p *api.PullRequestPayload, event models.HookEventType) (*DingtalkPayload, error) { func getDingtalkPullRequestApprovalPayload(p *api.PullRequestPayload, event models.HookEventType) (*DingtalkPayload, error) {
var text, title string var text, title string
switch p.Action { switch p.Action {
case api.HookIssueSynchronized: case api.HookIssueReviewed:
action, err := parseHookPullRequestEventType(event) action, err := parseHookPullRequestEventType(event)
if err != nil { if err != nil {
return nil, err return nil, err
@ -261,15 +261,16 @@ func GetDingtalkPayload(p api.Payloader, event models.HookEventType, meta string
return getDingtalkDeletePayload(p.(*api.DeletePayload)) return getDingtalkDeletePayload(p.(*api.DeletePayload))
case models.HookEventFork: case models.HookEventFork:
return getDingtalkForkPayload(p.(*api.ForkPayload)) return getDingtalkForkPayload(p.(*api.ForkPayload))
case models.HookEventIssues: case models.HookEventIssues, models.HookEventIssueAssign, models.HookEventIssueLabel, models.HookEventIssueMilestone:
return getDingtalkIssuesPayload(p.(*api.IssuePayload)) return getDingtalkIssuesPayload(p.(*api.IssuePayload))
case models.HookEventIssueComment: case models.HookEventIssueComment, models.HookEventPullRequestComment:
return getDingtalkIssueCommentPayload(p.(*api.IssueCommentPayload)) return getDingtalkIssueCommentPayload(p.(*api.IssueCommentPayload))
case models.HookEventPush: case models.HookEventPush:
return getDingtalkPushPayload(p.(*api.PushPayload)) return getDingtalkPushPayload(p.(*api.PushPayload))
case models.HookEventPullRequest: case models.HookEventPullRequest, models.HookEventPullRequestAssign, models.HookEventPullRequestLabel,
models.HookEventPullRequestMilestone, models.HookEventPullRequestSync:
return getDingtalkPullRequestPayload(p.(*api.PullRequestPayload)) return getDingtalkPullRequestPayload(p.(*api.PullRequestPayload))
case models.HookEventPullRequestApproved, models.HookEventPullRequestRejected, models.HookEventPullRequestComment: case models.HookEventPullRequestReviewApproved, models.HookEventPullRequestReviewRejected, models.HookEventPullRequestReviewComment:
return getDingtalkPullRequestApprovalPayload(p.(*api.PullRequestPayload), event) return getDingtalkPullRequestApprovalPayload(p.(*api.PullRequestPayload), event)
case models.HookEventRepository: case models.HookEventRepository:
return getDingtalkRepositoryPayload(p.(*api.RepositoryPayload)) return getDingtalkRepositoryPayload(p.(*api.RepositoryPayload))

@ -296,7 +296,7 @@ func getDiscordPullRequestApprovalPayload(p *api.PullRequestPayload, meta *Disco
var text, title string var text, title string
var color int var color int
switch p.Action { switch p.Action {
case api.HookIssueSynchronized: case api.HookIssueReviewed:
action, err := parseHookPullRequestEventType(event) action, err := parseHookPullRequestEventType(event)
if err != nil { if err != nil {
return nil, err return nil, err
@ -306,9 +306,9 @@ func getDiscordPullRequestApprovalPayload(p *api.PullRequestPayload, meta *Disco
text = p.Review.Content text = p.Review.Content
switch event { switch event {
case models.HookEventPullRequestApproved: case models.HookEventPullRequestReviewApproved:
color = greenColor color = greenColor
case models.HookEventPullRequestRejected: case models.HookEventPullRequestReviewRejected:
color = redColor color = redColor
case models.HookEventPullRequestComment: case models.HookEventPullRequestComment:
color = greyColor color = greyColor
@ -405,15 +405,16 @@ func GetDiscordPayload(p api.Payloader, event models.HookEventType, meta string)
return getDiscordDeletePayload(p.(*api.DeletePayload), discord) return getDiscordDeletePayload(p.(*api.DeletePayload), discord)
case models.HookEventFork: case models.HookEventFork:
return getDiscordForkPayload(p.(*api.ForkPayload), discord) return getDiscordForkPayload(p.(*api.ForkPayload), discord)
case models.HookEventIssues: case models.HookEventIssues, models.HookEventIssueAssign, models.HookEventIssueLabel, models.HookEventIssueMilestone:
return getDiscordIssuesPayload(p.(*api.IssuePayload), discord) return getDiscordIssuesPayload(p.(*api.IssuePayload), discord)
case models.HookEventIssueComment: case models.HookEventIssueComment, models.HookEventPullRequestComment:
return getDiscordIssueCommentPayload(p.(*api.IssueCommentPayload), discord) return getDiscordIssueCommentPayload(p.(*api.IssueCommentPayload), discord)
case models.HookEventPush: case models.HookEventPush:
return getDiscordPushPayload(p.(*api.PushPayload), discord) return getDiscordPushPayload(p.(*api.PushPayload), discord)
case models.HookEventPullRequest: case models.HookEventPullRequest, models.HookEventPullRequestAssign, models.HookEventPullRequestLabel,
models.HookEventPullRequestMilestone, models.HookEventPullRequestSync:
return getDiscordPullRequestPayload(p.(*api.PullRequestPayload), discord) return getDiscordPullRequestPayload(p.(*api.PullRequestPayload), discord)
case models.HookEventPullRequestRejected, models.HookEventPullRequestApproved, models.HookEventPullRequestComment: case models.HookEventPullRequestReviewRejected, models.HookEventPullRequestReviewApproved, models.HookEventPullRequestReviewComment:
return getDiscordPullRequestApprovalPayload(p.(*api.PullRequestPayload), discord, event) return getDiscordPullRequestApprovalPayload(p.(*api.PullRequestPayload), discord, event)
case models.HookEventRepository: case models.HookEventRepository:
return getDiscordRepositoryPayload(p.(*api.RepositoryPayload), discord) return getDiscordRepositoryPayload(p.(*api.RepositoryPayload), discord)
@ -428,9 +429,9 @@ func parseHookPullRequestEventType(event models.HookEventType) (string, error) {
switch event { switch event {
case models.HookEventPullRequestApproved: case models.HookEventPullRequestReviewApproved:
return "approved", nil return "approved", nil
case models.HookEventPullRequestRejected: case models.HookEventPullRequestReviewRejected:
return "rejected", nil return "rejected", nil
case models.HookEventPullRequestComment: case models.HookEventPullRequestComment:
return "comment", nil return "comment", nil

@ -189,7 +189,7 @@ func GetFeishuPayload(p api.Payloader, event models.HookEventType, meta string)
return getFeishuPushPayload(p.(*api.PushPayload)) return getFeishuPushPayload(p.(*api.PushPayload))
case models.HookEventPullRequest: case models.HookEventPullRequest:
return getFeishuPullRequestPayload(p.(*api.PullRequestPayload)) return getFeishuPullRequestPayload(p.(*api.PullRequestPayload))
case models.HookEventPullRequestApproved, models.HookEventPullRequestRejected, models.HookEventPullRequestComment: case models.HookEventPullRequestReviewApproved, models.HookEventPullRequestReviewRejected, models.HookEventPullRequestComment:
return getFeishuPullRequestApprovalPayload(p.(*api.PullRequestPayload), event) return getFeishuPullRequestApprovalPayload(p.(*api.PullRequestPayload), event)
case models.HookEventRepository: case models.HookEventRepository:
return getFeishuRepositoryPayload(p.(*api.RepositoryPayload)) return getFeishuRepositoryPayload(p.(*api.RepositoryPayload))

@ -395,7 +395,7 @@ func getMSTeamsPullRequestApprovalPayload(p *api.PullRequestPayload, event model
var text, title string var text, title string
var color int var color int
switch p.Action { switch p.Action {
case api.HookIssueSynchronized: case api.HookIssueReviewed:
action, err := parseHookPullRequestEventType(event) action, err := parseHookPullRequestEventType(event)
if err != nil { if err != nil {
return nil, err return nil, err
@ -405,9 +405,9 @@ func getMSTeamsPullRequestApprovalPayload(p *api.PullRequestPayload, event model
text = p.Review.Content text = p.Review.Content
switch event { switch event {
case models.HookEventPullRequestApproved: case models.HookEventPullRequestReviewApproved:
color = greenColor color = greenColor
case models.HookEventPullRequestRejected: case models.HookEventPullRequestReviewRejected:
color = redColor color = redColor
case models.HookEventPullRequestComment: case models.HookEventPullRequestComment:
color = greyColor color = greyColor
@ -555,15 +555,16 @@ func GetMSTeamsPayload(p api.Payloader, event models.HookEventType, meta string)
return getMSTeamsDeletePayload(p.(*api.DeletePayload)) return getMSTeamsDeletePayload(p.(*api.DeletePayload))
case models.HookEventFork: case models.HookEventFork:
return getMSTeamsForkPayload(p.(*api.ForkPayload)) return getMSTeamsForkPayload(p.(*api.ForkPayload))
case models.HookEventIssues: case models.HookEventIssues, models.HookEventIssueAssign, models.HookEventIssueLabel, models.HookEventIssueMilestone:
return getMSTeamsIssuesPayload(p.(*api.IssuePayload)) return getMSTeamsIssuesPayload(p.(*api.IssuePayload))
case models.HookEventIssueComment: case models.HookEventIssueComment, models.HookEventPullRequestComment:
return getMSTeamsIssueCommentPayload(p.(*api.IssueCommentPayload)) return getMSTeamsIssueCommentPayload(p.(*api.IssueCommentPayload))
case models.HookEventPush: case models.HookEventPush:
return getMSTeamsPushPayload(p.(*api.PushPayload)) return getMSTeamsPushPayload(p.(*api.PushPayload))
case models.HookEventPullRequest: case models.HookEventPullRequest, models.HookEventPullRequestAssign, models.HookEventPullRequestLabel,
models.HookEventPullRequestMilestone, models.HookEventPullRequestSync:
return getMSTeamsPullRequestPayload(p.(*api.PullRequestPayload)) return getMSTeamsPullRequestPayload(p.(*api.PullRequestPayload))
case models.HookEventPullRequestRejected, models.HookEventPullRequestApproved, models.HookEventPullRequestComment: case models.HookEventPullRequestReviewRejected, models.HookEventPullRequestReviewApproved, models.HookEventPullRequestReviewComment:
return getMSTeamsPullRequestApprovalPayload(p.(*api.PullRequestPayload), event) return getMSTeamsPullRequestApprovalPayload(p.(*api.PullRequestPayload), event)
case models.HookEventRepository: case models.HookEventRepository:
return getMSTeamsRepositoryPayload(p.(*api.RepositoryPayload)) return getMSTeamsRepositoryPayload(p.(*api.RepositoryPayload))

@ -271,7 +271,7 @@ func getSlackPullRequestApprovalPayload(p *api.PullRequestPayload, slack *SlackM
var text string var text string
switch p.Action { switch p.Action {
case api.HookIssueSynchronized: case api.HookIssueReviewed:
action, err := parseHookPullRequestEventType(event) action, err := parseHookPullRequestEventType(event)
if err != nil { if err != nil {
return nil, err return nil, err
@ -324,15 +324,16 @@ func GetSlackPayload(p api.Payloader, event models.HookEventType, meta string) (
return getSlackDeletePayload(p.(*api.DeletePayload), slack) return getSlackDeletePayload(p.(*api.DeletePayload), slack)
case models.HookEventFork: case models.HookEventFork:
return getSlackForkPayload(p.(*api.ForkPayload), slack) return getSlackForkPayload(p.(*api.ForkPayload), slack)
case models.HookEventIssues: case models.HookEventIssues, models.HookEventIssueAssign, models.HookEventIssueLabel, models.HookEventIssueMilestone:
return getSlackIssuesPayload(p.(*api.IssuePayload), slack) return getSlackIssuesPayload(p.(*api.IssuePayload), slack)
case models.HookEventIssueComment: case models.HookEventIssueComment, models.HookEventPullRequestComment:
return getSlackIssueCommentPayload(p.(*api.IssueCommentPayload), slack) return getSlackIssueCommentPayload(p.(*api.IssueCommentPayload), slack)
case models.HookEventPush: case models.HookEventPush:
return getSlackPushPayload(p.(*api.PushPayload), slack) return getSlackPushPayload(p.(*api.PushPayload), slack)
case models.HookEventPullRequest: case models.HookEventPullRequest, models.HookEventPullRequestAssign, models.HookEventPullRequestLabel,
models.HookEventPullRequestMilestone, models.HookEventPullRequestSync:
return getSlackPullRequestPayload(p.(*api.PullRequestPayload), slack) return getSlackPullRequestPayload(p.(*api.PullRequestPayload), slack)
case models.HookEventPullRequestRejected, models.HookEventPullRequestApproved, models.HookEventPullRequestComment: case models.HookEventPullRequestReviewRejected, models.HookEventPullRequestReviewApproved, models.HookEventPullRequestReviewComment:
return getSlackPullRequestApprovalPayload(p.(*api.PullRequestPayload), slack, event) return getSlackPullRequestApprovalPayload(p.(*api.PullRequestPayload), slack, event)
case models.HookEventRepository: case models.HookEventRepository:
return getSlackRepositoryPayload(p.(*api.RepositoryPayload), slack) return getSlackRepositoryPayload(p.(*api.RepositoryPayload), slack)

@ -151,7 +151,7 @@ func getTelegramPullRequestPayload(p *api.PullRequestPayload) (*TelegramPayload,
func getTelegramPullRequestApprovalPayload(p *api.PullRequestPayload, event models.HookEventType) (*TelegramPayload, error) { func getTelegramPullRequestApprovalPayload(p *api.PullRequestPayload, event models.HookEventType) (*TelegramPayload, error) {
var text, attachmentText string var text, attachmentText string
switch p.Action { switch p.Action {
case api.HookIssueSynchronized: case api.HookIssueReviewed:
action, err := parseHookPullRequestEventType(event) action, err := parseHookPullRequestEventType(event)
if err != nil { if err != nil {
return nil, err return nil, err
@ -203,15 +203,16 @@ func GetTelegramPayload(p api.Payloader, event models.HookEventType, meta string
return getTelegramDeletePayload(p.(*api.DeletePayload)) return getTelegramDeletePayload(p.(*api.DeletePayload))
case models.HookEventFork: case models.HookEventFork:
return getTelegramForkPayload(p.(*api.ForkPayload)) return getTelegramForkPayload(p.(*api.ForkPayload))
case models.HookEventIssues: case models.HookEventIssues, models.HookEventIssueAssign, models.HookEventIssueLabel, models.HookEventIssueMilestone:
return getTelegramIssuesPayload(p.(*api.IssuePayload)) return getTelegramIssuesPayload(p.(*api.IssuePayload))
case models.HookEventIssueComment: case models.HookEventIssueComment, models.HookEventPullRequestComment:
return getTelegramIssueCommentPayload(p.(*api.IssueCommentPayload)) return getTelegramIssueCommentPayload(p.(*api.IssueCommentPayload))
case models.HookEventPush: case models.HookEventPush:
return getTelegramPushPayload(p.(*api.PushPayload)) return getTelegramPushPayload(p.(*api.PushPayload))
case models.HookEventPullRequest: case models.HookEventPullRequest, models.HookEventPullRequestAssign, models.HookEventPullRequestLabel,
models.HookEventPullRequestMilestone, models.HookEventPullRequestSync:
return getTelegramPullRequestPayload(p.(*api.PullRequestPayload)) return getTelegramPullRequestPayload(p.(*api.PullRequestPayload))
case models.HookEventPullRequestRejected, models.HookEventPullRequestApproved, models.HookEventPullRequestComment: case models.HookEventPullRequestReviewRejected, models.HookEventPullRequestReviewApproved, models.HookEventPullRequestReviewComment:
return getTelegramPullRequestApprovalPayload(p.(*api.PullRequestPayload), event) return getTelegramPullRequestApprovalPayload(p.(*api.PullRequestPayload), event)
case models.HookEventRepository: case models.HookEventRepository:
return getTelegramRepositoryPayload(p.(*api.RepositoryPayload)) return getTelegramRepositoryPayload(p.(*api.RepositoryPayload))

@ -1380,26 +1380,47 @@ settings.event_desc = Trigger On:
settings.event_push_only = Push Events settings.event_push_only = Push Events
settings.event_send_everything = All Events settings.event_send_everything = All Events
settings.event_choose = Custom Events… settings.event_choose = Custom Events…
settings.event_header_repository = Repository Events
settings.event_create = Create settings.event_create = Create
settings.event_create_desc = Branch or tag created. settings.event_create_desc = Branch or tag created.
settings.event_delete = Delete settings.event_delete = Delete
settings.event_delete_desc = Branch or tag deleted settings.event_delete_desc = Branch or tag deleted.
settings.event_fork = Fork settings.event_fork = Fork
settings.event_fork_desc = Repository forked settings.event_fork_desc = Repository forked.
settings.event_issues = Issues
settings.event_issues_desc = Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment = Issue Comment
settings.event_issue_comment_desc = Issue comment created, edited, or deleted.
settings.event_release = Release settings.event_release = Release
settings.event_release_desc = Release published, updated or deleted in a repository. settings.event_release_desc = Release published, updated or deleted in a repository.
settings.event_pull_request = Pull Request
settings.event_pull_request_desc = Pull request opened, closed, reopened, edited, approved, rejected, review comment, assigned, unassigned, label updated, label cleared or synchronized.
settings.event_push = Push settings.event_push = Push
settings.event_push_desc = Git push to a repository. settings.event_push_desc = Git push to a repository.
settings.branch_filter = Branch filter
settings.branch_filter_desc = Branch whitelist for push, branch creation and branch deletion events, specified as glob pattern. If empty or <code>*</code>, events for all branches are reported. See <a href="https://godoc.org/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> documentation for syntax. Examples: <code>master</code>, <code>{master,release*}</code>.
settings.event_repository = Repository settings.event_repository = Repository
settings.event_repository_desc = Repository created or deleted. settings.event_repository_desc = Repository created or deleted.
settings.event_header_issue = Issue Events
settings.event_issues = Issues
settings.event_issues_desc = Issue opened, closed, reopened, or edited.
settings.event_issue_assign = Issue Assigned
settings.event_issue_assign_desc = Issue assigned or unassigned.
settings.event_issue_label = Issue Labeled
settings.event_issue_label_desc = Issue labels updated or cleared.
settings.event_issue_milestone = Issue Milestoned
settings.event_issue_milestone_desc = Issue milestoned or demilestoned.
settings.event_issue_comment = Issue Comment
settings.event_issue_comment_desc = Issue comment created, edited, or deleted.
settings.event_header_pull_request = Pull Request Events
settings.event_pull_request = Pull Request
settings.event_pull_request_desc = Pull request opened, closed, reopened, or edited.
settings.event_pull_request_assign = Pull Request Assigned
settings.event_pull_request_assign_desc = Pull request assigned or unassigned.
settings.event_pull_request_label = Pull Request Labeled
settings.event_pull_request_label_desc = Pull request labels updated or cleared.
settings.event_pull_request_milestone = Pull Request Milestoned
settings.event_pull_request_milestone_desc = Pull request milestoned or demilestoned.
settings.event_pull_request_comment = Pull Request Comment
settings.event_pull_request_comment_desc = Pull request comment created, edited, or deleted.
settings.event_pull_request_review = Pull Request Reviewed
settings.event_pull_request_review_desc = Pull request approved, rejected, or review comment.
settings.event_pull_request_sync = Pull Request Synchronized
settings.event_pull_request_sync_desc = Pull request synchronized.
settings.branch_filter = Branch filter
settings.branch_filter_desc = Branch whitelist for push, branch creation and branch deletion events, specified as glob pattern. If empty or <code>*</code>, events for all branches are reported. See <a href="https://godoc.org/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> documentation for syntax. Examples: <code>master</code>, <code>{master,release*}</code>.
settings.active = Active settings.active = Active
settings.active_helper = Information about triggered events will be sent to this webhook URL. settings.active_helper = Information about triggered events will be sent to this webhook URL.
settings.add_hook_success = The webhook has been added. settings.add_hook_success = The webhook has been added.

@ -87,6 +87,14 @@ func AddRepoHook(ctx *context.APIContext, form *api.CreateHookOption) {
} }
} }
func issuesHook(events []string, event string) bool {
return com.IsSliceContainsStr(events, event) || com.IsSliceContainsStr(events, string(models.HookEventIssues))
}
func pullHook(events []string, event string) bool {
return com.IsSliceContainsStr(events, event) || com.IsSliceContainsStr(events, string(models.HookEventPullRequest))
}
// addHook add the hook specified by `form`, `orgID` and `repoID`. If there is // addHook add the hook specified by `form`, `orgID` and `repoID`. If there is
// an error, write to `ctx` accordingly. Return (webhook, ok) // an error, write to `ctx` accordingly. Return (webhook, ok)
func addHook(ctx *context.APIContext, form *api.CreateHookOption, orgID, repoID int64) (*models.Webhook, bool) { func addHook(ctx *context.APIContext, form *api.CreateHookOption, orgID, repoID int64) (*models.Webhook, bool) {
@ -103,15 +111,24 @@ func addHook(ctx *context.APIContext, form *api.CreateHookOption, orgID, repoID
HookEvent: &models.HookEvent{ HookEvent: &models.HookEvent{
ChooseEvents: true, ChooseEvents: true,
HookEvents: models.HookEvents{ HookEvents: models.HookEvents{
Create: com.IsSliceContainsStr(form.Events, string(models.HookEventCreate)), Create: com.IsSliceContainsStr(form.Events, string(models.HookEventCreate)),
Delete: com.IsSliceContainsStr(form.Events, string(models.HookEventDelete)), Delete: com.IsSliceContainsStr(form.Events, string(models.HookEventDelete)),
Fork: com.IsSliceContainsStr(form.Events, string(models.HookEventFork)), Fork: com.IsSliceContainsStr(form.Events, string(models.HookEventFork)),
Issues: com.IsSliceContainsStr(form.Events, string(models.HookEventIssues)), Issues: issuesHook(form.Events, "issues_only"),
IssueComment: com.IsSliceContainsStr(form.Events, string(models.HookEventIssueComment)), IssueAssign: issuesHook(form.Events, string(models.HookEventIssueAssign)),
Push: com.IsSliceContainsStr(form.Events, string(models.HookEventPush)), IssueLabel: issuesHook(form.Events, string(models.HookEventIssueLabel)),
PullRequest: com.IsSliceContainsStr(form.Events, string(models.HookEventPullRequest)), IssueMilestone: issuesHook(form.Events, string(models.HookEventIssueMilestone)),
Repository: com.IsSliceContainsStr(form.Events, string(models.HookEventRepository)), IssueComment: issuesHook(form.Events, string(models.HookEventIssueComment)),
Release: com.IsSliceContainsStr(form.Events, string(models.HookEventRelease)), Push: com.IsSliceContainsStr(form.Events, string(models.HookEventPush)),
PullRequest: pullHook(form.Events, "pull_request_only"),
PullRequestAssign: pullHook(form.Events, string(models.HookEventPullRequestAssign)),
PullRequestLabel: pullHook(form.Events, string(models.HookEventPullRequestLabel)),
PullRequestMilestone: pullHook(form.Events, string(models.HookEventPullRequestMilestone)),
PullRequestComment: pullHook(form.Events, string(models.HookEventPullRequestComment)),
PullRequestReview: pullHook(form.Events, "pull_request_review"),
PullRequestSync: pullHook(form.Events, string(models.HookEventPullRequestSync)),
Repository: com.IsSliceContainsStr(form.Events, string(models.HookEventRepository)),
Release: com.IsSliceContainsStr(form.Events, string(models.HookEventRelease)),
}, },
BranchFilter: form.BranchFilter, BranchFilter: form.BranchFilter,
}, },

@ -136,15 +136,24 @@ func ParseHookEvent(form auth.WebhookForm) *models.HookEvent {
SendEverything: form.SendEverything(), SendEverything: form.SendEverything(),
ChooseEvents: form.ChooseEvents(), ChooseEvents: form.ChooseEvents(),
HookEvents: models.HookEvents{ HookEvents: models.HookEvents{
Create: form.Create, Create: form.Create,
Delete: form.Delete, Delete: form.Delete,
Fork: form.Fork, Fork: form.Fork,
Issues: form.Issues, Issues: form.Issues,
IssueComment: form.IssueComment, IssueAssign: form.IssueAssign,
Release: form.Release, IssueLabel: form.IssueLabel,
Push: form.Push, IssueMilestone: form.IssueMilestone,
PullRequest: form.PullRequest, IssueComment: form.IssueComment,
Repository: form.Repository, Release: form.Release,
Push: form.Push,
PullRequest: form.PullRequest,
PullRequestAssign: form.PullRequestAssign,
PullRequestLabel: form.PullRequestLabel,
PullRequestMilestone: form.PullRequestMilestone,
PullRequestComment: form.PullRequestComment,
PullRequestReview: form.PullRequestReview,
PullRequestSync: form.PullRequestSync,
Repository: form.Repository,
}, },
BranchFilter: form.BranchFilter, BranchFilter: form.BranchFilter,
} }

@ -23,6 +23,10 @@
</div> </div>
<div class="events fields ui grid" {{if not .Webhook.ChooseEvents}}style="display:none"{{end}}> <div class="events fields ui grid" {{if not .Webhook.ChooseEvents}}style="display:none"{{end}}>
<!-- Repository Events -->
<div class="fourteen wide column">
<label>{{.i18n.Tr "repo.settings.event_header_repository"}}</label>
</div>
<!-- Create --> <!-- Create -->
<div class="seven wide column"> <div class="seven wide column">
<div class="field"> <div class="field">
@ -63,6 +67,31 @@
</div> </div>
</div> </div>
</div> </div>
<!-- Repository -->
<div class="seven wide column">
<div class="field">
<div class="ui checkbox">
<input class="hidden" name="repository" type="checkbox" tabindex="0" {{if .Webhook.Repository}}checked{{end}}>
<label>{{.i18n.Tr "repo.settings.event_repository"}}</label>
<span class="help">{{.i18n.Tr "repo.settings.event_repository_desc"}}</span>
</div>
</div>
</div>
<!-- Release -->
<div class="seven wide column">
<div class="field">
<div class="ui checkbox">
<input class="hidden" name="release" type="checkbox" tabindex="0" {{if .Webhook.Release}}checked{{end}}>
<label>{{.i18n.Tr "repo.settings.event_release"}}</label>
<span class="help">{{.i18n.Tr "repo.settings.event_release_desc"}}</span>
</div>
</div>
</div>
<!-- Issue Events -->
<div class="fourteen wide column">
<label>{{.i18n.Tr "repo.settings.event_header_issue"}}</label>
</div>
<!-- Issues --> <!-- Issues -->
<div class="seven wide column"> <div class="seven wide column">
<div class="field"> <div class="field">
@ -73,6 +102,36 @@
</div> </div>
</div> </div>
</div> </div>
<!-- Issue Assign -->
<div class="seven wide column">
<div class="field">
<div class="ui checkbox">
<input class="hidden" name="issue_assign" type="checkbox" tabindex="0" {{if .Webhook.IssueAssign}}checked{{end}}>
<label>{{.i18n.Tr "repo.settings.event_issue_assign"}}</label>
<span class="help">{{.i18n.Tr "repo.settings.event_issue_assign_desc"}}</span>
</div>
</div>
</div>
<!-- Issue Label -->
<div class="seven wide column">
<div class="field">
<div class="ui checkbox">
<input class="hidden" name="issue_label" type="checkbox" tabindex="0" {{if .Webhook.IssueLabel}}checked{{end}}>
<label>{{.i18n.Tr "repo.settings.event_issue_label"}}</label>
<span class="help">{{.i18n.Tr "repo.settings.event_issue_label_desc"}}</span>
</div>
</div>
</div>
<!-- Issue Milestone -->
<div class="seven wide column">
<div class="field">
<div class="ui checkbox">
<input class="hidden" name="issue_milestone" type="checkbox" tabindex="0" {{if .Webhook.IssueMilestone}}checked{{end}}>
<label>{{.i18n.Tr "repo.settings.event_issue_milestone"}}</label>
<span class="help">{{.i18n.Tr "repo.settings.event_issue_milestone_desc"}}</span>
</div>
</div>
</div>
<!-- Issue Comment --> <!-- Issue Comment -->
<div class="seven wide column"> <div class="seven wide column">
<div class="field"> <div class="field">
@ -83,6 +142,11 @@
</div> </div>
</div> </div>
</div> </div>
<!-- Pull Request Events -->
<div class="fourteen wide column">
<label>{{.i18n.Tr "repo.settings.event_header_pull_request"}}</label>
</div>
<!-- Pull Request --> <!-- Pull Request -->
<div class="seven wide column"> <div class="seven wide column">
<div class="field"> <div class="field">
@ -93,23 +157,63 @@
</div> </div>
</div> </div>
</div> </div>
<!-- Repository --> <!-- Pull Request Assign -->
<div class="seven wide column"> <div class="seven wide column">
<div class="field"> <div class="field">
<div class="ui checkbox"> <div class="ui checkbox">
<input class="hidden" name="repository" type="checkbox" tabindex="0" {{if .Webhook.Repository}}checked{{end}}> <input class="hidden" name="pull_request_assign" type="checkbox" tabindex="0" {{if .Webhook.PullRequestAssign}}checked{{end}}>
<label>{{.i18n.Tr "repo.settings.event_repository"}}</label> <label>{{.i18n.Tr "repo.settings.event_pull_request_assign"}}</label>
<span class="help">{{.i18n.Tr "repo.settings.event_repository_desc"}}</span> <span class="help">{{.i18n.Tr "repo.settings.event_pull_request_assign_desc"}}</span>
</div> </div>
</div> </div>
</div> </div>
<!-- Release --> <!-- Pull Request Label -->
<div class="seven wide column"> <div class="seven wide column">
<div class="field"> <div class="field">
<div class="ui checkbox"> <div class="ui checkbox">
<input class="hidden" name="release" type="checkbox" tabindex="0" {{if .Webhook.Release}}checked{{end}}> <input class="hidden" name="pull_request_label" type="checkbox" tabindex="0" {{if .Webhook.PullRequestLabel}}checked{{end}}>
<label>{{.i18n.Tr "repo.settings.event_release"}}</label> <label>{{.i18n.Tr "repo.settings.event_pull_request_label"}}</label>
<span class="help">{{.i18n.Tr "repo.settings.event_release_desc"}}</span> <span class="help">{{.i18n.Tr "repo.settings.event_pull_request_label_desc"}}</span>
</div>
</div>
</div>
<!-- Pull Request Milestone -->
<div class="seven wide column">
<div class="field">
<div class="ui checkbox">
<input class="hidden" name="pull_request_milestone" type="checkbox" tabindex="0" {{if .Webhook.PullRequestMilestone}}checked{{end}}>
<label>{{.i18n.Tr "repo.settings.event_pull_request_milestone"}}</label>
<span class="help">{{.i18n.Tr "repo.settings.event_pull_request_milestone_desc"}}</span>
</div>
</div>
</div>
<!-- Pull Request Comment -->
<div class="seven wide column">
<div class="field">
<div class="ui checkbox">
<input class="hidden" name="pull_request_comment" type="checkbox" tabindex="0" {{if .Webhook.PullRequestComment}}checked{{end}}>
<label>{{.i18n.Tr "repo.settings.event_pull_request_comment"}}</label>
<span class="help">{{.i18n.Tr "repo.settings.event_pull_request_comment_desc"}}</span>
</div>
</div>
</div>
<!-- Pull Request Review -->
<div class="seven wide column">
<div class="field">
<div class="ui checkbox">
<input class="hidden" name="pull_request_review" type="checkbox" tabindex="0" {{if .Webhook.PullRequestReview}}checked{{end}}>
<label>{{.i18n.Tr "repo.settings.event_pull_request_review"}}</label>
<span class="help">{{.i18n.Tr "repo.settings.event_pull_request_review_desc"}}</span>
</div>
</div>
</div>
<!-- Pull Request Sync -->
<div class="seven wide column">
<div class="field">
<div class="ui checkbox">
<input class="hidden" name="pull_request_sync" type="checkbox" tabindex="0" {{if .Webhook.PullRequestSync}}checked{{end}}>
<label>{{.i18n.Tr "repo.settings.event_pull_request_sync"}}</label>
<span class="help">{{.i18n.Tr "repo.settings.event_pull_request_sync_desc"}}</span>
</div> </div>
</div> </div>
</div> </div>

Loading…
Cancel
Save