diff options
author | John Olheiser <john.olheiser@gmail.com> | 2020-03-05 23:10:48 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-03-06 07:10:48 +0200 |
commit | 3f1c0841cb9fc61136b85c6b39613679d2851707 (patch) | |
tree | d0b15f3b809891d83f41fed5ab7378765330525a /models | |
parent | 80db44267ccb688c596e8375523af5cd92864d87 (diff) | |
download | gitea-3f1c0841cb9fc61136b85c6b39613679d2851707.tar.gz gitea-3f1c0841cb9fc61136b85c6b39613679d2851707.zip |
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>
Diffstat (limited to 'models')
-rw-r--r-- | models/migrations/migrations.go | 2 | ||||
-rw-r--r-- | models/migrations/v130.go | 101 | ||||
-rw-r--r-- | models/webhook.go | 168 | ||||
-rw-r--r-- | models/webhook_test.go | 6 |
4 files changed, 255 insertions, 22 deletions
diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index bb72b7f5d3..ba411dd8c2 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -192,6 +192,8 @@ var migrations = []Migration{ NewMigration("fix merge base for pull requests", fixMergeBase), // v129 -> v130 NewMigration("remove dependencies from deleted repositories", purgeUnusedDependencies), + // v130 -> v131 + NewMigration("Expand webhooks for more granularity", expandWebhooks), } // Migrate database to current version diff --git a/models/migrations/v130.go b/models/migrations/v130.go new file mode 100644 index 0000000000..3a7efedf86 --- /dev/null +++ b/models/migrations/v130.go @@ -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 +} diff --git a/models/webhook.go b/models/webhook.go index 626489b342..82aedf7e81 100644 --- a/models/webhook.go +++ b/models/webhook.go @@ -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. @@ -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 || @@ -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 || @@ -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}, } @@ -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" + 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 "" +} + // HookRequest represents hook task request information. type HookRequest struct { Headers map[string]string `json:"headers"` diff --git a/models/webhook_test.go b/models/webhook_test.go index f8e4234299..5ee7f9159b 100644 --- a/models/webhook_test.go +++ b/models/webhook_test.go @@ -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(), |