uniform an abstract notification layer for ui, mail, action, webhook, indexer
This commit is contained in:
parent
659bc727bd
commit
fdb5bd2d20
1
main.go
1
main.go
|
@ -16,6 +16,7 @@ import (
|
||||||
// register supported doc types
|
// register supported doc types
|
||||||
_ "code.gitea.io/gitea/modules/markup/markdown"
|
_ "code.gitea.io/gitea/modules/markup/markdown"
|
||||||
_ "code.gitea.io/gitea/modules/markup/orgmode"
|
_ "code.gitea.io/gitea/modules/markup/orgmode"
|
||||||
|
_ "code.gitea.io/gitea/modules/notification/init"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
)
|
)
|
||||||
|
|
|
@ -1035,36 +1035,6 @@ func NewIssue(repo *Repository, issue *Issue, labelIDs []int64, assigneeIDs []in
|
||||||
return fmt.Errorf("Commit: %v", err)
|
return fmt.Errorf("Commit: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateIssueIndexer(issue.ID)
|
|
||||||
|
|
||||||
if err = NotifyWatchers(&Action{
|
|
||||||
ActUserID: issue.Poster.ID,
|
|
||||||
ActUser: issue.Poster,
|
|
||||||
OpType: ActionCreateIssue,
|
|
||||||
Content: fmt.Sprintf("%d|%s", issue.Index, issue.Title),
|
|
||||||
RepoID: repo.ID,
|
|
||||||
Repo: repo,
|
|
||||||
IsPrivate: repo.IsPrivate,
|
|
||||||
}); err != nil {
|
|
||||||
log.Error(4, "NotifyWatchers: %v", err)
|
|
||||||
}
|
|
||||||
if err = issue.MailParticipants(); err != nil {
|
|
||||||
log.Error(4, "MailParticipants: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
mode, _ := AccessLevel(issue.Poster.ID, issue.Repo)
|
|
||||||
if err = PrepareWebhooks(repo, HookEventIssues, &api.IssuePayload{
|
|
||||||
Action: api.HookIssueOpened,
|
|
||||||
Index: issue.Index,
|
|
||||||
Issue: issue.APIFormat(),
|
|
||||||
Repository: repo.APIFormat(mode),
|
|
||||||
Sender: issue.Poster.APIFormat(),
|
|
||||||
}); err != nil {
|
|
||||||
log.Error(4, "PrepareWebhooks: %v", err)
|
|
||||||
} else {
|
|
||||||
go HookQueue.Add(issue.RepoID)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -607,18 +607,6 @@ func CreateIssueComment(doer *User, repo *Repository, issue *Issue, content stri
|
||||||
return nil, fmt.Errorf("CreateComment: %v", err)
|
return nil, fmt.Errorf("CreateComment: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
mode, _ := AccessLevel(doer.ID, repo)
|
|
||||||
if err = PrepareWebhooks(repo, HookEventIssueComment, &api.IssueCommentPayload{
|
|
||||||
Action: api.HookIssueCommentCreated,
|
|
||||||
Issue: issue.APIFormat(),
|
|
||||||
Comment: comment.APIFormat(),
|
|
||||||
Repository: repo.APIFormat(mode),
|
|
||||||
Sender: doer.APIFormat(),
|
|
||||||
}); err != nil {
|
|
||||||
log.Error(2, "PrepareWebhooks [comment_id: %d]: %v", comment.ID, err)
|
|
||||||
} else {
|
|
||||||
go HookQueue.Add(repo.ID)
|
|
||||||
}
|
|
||||||
return comment, nil
|
return comment, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -445,10 +445,6 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository, mergeStyle
|
||||||
log.Error(4, "setMerged [%d]: %v", pr.ID, err)
|
log.Error(4, "setMerged [%d]: %v", pr.ID, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = MergePullRequestAction(doer, pr.Issue.Repo, pr.Issue); err != nil {
|
|
||||||
log.Error(4, "MergePullRequestAction [%d]: %v", pr.ID, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset cached commit count
|
// Reset cached commit count
|
||||||
cache.Remove(pr.Issue.Repo.GetCommitsCountCacheKey(pr.BaseBranch, true))
|
cache.Remove(pr.Issue.Repo.GetCommitsCountCacheKey(pr.BaseBranch, true))
|
||||||
|
|
||||||
|
@ -458,19 +454,6 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository, mergeStyle
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
mode, _ := AccessLevel(doer.ID, pr.Issue.Repo)
|
|
||||||
if err = PrepareWebhooks(pr.Issue.Repo, HookEventPullRequest, &api.PullRequestPayload{
|
|
||||||
Action: api.HookIssueClosed,
|
|
||||||
Index: pr.Index,
|
|
||||||
PullRequest: pr.APIFormat(),
|
|
||||||
Repository: pr.Issue.Repo.APIFormat(mode),
|
|
||||||
Sender: doer.APIFormat(),
|
|
||||||
}); err != nil {
|
|
||||||
log.Error(4, "PrepareWebhooks: %v", err)
|
|
||||||
} else {
|
|
||||||
go HookQueue.Add(pr.Issue.Repo.ID)
|
|
||||||
}
|
|
||||||
|
|
||||||
l, err := baseGitRepo.CommitsBetweenIDs(pr.MergedCommitID, pr.MergeBase)
|
l, err := baseGitRepo.CommitsBetweenIDs(pr.MergedCommitID, pr.MergeBase)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(4, "CommitsBetweenIDs: %v", err)
|
log.Error(4, "CommitsBetweenIDs: %v", err)
|
||||||
|
@ -489,21 +472,6 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository, mergeStyle
|
||||||
l.PushFront(mergeCommit)
|
l.PushFront(mergeCommit)
|
||||||
}
|
}
|
||||||
|
|
||||||
p := &api.PushPayload{
|
|
||||||
Ref: git.BranchPrefix + pr.BaseBranch,
|
|
||||||
Before: pr.MergeBase,
|
|
||||||
After: mergeCommit.ID.String(),
|
|
||||||
CompareURL: setting.AppURL + pr.BaseRepo.ComposeCompareURL(pr.MergeBase, pr.MergedCommitID),
|
|
||||||
Commits: ListToPushCommits(l).ToAPIPayloadCommits(pr.BaseRepo.HTMLURL()),
|
|
||||||
Repo: pr.BaseRepo.APIFormat(mode),
|
|
||||||
Pusher: pr.HeadRepo.MustOwner().APIFormat(),
|
|
||||||
Sender: doer.APIFormat(),
|
|
||||||
}
|
|
||||||
if err = PrepareWebhooks(pr.BaseRepo, HookEventPush, p); err != nil {
|
|
||||||
log.Error(4, "PrepareWebhooks: %v", err)
|
|
||||||
} else {
|
|
||||||
go HookQueue.Add(pr.BaseRepo.ID)
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -769,36 +737,8 @@ func NewPullRequest(repo *Repository, pull *Issue, labelIDs []int64, uuids []str
|
||||||
return fmt.Errorf("Commit: %v", err)
|
return fmt.Errorf("Commit: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateIssueIndexer(pull.ID)
|
|
||||||
|
|
||||||
if err = NotifyWatchers(&Action{
|
|
||||||
ActUserID: pull.Poster.ID,
|
|
||||||
ActUser: pull.Poster,
|
|
||||||
OpType: ActionCreatePullRequest,
|
|
||||||
Content: fmt.Sprintf("%d|%s", pull.Index, pull.Title),
|
|
||||||
RepoID: repo.ID,
|
|
||||||
Repo: repo,
|
|
||||||
IsPrivate: repo.IsPrivate,
|
|
||||||
}); err != nil {
|
|
||||||
log.Error(4, "NotifyWatchers: %v", err)
|
|
||||||
} else if err = pull.MailParticipants(); err != nil {
|
|
||||||
log.Error(4, "MailParticipants: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
pr.Issue = pull
|
pr.Issue = pull
|
||||||
pull.PullRequest = pr
|
pull.PullRequest = pr
|
||||||
mode, _ := AccessLevel(pull.Poster.ID, repo)
|
|
||||||
if err = PrepareWebhooks(repo, HookEventPullRequest, &api.PullRequestPayload{
|
|
||||||
Action: api.HookIssueOpened,
|
|
||||||
Index: pull.Index,
|
|
||||||
PullRequest: pr.APIFormat(),
|
|
||||||
Repository: repo.APIFormat(mode),
|
|
||||||
Sender: pull.Poster.APIFormat(),
|
|
||||||
}); err != nil {
|
|
||||||
log.Error(4, "PrepareWebhooks: %v", err)
|
|
||||||
} else {
|
|
||||||
go HookQueue.Add(repo.ID)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
71
modules/notification/action/action.go
Normal file
71
modules/notification/action/action.go
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
// Copyright 2018 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 action
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"code.gitea.io/git"
|
||||||
|
"code.gitea.io/gitea/models"
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
"code.gitea.io/gitea/modules/notification"
|
||||||
|
)
|
||||||
|
|
||||||
|
type actionReceiver struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
receiver notification.NotifyReceiver = &actionReceiver{}
|
||||||
|
)
|
||||||
|
|
||||||
|
func ini() {
|
||||||
|
notification.RegisterReceiver(receiver)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *actionReceiver) Run() {}
|
||||||
|
|
||||||
|
func (r *actionReceiver) NotifyCreateIssueComment(doer *models.User, repo *models.Repository,
|
||||||
|
issue *models.Issue, comment *models.Comment) {
|
||||||
|
panic("not implementation")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *actionReceiver) NotifyNewIssue(issue *models.Issue) {
|
||||||
|
if err := models.NotifyWatchers(&models.Action{
|
||||||
|
ActUserID: issue.Poster.ID,
|
||||||
|
ActUser: issue.Poster,
|
||||||
|
OpType: models.ActionCreateIssue,
|
||||||
|
Content: fmt.Sprintf("%d|%s", issue.Index, issue.Title),
|
||||||
|
RepoID: issue.Repo.ID,
|
||||||
|
Repo: issue.Repo,
|
||||||
|
IsPrivate: issue.Repo.IsPrivate,
|
||||||
|
}); err != nil {
|
||||||
|
log.Error(4, "NotifyWatchers: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *actionReceiver) NotifyCloseIssue(issue *models.Issue, doer *models.User) {
|
||||||
|
panic("not implementation")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *actionReceiver) NotifyNewPullRequest(pr *models.PullRequest) {
|
||||||
|
issue := pr.Issue
|
||||||
|
if err := models.NotifyWatchers(&models.Action{
|
||||||
|
ActUserID: issue.Poster.ID,
|
||||||
|
ActUser: issue.Poster,
|
||||||
|
OpType: models.ActionCreatePullRequest,
|
||||||
|
Content: fmt.Sprintf("%d|%s", issue.Index, issue.Title),
|
||||||
|
RepoID: issue.Repo.ID,
|
||||||
|
Repo: issue.Repo,
|
||||||
|
IsPrivate: issue.Repo.IsPrivate,
|
||||||
|
}); err != nil {
|
||||||
|
log.Error(4, "NotifyWatchers: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *actionReceiver) NotifyMergePullRequest(pr *models.PullRequest, doer *models.User, baseRepo *git.Repository) {
|
||||||
|
if err := models.MergePullRequestAction(doer, pr.Issue.Repo, pr.Issue); err != nil {
|
||||||
|
log.Error(4, "MergePullRequestAction [%d]: %v", pr.ID, err)
|
||||||
|
}
|
||||||
|
}
|
45
modules/notification/indexer/indexer.go
Normal file
45
modules/notification/indexer/indexer.go
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
// Copyright 2018 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 indexer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"code.gitea.io/git"
|
||||||
|
"code.gitea.io/gitea/models"
|
||||||
|
"code.gitea.io/gitea/modules/notification"
|
||||||
|
)
|
||||||
|
|
||||||
|
type indexerReceiver struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
receiver notification.NotifyReceiver = &indexerReceiver{}
|
||||||
|
)
|
||||||
|
|
||||||
|
func ini() {
|
||||||
|
notification.RegisterReceiver(receiver)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *indexerReceiver) Run() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *indexerReceiver) NotifyCreateIssueComment(doer *models.User, repo *models.Repository,
|
||||||
|
issue *models.Issue, comment *models.Comment) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *indexerReceiver) NotifyNewIssue(issue *models.Issue) {
|
||||||
|
models.UpdateIssueIndexer(issue.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *indexerReceiver) NotifyCloseIssue(issue *models.Issue, doer *models.User) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *indexerReceiver) NotifyNewPullRequest(pr *models.PullRequest) {
|
||||||
|
models.UpdateIssueIndexer(pr.Issue.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *indexerReceiver) NotifyMergePullRequest(pr *models.PullRequest, doer *models.User, baseRepo *git.Repository) {
|
||||||
|
}
|
9
modules/notification/init/init.go
Normal file
9
modules/notification/init/init.go
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
package init
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "code.gitea.io/gitea/modules/notification/action"
|
||||||
|
_ "code.gitea.io/gitea/modules/notification/indexer"
|
||||||
|
_ "code.gitea.io/gitea/modules/notification/mail"
|
||||||
|
_ "code.gitea.io/gitea/modules/notification/ui"
|
||||||
|
_ "code.gitea.io/gitea/modules/notification/webhook"
|
||||||
|
)
|
52
modules/notification/mail/mail.go
Normal file
52
modules/notification/mail/mail.go
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
// Copyright 2018 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 mail
|
||||||
|
|
||||||
|
import (
|
||||||
|
"code.gitea.io/git"
|
||||||
|
"code.gitea.io/gitea/models"
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
"code.gitea.io/gitea/modules/notification"
|
||||||
|
)
|
||||||
|
|
||||||
|
type mailReceiver struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
receiver notification.NotifyReceiver = &mailReceiver{}
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
notification.RegisterReceiver(receiver)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mailReceiver) Run() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mailReceiver) NotifyCreateIssueComment(doer *models.User, repo *models.Repository,
|
||||||
|
issue *models.Issue, comment *models.Comment) {
|
||||||
|
panic("not implementation")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mailReceiver) NotifyNewIssue(issue *models.Issue) {
|
||||||
|
if err := issue.MailParticipants(); err != nil {
|
||||||
|
log.Error(4, "MailParticipants: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mailReceiver) NotifyCloseIssue(issue *models.Issue, doer *models.User) {
|
||||||
|
if err := issue.MailParticipants(); err != nil {
|
||||||
|
log.Error(4, "MailParticipants: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mailReceiver) NotifyNewPullRequest(pr *models.PullRequest) {
|
||||||
|
if err := pr.Issue.MailParticipants(); err != nil {
|
||||||
|
log.Error(4, "MailParticipants: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mailReceiver) NotifyMergePullRequest(pr *models.PullRequest, doer *models.User, baseRepo *git.Repository) {
|
||||||
|
}
|
|
@ -1,50 +1,67 @@
|
||||||
// Copyright 2016 The Gitea Authors. All rights reserved.
|
// Copyright 2018 The Gitea Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a MIT-style
|
// Use of this source code is governed by a MIT-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package notification
|
package notification
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"code.gitea.io/git"
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/modules/log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
// NotifyReceiver defines an interface to notify receiver
|
||||||
notificationService struct {
|
type NotifyReceiver interface {
|
||||||
issueQueue chan issueNotificationOpts
|
Run()
|
||||||
}
|
NotifyCreateIssueComment(*models.User, *models.Repository,
|
||||||
|
*models.Issue, *models.Comment)
|
||||||
issueNotificationOpts struct {
|
NotifyNewIssue(*models.Issue)
|
||||||
issue *models.Issue
|
NotifyCloseIssue(*models.Issue, *models.User)
|
||||||
notificationAuthorID int64
|
NotifyMergePullRequest(*models.PullRequest, *models.User, *git.Repository)
|
||||||
}
|
NotifyNewPullRequest(*models.PullRequest)
|
||||||
)
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// Service is the notification service
|
notifyReceivers []NotifyReceiver
|
||||||
Service = ¬ificationService{
|
|
||||||
issueQueue: make(chan issueNotificationOpts, 100),
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
// RegisterReceiver providers method to receive notify messages
|
||||||
go Service.Run()
|
func RegisterReceiver(receiver NotifyReceiver) {
|
||||||
|
go receiver.Run()
|
||||||
|
notifyReceivers = append(notifyReceivers, receiver)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ns *notificationService) Run() {
|
// NotifyCreateIssueComment notifies issue comment related message to receivers
|
||||||
for {
|
func NotifyCreateIssueComment(doer *models.User, repo *models.Repository,
|
||||||
select {
|
issue *models.Issue, comment *models.Comment) {
|
||||||
case opts := <-ns.issueQueue:
|
for _, receiver := range notifyReceivers {
|
||||||
if err := models.CreateOrUpdateIssueNotifications(opts.issue, opts.notificationAuthorID); err != nil {
|
receiver.NotifyCreateIssueComment(doer, repo, issue, comment)
|
||||||
log.Error(4, "Was unable to create issue notification: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ns *notificationService) NotifyIssue(issue *models.Issue, notificationAuthorID int64) {
|
// NotifyNewIssue notifies new issue to receivers
|
||||||
ns.issueQueue <- issueNotificationOpts{
|
func NotifyNewIssue(issue *models.Issue) {
|
||||||
issue,
|
for _, receiver := range notifyReceivers {
|
||||||
notificationAuthorID,
|
receiver.NotifyNewIssue(issue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotifyCloseIssue notifies close issue to receivers
|
||||||
|
func NotifyCloseIssue(issue *models.Issue, doer *models.User) {
|
||||||
|
for _, receiver := range notifyReceivers {
|
||||||
|
receiver.NotifyCloseIssue(issue, doer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotifyMergePullRequest notifies merge pull request to receivers
|
||||||
|
func NotifyMergePullRequest(pr *models.PullRequest, doer *models.User, baseGitRepo *git.Repository) {
|
||||||
|
for _, receiver := range notifyReceivers {
|
||||||
|
receiver.NotifyMergePullRequest(pr, doer, baseGitRepo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotifyNewPullRequest notifies new pull request to receivers
|
||||||
|
func NotifyNewPullRequest(pr *models.PullRequest) {
|
||||||
|
for _, receiver := range notifyReceivers {
|
||||||
|
receiver.NotifyNewPullRequest(pr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
78
modules/notification/ui/ui.go
Normal file
78
modules/notification/ui/ui.go
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
// Copyright 2018 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 ui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"code.gitea.io/git"
|
||||||
|
"code.gitea.io/gitea/models"
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
"code.gitea.io/gitea/modules/notification"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
notificationService struct {
|
||||||
|
issueQueue chan issueNotificationOpts
|
||||||
|
}
|
||||||
|
|
||||||
|
issueNotificationOpts struct {
|
||||||
|
issue *models.Issue
|
||||||
|
notificationAuthorID int64
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// service is the notification service
|
||||||
|
service = ¬ificationService{
|
||||||
|
issueQueue: make(chan issueNotificationOpts, 100),
|
||||||
|
}
|
||||||
|
_ notification.NotifyReceiver = ¬ificationService{}
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
notification.RegisterReceiver(service)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ns *notificationService) Run() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case opts := <-service.issueQueue:
|
||||||
|
if err := models.CreateOrUpdateIssueNotifications(opts.issue, opts.notificationAuthorID); err != nil {
|
||||||
|
log.Error(4, "Was unable to create issue notification: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *notificationService) NotifyCreateIssueComment(doer *models.User, repo *models.Repository,
|
||||||
|
issue *models.Issue, comment *models.Comment) {
|
||||||
|
service.issueQueue <- issueNotificationOpts{
|
||||||
|
issue,
|
||||||
|
doer.ID,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *notificationService) NotifyNewIssue(issue *models.Issue) {
|
||||||
|
service.issueQueue <- issueNotificationOpts{
|
||||||
|
issue,
|
||||||
|
issue.Poster.ID,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *notificationService) NotifyCloseIssue(issue *models.Issue, doer *models.User) {
|
||||||
|
service.issueQueue <- issueNotificationOpts{
|
||||||
|
issue,
|
||||||
|
doer.ID,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *notificationService) NotifyMergePullRequest(*models.PullRequest, *models.User, *git.Repository) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *notificationService) NotifyNewPullRequest(pr *models.PullRequest) {
|
||||||
|
service.issueQueue <- issueNotificationOpts{
|
||||||
|
pr.Issue,
|
||||||
|
pr.Issue.PosterID,
|
||||||
|
}
|
||||||
|
}
|
127
modules/notification/webhook/webhook.go
Normal file
127
modules/notification/webhook/webhook.go
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
// Copyright 2018 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 webhook
|
||||||
|
|
||||||
|
import (
|
||||||
|
"code.gitea.io/git"
|
||||||
|
"code.gitea.io/gitea/models"
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
"code.gitea.io/gitea/modules/notification"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
|
api "code.gitea.io/sdk/gitea"
|
||||||
|
)
|
||||||
|
|
||||||
|
type webhookReceiver struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
receiver notification.NotifyReceiver = &webhookReceiver{}
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
notification.RegisterReceiver(receiver)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *webhookReceiver) Run() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *webhookReceiver) NotifyCreateIssueComment(doer *models.User, repo *models.Repository,
|
||||||
|
issue *models.Issue, comment *models.Comment) {
|
||||||
|
mode, _ := models.AccessLevel(doer.ID, repo)
|
||||||
|
if err := models.PrepareWebhooks(repo, models.HookEventIssueComment, &api.IssueCommentPayload{
|
||||||
|
Action: api.HookIssueCommentCreated,
|
||||||
|
Issue: issue.APIFormat(),
|
||||||
|
Comment: comment.APIFormat(),
|
||||||
|
Repository: repo.APIFormat(mode),
|
||||||
|
Sender: doer.APIFormat(),
|
||||||
|
}); err != nil {
|
||||||
|
log.Error(2, "PrepareWebhooks [comment_id: %d]: %v", comment.ID, err)
|
||||||
|
} else {
|
||||||
|
go models.HookQueue.Add(repo.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotifyNewIssue implements notification.Receiver
|
||||||
|
func (w *webhookReceiver) NotifyNewIssue(issue *models.Issue) {
|
||||||
|
mode, _ := models.AccessLevel(issue.Poster.ID, issue.Repo)
|
||||||
|
if err := models.PrepareWebhooks(issue.Repo, models.HookEventIssues, &api.IssuePayload{
|
||||||
|
Action: api.HookIssueOpened,
|
||||||
|
Index: issue.Index,
|
||||||
|
Issue: issue.APIFormat(),
|
||||||
|
Repository: issue.Repo.APIFormat(mode),
|
||||||
|
Sender: issue.Poster.APIFormat(),
|
||||||
|
}); err != nil {
|
||||||
|
log.Error(4, "PrepareWebhooks: %v", err)
|
||||||
|
} else {
|
||||||
|
go models.HookQueue.Add(issue.RepoID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotifyCloseIssue implements notification.Receiver
|
||||||
|
func (w *webhookReceiver) NotifyCloseIssue(issue *models.Issue, doer *models.User) {
|
||||||
|
panic("not implements")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *webhookReceiver) NotifyMergePullRequest(pr *models.PullRequest, doer *models.User, baseGitRepo *git.Repository) {
|
||||||
|
mode, _ := models.AccessLevel(doer.ID, pr.Issue.Repo)
|
||||||
|
if err := models.PrepareWebhooks(pr.Issue.Repo, models.HookEventPullRequest, &api.PullRequestPayload{
|
||||||
|
Action: api.HookIssueClosed,
|
||||||
|
Index: pr.Index,
|
||||||
|
PullRequest: pr.APIFormat(),
|
||||||
|
Repository: pr.Issue.Repo.APIFormat(mode),
|
||||||
|
Sender: doer.APIFormat(),
|
||||||
|
}); err != nil {
|
||||||
|
log.Error(4, "PrepareWebhooks: %v", err)
|
||||||
|
} else {
|
||||||
|
go models.HookQueue.Add(pr.Issue.Repo.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
l, err := baseGitRepo.CommitsBetweenIDs(pr.MergedCommitID, pr.MergeBase)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(4, "CommitsBetweenIDs: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// It is possible that head branch is not fully sync with base branch for merge commits,
|
||||||
|
// so we need to get latest head commit and append merge commit manually
|
||||||
|
// to avoid strange diff commits produced.
|
||||||
|
mergeCommit, err := baseGitRepo.GetBranchCommit(pr.BaseBranch)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(4, "GetBranchCommit: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
p := &api.PushPayload{
|
||||||
|
Ref: git.BranchPrefix + pr.BaseBranch,
|
||||||
|
Before: pr.MergeBase,
|
||||||
|
After: mergeCommit.ID.String(),
|
||||||
|
CompareURL: setting.AppURL + pr.BaseRepo.ComposeCompareURL(pr.MergeBase, pr.MergedCommitID),
|
||||||
|
Commits: models.ListToPushCommits(l).ToAPIPayloadCommits(pr.BaseRepo.HTMLURL()),
|
||||||
|
Repo: pr.BaseRepo.APIFormat(mode),
|
||||||
|
Pusher: pr.HeadRepo.MustOwner().APIFormat(),
|
||||||
|
Sender: doer.APIFormat(),
|
||||||
|
}
|
||||||
|
if err := models.PrepareWebhooks(pr.BaseRepo, models.HookEventPush, p); err != nil {
|
||||||
|
log.Error(4, "PrepareWebhooks: %v", err)
|
||||||
|
} else {
|
||||||
|
go models.HookQueue.Add(pr.BaseRepo.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *webhookReceiver) NotifyNewPullRequest(pr *models.PullRequest) {
|
||||||
|
mode, _ := models.AccessLevel(pr.Issue.Poster.ID, pr.Issue.Repo)
|
||||||
|
if err := models.PrepareWebhooks(pr.Issue.Repo, models.HookEventPullRequest, &api.PullRequestPayload{
|
||||||
|
Action: api.HookIssueOpened,
|
||||||
|
Index: pr.Issue.Index,
|
||||||
|
PullRequest: pr.APIFormat(),
|
||||||
|
Repository: pr.Issue.Repo.APIFormat(mode),
|
||||||
|
Sender: pr.Issue.Poster.APIFormat(),
|
||||||
|
}); err != nil {
|
||||||
|
log.Error(4, "PrepareWebhooks: %v", err)
|
||||||
|
} else {
|
||||||
|
go models.HookQueue.Add(pr.Issue.Repo.ID)
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/indexer"
|
"code.gitea.io/gitea/modules/indexer"
|
||||||
|
"code.gitea.io/gitea/modules/notification"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
|
@ -206,6 +207,8 @@ func CreateIssue(ctx *context.APIContext, form api.CreateIssueOption) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
notification.NotifyNewIssue(issue)
|
||||||
|
|
||||||
if form.Closed {
|
if form.Closed {
|
||||||
if err := issue.ChangeStatus(ctx.User, ctx.Repo.Repository, true); err != nil {
|
if err := issue.ChangeStatus(ctx.User, ctx.Repo.Repository, true); err != nil {
|
||||||
ctx.Error(500, "ChangeStatus", err)
|
ctx.Error(500, "ChangeStatus", err)
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
|
"code.gitea.io/gitea/modules/notification"
|
||||||
|
|
||||||
api "code.gitea.io/sdk/gitea"
|
api "code.gitea.io/sdk/gitea"
|
||||||
)
|
)
|
||||||
|
@ -163,6 +164,8 @@ func CreateIssueComment(ctx *context.APIContext, form api.CreateIssueCommentOpti
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
notification.NotifyCreateIssueComment(ctx.User, ctx.Repo.Repository, issue, comment)
|
||||||
|
|
||||||
ctx.JSON(201, comment.APIFormat())
|
ctx.JSON(201, comment.APIFormat())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/notification"
|
||||||
|
|
||||||
"code.gitea.io/git"
|
"code.gitea.io/git"
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/modules/auth"
|
"code.gitea.io/gitea/modules/auth"
|
||||||
|
@ -538,6 +540,8 @@ func MergePullRequest(ctx *context.APIContext, form auth.MergePullRequestForm) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
notification.NotifyMergePullRequest(pr, ctx.User, ctx.Repo.GitRepo)
|
||||||
|
|
||||||
log.Trace("Pull request merged: %d", pr.ID)
|
log.Trace("Pull request merged: %d", pr.ID)
|
||||||
ctx.Status(200)
|
ctx.Status(200)
|
||||||
}
|
}
|
||||||
|
|
|
@ -484,7 +484,7 @@ func NewIssuePost(ctx *context.Context, form auth.CreateIssueForm) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
notification.Service.NotifyIssue(issue, ctx.User.ID)
|
notification.NotifyNewIssue(issue)
|
||||||
|
|
||||||
log.Trace("Issue created: %d/%d", repo.ID, issue.ID)
|
log.Trace("Issue created: %d/%d", repo.ID, issue.ID)
|
||||||
ctx.Redirect(ctx.Repo.RepoLink + "/issues/" + com.ToStr(issue.Index))
|
ctx.Redirect(ctx.Repo.RepoLink + "/issues/" + com.ToStr(issue.Index))
|
||||||
|
@ -1037,7 +1037,7 @@ func NewComment(ctx *context.Context, form auth.CreateCommentForm) {
|
||||||
} else {
|
} else {
|
||||||
log.Trace("Issue [%d] status changed to closed: %v", issue.ID, issue.IsClosed)
|
log.Trace("Issue [%d] status changed to closed: %v", issue.ID, issue.IsClosed)
|
||||||
|
|
||||||
notification.Service.NotifyIssue(issue, ctx.User.ID)
|
notification.NotifyCloseIssue(issue, ctx.User)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1065,7 +1065,7 @@ func NewComment(ctx *context.Context, form auth.CreateCommentForm) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
notification.Service.NotifyIssue(issue, ctx.User.ID)
|
notification.NotifyCreateIssueComment(ctx.User, ctx.Repo.Repository, issue, comment)
|
||||||
|
|
||||||
log.Trace("Comment created: %d/%d/%d", ctx.Repo.Repository.ID, issue.ID, comment.ID)
|
log.Trace("Comment created: %d/%d/%d", ctx.Repo.Repository.ID, issue.ID, comment.ID)
|
||||||
}
|
}
|
||||||
|
|
|
@ -534,7 +534,7 @@ func MergePullRequest(ctx *context.Context, form auth.MergePullRequestForm) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
notification.Service.NotifyIssue(pr.Issue, ctx.User.ID)
|
notification.NotifyMergePullRequest(pr, ctx.User, ctx.Repo.GitRepo)
|
||||||
|
|
||||||
log.Trace("Pull request merged: %d", pr.ID)
|
log.Trace("Pull request merged: %d", pr.ID)
|
||||||
ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + com.ToStr(pr.Index))
|
ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + com.ToStr(pr.Index))
|
||||||
|
@ -824,6 +824,7 @@ func CompareAndPullRequestPost(ctx *context.Context, form auth.CreateIssueForm)
|
||||||
BaseRepo: repo,
|
BaseRepo: repo,
|
||||||
MergeBase: prInfo.MergeBase,
|
MergeBase: prInfo.MergeBase,
|
||||||
Type: models.PullRequestGitea,
|
Type: models.PullRequestGitea,
|
||||||
|
Issue: pullIssue,
|
||||||
}
|
}
|
||||||
// FIXME: check error in the case two people send pull request at almost same time, give nice error prompt
|
// FIXME: check error in the case two people send pull request at almost same time, give nice error prompt
|
||||||
// instead of 500.
|
// instead of 500.
|
||||||
|
@ -840,7 +841,7 @@ func CompareAndPullRequestPost(ctx *context.Context, form auth.CreateIssueForm)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
notification.Service.NotifyIssue(pullIssue, ctx.User.ID)
|
notification.NotifyNewPullRequest(pullRequest)
|
||||||
|
|
||||||
log.Trace("Pull request created: %d/%d", repo.ID, pullIssue.ID)
|
log.Trace("Pull request created: %d/%d", repo.ID, pullIssue.ID)
|
||||||
ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + com.ToStr(pullIssue.Index))
|
ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + com.ToStr(pullIssue.Index))
|
||||||
|
|
Loading…
Reference in New Issue
Block a user