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>
release/v1.15
John Olheiser 2020-03-05 23:10:48 -06:00 committed by GitHub
parent 80db44267c
commit 3f1c0841cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 624 additions and 173 deletions

View File

@ -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

101
models/migrations/v130.go Normal file
View File

@ -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
}

View File

@ -61,9 +61,18 @@ type HookEvents struct {
Delete bool `json:"delete"` Delete bool `json:"delete"`
Fork bool `json:"fork"` Fork bool `json:"fork"`
Issues bool `json:"issues"` Issues bool `json:"issues"`
IssueAssign bool `json:"issue_assign"`
IssueLabel bool `json:"issue_label"`
IssueMilestone bool `json:"issue_milestone"`
IssueComment bool `json:"issue_comment"` IssueComment bool `json:"issue_comment"`
Push bool `json:"push"` Push bool `json:"push"`
PullRequest bool `json:"pull_request"` 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"` Repository bool `json:"repository"`
Release bool `json:"release"` Release bool `json:"release"`
} }
@ -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},
} }
@ -503,15 +589,55 @@ const (
HookEventFork HookEventType = "fork" HookEventFork HookEventType = "fork"
HookEventPush HookEventType = "push" HookEventPush HookEventType = "push"
HookEventIssues HookEventType = "issues" HookEventIssues HookEventType = "issues"
HookEventIssueAssign HookEventType = "issue_assign"
HookEventIssueLabel HookEventType = "issue_label"
HookEventIssueMilestone HookEventType = "issue_milestone"
HookEventIssueComment HookEventType = "issue_comment" HookEventIssueComment HookEventType = "issue_comment"
HookEventPullRequest HookEventType = "pull_request" HookEventPullRequest HookEventType = "pull_request"
HookEventPullRequestAssign HookEventType = "pull_request_assign"
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" HookEventRepository HookEventType = "repository"
HookEventRelease HookEventType = "release" HookEventRelease HookEventType = "release"
HookEventPullRequestApproved HookEventType = "pull_request_approved"
HookEventPullRequestRejected HookEventType = "pull_request_rejected"
HookEventPullRequestComment HookEventType = "pull_request_comment"
) )
// 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"`

View File

@ -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(),

View File

@ -195,10 +195,19 @@ type WebhookForm struct {
Delete bool Delete bool
Fork bool Fork bool
Issues bool Issues bool
IssueAssign bool
IssueLabel bool
IssueMilestone bool
IssueComment bool IssueComment bool
Release bool Release bool
Push bool Push bool
PullRequest bool PullRequest bool
PullRequestAssign bool
PullRequestLabel bool
PullRequestMilestone bool
PullRequestComment bool
PullRequestReview bool
PullRequestSync bool
Repository bool Repository bool
Active bool Active bool
BranchFilter string `binding:"GlobPattern"` BranchFilter string `binding:"GlobPattern"`

View File

@ -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,22 +338,25 @@ 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 {
err = webhook_module.PrepareWebhooks(c.Issue.Repo, models.HookEventPullRequestComment, &api.IssueCommentPayload{
Action: api.HookIssueCommentEdited, Action: api.HookIssueCommentEdited,
Issue: convert.ToAPIIssue(c.Issue), Issue: convert.ToAPIIssue(c.Issue),
Comment: c.APIFormat(), Comment: c.APIFormat(),
@ -364,8 +367,25 @@ func (m *webhookNotifier) NotifyUpdateComment(doer *models.User, c *models.Comme
}, },
Repository: c.Issue.Repo.APIFormat(mode), Repository: c.Issue.Repo.APIFormat(mode),
Sender: doer.APIFormat(), Sender: doer.APIFormat(),
IsPull: c.Issue.IsPull, IsPull: true,
}); 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{
var err error
if issue.IsPull {
err = webhook_module.PrepareWebhooks(issue.Repo, models.HookEventPullRequestComment, &api.IssueCommentPayload{
Action: api.HookIssueCommentCreated, Action: api.HookIssueCommentCreated,
Issue: convert.ToAPIIssue(issue), Issue: convert.ToAPIIssue(issue),
Comment: comment.APIFormat(), Comment: comment.APIFormat(),
Repository: repo.APIFormat(mode), Repository: repo.APIFormat(mode),
Sender: doer.APIFormat(), Sender: doer.APIFormat(),
IsPull: issue.IsPull, IsPull: true,
}); err != nil { })
} 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 {
err = webhook_module.PrepareWebhooks(comment.Issue.Repo, models.HookEventPullRequestComment, &api.IssueCommentPayload{
Action: api.HookIssueCommentDeleted, Action: api.HookIssueCommentDeleted,
Issue: convert.ToAPIIssue(comment.Issue), Issue: convert.ToAPIIssue(comment.Issue),
Comment: comment.APIFormat(), Comment: comment.APIFormat(),
Repository: comment.Issue.Repo.APIFormat(mode), Repository: comment.Issue.Repo.APIFormat(mode),
Sender: doer.APIFormat(), Sender: doer.APIFormat(),
IsPull: comment.Issue.IsPull, IsPull: true,
}); err != nil { })
} 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),

View File

@ -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.

View File

@ -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{

View File

@ -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))

View File

@ -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

View File

@ -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))

View File

@ -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))

View File

@ -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)

View File

@ -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))

View File

@ -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.

View File

