Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Granular webhook events #9626

Merged
merged 29 commits into from
Mar 6, 2020
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
b9944ec
Initial work
jolheiser Dec 18, 2019
f448067
Add PR reviews and API coverage
jolheiser Dec 18, 2019
1120940
Merge branch 'master' of github.com:go-gitea/gitea into granular_webhook
jolheiser Jan 6, 2020
0e35801
Split up events
jolheiser Jan 6, 2020
ed56ac1
Add migration and locale
jolheiser Jan 7, 2020
3b922b9
Format
jolheiser Jan 7, 2020
5fb82d8
Revert IsPull
jolheiser Jan 7, 2020
314e704
Fix comments
jolheiser Jan 7, 2020
465b1f2
Fix tests
jolheiser Jan 7, 2020
4f70eef
Merge branch 'master' into granular_webhook
jolheiser Jan 7, 2020
7885ffe
Merge branch 'master' into granular_webhook
jolheiser Jan 7, 2020
4d165ca
Merge branch 'master' into granular_webhook
jolheiser Jan 8, 2020
70d1473
Merge master and transform events back into non-breaking strings
jolheiser Jan 19, 2020
5c24d13
Fix PR reviews
jolheiser Jan 19, 2020
50d0484
Fix issue_comment
jolheiser Jan 19, 2020
d8fa08d
Merge branch 'master' into granular_webhook
jolheiser Jan 19, 2020
ad122d3
Merge branch 'master' of github.com:go-gitea/gitea into granular_webhook
jolheiser Feb 13, 2020
40eeecc
Merge branch 'granular_webhook' of github.com:jolheiser/gitea into gr…
jolheiser Feb 13, 2020
b0af0ae
Make fmt
jolheiser Feb 13, 2020
6db2aa8
Merge branch 'master' of github.com:go-gitea/gitea into granular_webhook
jolheiser Mar 1, 2020
9439696
Migrations
jolheiser Mar 1, 2020
7d96bf8
Backwards compatible API
jolheiser Mar 1, 2020
70b5dbb
Fix feishu
jolheiser Mar 1, 2020
2dd70bc
Move session commit
jolheiser Mar 2, 2020
5060334
Merge branch 'master' into granular_webhook
lafriks Mar 2, 2020
1a91e77
Merge branch 'master' into granular_webhook
guillep2k Mar 3, 2020
a907681
Merge branch 'master' of https://github.com/go-gitea/gitea into granu…
jolheiser Mar 5, 2020
896f955
Merge branch 'master' into granular_webhook
lafriks Mar 5, 2020
0c37fca
Merge branch 'master' into granular_webhook
guillep2k Mar 6, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions models/migrations/migrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ var migrations = []Migration{
NewMigration("Fix topic repository count", fixTopicRepositoryCount),
// v127 -> v128
NewMigration("add repository code language statistics", addLanguageStats),
// v128 -> v129
NewMigration("Expand webhooks for more granularity", expandWebhooks),
}

// Migrate database to current version
Expand Down
101 changes: 101 additions & 0 deletions models/migrations/v128.go
Original file line number Diff line number Diff line change
@@ -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
}
168 changes: 147 additions & 21 deletions models/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,24 @@ func IsValidHookContentType(name string) bool {

// HookEvents is a set of web hook events
type HookEvents struct {
Create bool `json:"create"`
Delete bool `json:"delete"`
Fork bool `json:"fork"`
Issues bool `json:"issues"`
IssueComment bool `json:"issue_comment"`
Push bool `json:"push"`
PullRequest bool `json:"pull_request"`
Repository bool `json:"repository"`
Release bool `json:"release"`
Create bool `json:"create"`
Delete bool `json:"delete"`
Fork bool `json:"fork"`
Issues bool `json:"issues"`
IssueAssign bool `json:"issue_assign"`
IssueLabel bool `json:"issue_label"`
IssueMilestone bool `json:"issue_milestone"`
IssueComment bool `json:"issue_comment"`
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.
Expand Down Expand Up @@ -154,6 +163,24 @@ func (w *Webhook) HasIssuesEvent() bool {
(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.
func (w *Webhook) HasIssueCommentEvent() bool {
return w.SendEverything ||
Expand All @@ -172,6 +199,54 @@ func (w *Webhook) HasPullRequestEvent() bool {
(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.
func (w *Webhook) HasReleaseEvent() bool {
return w.SendEverything ||
Expand All @@ -198,8 +273,19 @@ func (w *Webhook) EventCheckers() []struct {
{w.HasForkEvent, HookEventFork},
{w.HasPushEvent, HookEventPush},
{w.HasIssuesEvent, HookEventIssues},
{w.HasIssuesAssignEvent, HookEventIssueAssign},
{w.HasIssuesLabelEvent, HookEventIssueLabel},
{w.HasIssuesMilestoneEvent, HookEventIssueMilestone},
{w.HasIssueCommentEvent, HookEventIssueComment},
{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.HasReleaseEvent, HookEventRelease},
}
Expand Down Expand Up @@ -498,20 +584,60 @@ type HookEventType string

// Types of hook events
const (
HookEventCreate HookEventType = "create"
HookEventDelete HookEventType = "delete"
HookEventFork HookEventType = "fork"
HookEventPush HookEventType = "push"
HookEventIssues HookEventType = "issues"
HookEventIssueComment HookEventType = "issue_comment"
HookEventPullRequest HookEventType = "pull_request"
HookEventRepository HookEventType = "repository"
HookEventRelease HookEventType = "release"
HookEventPullRequestApproved HookEventType = "pull_request_approved"
HookEventPullRequestRejected HookEventType = "pull_request_rejected"
HookEventPullRequestComment HookEventType = "pull_request_comment"
HookEventCreate HookEventType = "create"
lafriks marked this conversation as resolved.
Show resolved Hide resolved
HookEventDelete HookEventType = "delete"
HookEventFork HookEventType = "fork"
HookEventPush HookEventType = "push"
HookEventIssues HookEventType = "issues"
HookEventIssueAssign HookEventType = "issue_assign"
HookEventIssueLabel HookEventType = "issue_label"
HookEventIssueMilestone HookEventType = "issue_milestone"
HookEventIssueComment HookEventType = "issue_comment"
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"
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 ""
}

lafriks marked this conversation as resolved.
Show resolved Hide resolved
// HookRequest represents hook task request information.
type HookRequest struct {
Headers map[string]string `json:"headers"`
Expand Down
6 changes: 5 additions & 1 deletion models/webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,11 @@ func TestWebhook_UpdateEvent(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{
HookEvent: &HookEvent{SendEverything: true},
}).EventsArray(),
Expand Down
33 changes: 21 additions & 12 deletions modules/auth/repo_form.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,18 +190,27 @@ func (f *ProtectBranchForm) Validate(ctx *macaron.Context, errs binding.Errors)

// WebhookForm form for changing web hook
type WebhookForm struct {
Events string
Create bool
Delete bool
Fork bool
Issues bool
IssueComment bool
Release bool
Push bool
PullRequest bool
Repository bool
Active bool
BranchFilter string `binding:"GlobPattern"`
Events string
Create bool
Delete bool
Fork bool
Issues bool
IssueAssign bool
IssueLabel bool
IssueMilestone bool
IssueComment bool
Release bool
Push bool
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
Expand Down
Loading