@ -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) {
@ -106,10 +114,19 @@ func addHook(ctx *context.APIContext, form *api.CreateHookOption, orgID, repoID
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)),
IssueLabel: issuesHook(form.Events, string(models.HookEventIssueLabel)),
IssueMilestone: issuesHook(form.Events, string(models.HookEventIssueMilestone)),
IssueComment: issuesHook(form.Events, string(models.HookEventIssueComment)),
Push: com.IsSliceContainsStr(form.Events, string(models.HookEventPush)), Push: com.IsSliceContainsStr(form.Events, string(models.HookEventPush)),
PullRequest: com.IsSliceContainsStr(form.Events, string(models.HookEventPullRequest)), 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)), Repository: com.IsSliceContainsStr(form.Events, string(models.HookEventRepository)),
Release: com.IsSliceContainsStr(form.Events, string(models.HookEventRelease)), Release: com.IsSliceContainsStr(form.Events, string(models.HookEventRelease)),
}, },

View File

@ -140,10 +140,19 @@ func ParseHookEvent(form auth.WebhookForm) *models.HookEvent {
Delete: form.Delete, Delete: form.Delete,
Fork: form.Fork, Fork: form.Fork,
Issues: form.Issues, Issues: form.Issues,
IssueAssign: form.IssueAssign,
IssueLabel: form.IssueLabel,
IssueMilestone: form.IssueMilestone,
IssueComment: form.IssueComment, IssueComment: form.IssueComment,
Release: form.Release, Release: form.Release,
Push: form.Push, Push: form.Push,
PullRequest: form.PullRequest, PullRequest: form.PullRequest,
PullRequestAssign: form.PullRequestAssign,
PullRequestLabel: form.PullRequestLabel,
PullRequestMilestone: form.PullRequestMilestone,
PullRequestComment: form.PullRequestComment,
PullRequestReview: form.PullRequestReview,
PullRequestSync: form.PullRequestSync,
Repository: form.Repository, Repository: form.Repository,
}, },
BranchFilter: form.BranchFilter, BranchFilter: form.BranchFilter,

View File

@ -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,36 +67,6 @@
</div> </div>
</div> </div>
</div> </div>
<!-- Issues -->
<div class="seven wide column">
<div class="field">
<div class="ui checkbox">
<input class="hidden" name="issues" type="checkbox" tabindex="0" {{if .Webhook.Issues}}checked{{end}}>
<label>{{.i18n.Tr "repo.settings.event_issues"}}</label>
<span class="help">{{.i18n.Tr "repo.settings.event_issues_desc"}}</span>
</div>
</div>
</div>
<!-- Issue Comment -->
<div class="seven wide column">
<div class="field">
<div class="ui checkbox">
<input class="hidden" name="issue_comment" type="checkbox" tabindex="0" {{if .Webhook.IssueComment}}checked{{end}}>
<label>{{.i18n.Tr "repo.settings.event_issue_comment"}}</label>
<span class="help">{{.i18n.Tr "repo.settings.event_issue_comment_desc"}}</span>
</div>
</div>
</div>
<!-- Pull Request -->
<div class="seven wide column">
<div class="field">
<div class="ui checkbox">
<input class="hidden" name="pull_request" type="checkbox" tabindex="0" {{if .Webhook.PullRequest}}checked{{end}}>
<label>{{.i18n.Tr "repo.settings.event_pull_request"}}</label>
<span class="help">{{.i18n.Tr "repo.settings.event_pull_request_desc"}}</span>
</div>
</div>
</div>
<!-- Repository --> <!-- Repository -->
<div class="seven wide column"> <div class="seven wide column">
<div class="field"> <div class="field">
@ -113,6 +87,136 @@
</div> </div>
</div> </div>
</div> </div>
<!-- Issue Events -->
<div class="fourteen wide column">
<label>{{.i18n.Tr "repo.settings.event_header_issue"}}</label>
</div>
<!-- Issues -->
<div class="seven wide column">
<div class="field">
<div class="ui checkbox">
<input class="hidden" name="issues" type="checkbox" tabindex="0" {{if .Webhook.Issues}}checked{{end}}>
<label>{{.i18n.Tr "repo.settings.event_issues"}}</label>
<span class="help">{{.i18n.Tr "repo.settings.event_issues_desc"}}</span>
</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 -->
<div class="seven wide column">
<div class="field">
<div class="ui checkbox">
<input class="hidden" name="issue_comment" type="checkbox" tabindex="0" {{if .Webhook.IssueComment}}checked{{end}}>
<label>{{.i18n.Tr "repo.settings.event_issue_comment"}}</label>
<span class="help">{{.i18n.Tr "repo.settings.event_issue_comment_desc"}}</span>
</div>
</div>
</div>
<!-- Pull Request Events -->
<div class="fourteen wide column">
<label>{{.i18n.Tr "repo.settings.event_header_pull_request"}}</label>
</div>
<!-- Pull Request -->
<div class="seven wide column">
<div class="field">
<div class="ui checkbox">
<input class="hidden" name="pull_request" type="checkbox" tabindex="0" {{if .Webhook.PullRequest}}checked{{end}}>
<label>{{.i18n.Tr "repo.settings.event_pull_request"}}</label>
<span class="help">{{.i18n.Tr "repo.settings.event_pull_request_desc"}}</span>
</div>
</div>
</div>
<!-- Pull Request Assign -->
<div class="seven wide column">
<div class="field">
<div class="ui checkbox">
<input class="hidden" name="pull_request_assign" type="checkbox" tabindex="0" {{if .Webhook.PullRequestAssign}}checked{{end}}>
<label>{{.i18n.Tr "repo.settings.event_pull_request_assign"}}</label>
<span class="help">{{.i18n.Tr "repo.settings.event_pull_request_assign_desc"}}</span>
</div>
</div>
</div>
<!-- Pull Request Label -->
<div class="seven wide column">
<div class="field">
<div class="ui checkbox">
<input class="hidden" name="pull_request_label" type="checkbox" tabindex="0" {{if .Webhook.PullRequestLabel}}checked{{end}}>
<label>{{.i18n.Tr "repo.settings.event_pull_request_label"}}</label>
<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> </div>