Add more webhooks support and refactor webhook templates directory (#3929)
* add more webhook support * move hooks templates to standalone dir and add more webhooks ui * fix tests * update vendor checksum * add more webhook support * move hooks templates to standalone dir and add more webhooks ui * fix tests * update vendor checksum * update vendor Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com> * load attributes when created release * update comparsion doc
This commit is contained in:
parent
188fe6c301
commit
24941a1046
|
@ -537,7 +537,7 @@ _Symbols used in table:_
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Webhook support</td>
|
<td>Webhook support</td>
|
||||||
<td>⁄</td>
|
<td>✓</td>
|
||||||
<td>✓</td>
|
<td>✓</td>
|
||||||
<td>✓</td>
|
<td>✓</td>
|
||||||
<td>✓</td>
|
<td>✓</td>
|
||||||
|
|
|
@ -618,6 +618,16 @@ func CommitRepoAction(opts CommitRepoActionOptions) error {
|
||||||
case ActionDeleteBranch: // Delete Branch
|
case ActionDeleteBranch: // Delete Branch
|
||||||
isHookEventPush = true
|
isHookEventPush = true
|
||||||
|
|
||||||
|
if err = PrepareWebhooks(repo, HookEventDelete, &api.DeletePayload{
|
||||||
|
Ref: refName,
|
||||||
|
RefType: "branch",
|
||||||
|
PusherType: api.PusherTypeUser,
|
||||||
|
Repo: apiRepo,
|
||||||
|
Sender: apiPusher,
|
||||||
|
}); err != nil {
|
||||||
|
return fmt.Errorf("PrepareWebhooks.(delete branch): %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
case ActionPushTag: // Create
|
case ActionPushTag: // Create
|
||||||
isHookEventPush = true
|
isHookEventPush = true
|
||||||
|
|
||||||
|
@ -640,6 +650,16 @@ func CommitRepoAction(opts CommitRepoActionOptions) error {
|
||||||
}
|
}
|
||||||
case ActionDeleteTag: // Delete Tag
|
case ActionDeleteTag: // Delete Tag
|
||||||
isHookEventPush = true
|
isHookEventPush = true
|
||||||
|
|
||||||
|
if err = PrepareWebhooks(repo, HookEventDelete, &api.DeletePayload{
|
||||||
|
Ref: refName,
|
||||||
|
RefType: "tag",
|
||||||
|
PusherType: api.PusherTypeUser,
|
||||||
|
Repo: apiRepo,
|
||||||
|
Sender: apiPusher,
|
||||||
|
}); err != nil {
|
||||||
|
return fmt.Errorf("PrepareWebhooks.(delete tag): %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if isHookEventPush {
|
if isHookEventPush {
|
||||||
|
|
|
@ -86,6 +86,7 @@ type Comment struct {
|
||||||
PosterID int64 `xorm:"INDEX"`
|
PosterID int64 `xorm:"INDEX"`
|
||||||
Poster *User `xorm:"-"`
|
Poster *User `xorm:"-"`
|
||||||
IssueID int64 `xorm:"INDEX"`
|
IssueID int64 `xorm:"INDEX"`
|
||||||
|
Issue *Issue `xorm:"-"`
|
||||||
LabelID int64
|
LabelID int64
|
||||||
Label *Label `xorm:"-"`
|
Label *Label `xorm:"-"`
|
||||||
OldMilestoneID int64
|
OldMilestoneID int64
|
||||||
|
@ -116,6 +117,15 @@ type Comment struct {
|
||||||
ShowTag CommentTag `xorm:"-"`
|
ShowTag CommentTag `xorm:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoadIssue loads issue from database
|
||||||
|
func (c *Comment) LoadIssue() (err error) {
|
||||||
|
if c.Issue != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
c.Issue, err = GetIssueByID(c.IssueID)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// AfterLoad is invoked from XORM after setting the values of all fields of this object.
|
// AfterLoad is invoked from XORM after setting the values of all fields of this object.
|
||||||
func (c *Comment) AfterLoad(session *xorm.Session) {
|
func (c *Comment) AfterLoad(session *xorm.Session) {
|
||||||
var err error
|
var err error
|
||||||
|
@ -146,40 +156,40 @@ func (c *Comment) AfterDelete() {
|
||||||
|
|
||||||
// HTMLURL formats a URL-string to the issue-comment
|
// HTMLURL formats a URL-string to the issue-comment
|
||||||
func (c *Comment) HTMLURL() string {
|
func (c *Comment) HTMLURL() string {
|
||||||
issue, err := GetIssueByID(c.IssueID)
|
err := c.LoadIssue()
|
||||||
if err != nil { // Silently dropping errors :unamused:
|
if err != nil { // Silently dropping errors :unamused:
|
||||||
log.Error(4, "GetIssueByID(%d): %v", c.IssueID, err)
|
log.Error(4, "LoadIssue(%d): %v", c.IssueID, err)
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%s#%s", issue.HTMLURL(), c.HashTag())
|
return fmt.Sprintf("%s#%s", c.Issue.HTMLURL(), c.HashTag())
|
||||||
}
|
}
|
||||||
|
|
||||||
// IssueURL formats a URL-string to the issue
|
// IssueURL formats a URL-string to the issue
|
||||||
func (c *Comment) IssueURL() string {
|
func (c *Comment) IssueURL() string {
|
||||||
issue, err := GetIssueByID(c.IssueID)
|
err := c.LoadIssue()
|
||||||
if err != nil { // Silently dropping errors :unamused:
|
if err != nil { // Silently dropping errors :unamused:
|
||||||
log.Error(4, "GetIssueByID(%d): %v", c.IssueID, err)
|
log.Error(4, "LoadIssue(%d): %v", c.IssueID, err)
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
if issue.IsPull {
|
if c.Issue.IsPull {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return issue.HTMLURL()
|
return c.Issue.HTMLURL()
|
||||||
}
|
}
|
||||||
|
|
||||||
// PRURL formats a URL-string to the pull-request
|
// PRURL formats a URL-string to the pull-request
|
||||||
func (c *Comment) PRURL() string {
|
func (c *Comment) PRURL() string {
|
||||||
issue, err := GetIssueByID(c.IssueID)
|
err := c.LoadIssue()
|
||||||
if err != nil { // Silently dropping errors :unamused:
|
if err != nil { // Silently dropping errors :unamused:
|
||||||
log.Error(4, "GetIssueByID(%d): %v", c.IssueID, err)
|
log.Error(4, "LoadIssue(%d): %v", c.IssueID, err)
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
if !issue.IsPull {
|
if !c.Issue.IsPull {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return issue.HTMLURL()
|
return c.Issue.HTMLURL()
|
||||||
}
|
}
|
||||||
|
|
||||||
// APIFormat converts a Comment to the api.Comment format
|
// APIFormat converts a Comment to the api.Comment format
|
||||||
|
@ -196,9 +206,14 @@ func (c *Comment) APIFormat() *api.Comment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CommentHashTag returns unique hash tag for comment id.
|
||||||
|
func CommentHashTag(id int64) string {
|
||||||
|
return fmt.Sprintf("issuecomment-%d", id)
|
||||||
|
}
|
||||||
|
|
||||||
// HashTag returns unique hash tag for comment.
|
// HashTag returns unique hash tag for comment.
|
||||||
func (c *Comment) HashTag() string {
|
func (c *Comment) HashTag() string {
|
||||||
return "issuecomment-" + com.ToStr(c.ID)
|
return CommentHashTag(c.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// EventTag returns unique event hash tag for comment.
|
// EventTag returns unique event hash tag for comment.
|
||||||
|
@ -576,7 +591,7 @@ func CreateComment(opts *CreateCommentOptions) (comment *Comment, err error) {
|
||||||
|
|
||||||
// CreateIssueComment creates a plain issue comment.
|
// CreateIssueComment creates a plain issue comment.
|
||||||
func CreateIssueComment(doer *User, repo *Repository, issue *Issue, content string, attachments []string) (*Comment, error) {
|
func CreateIssueComment(doer *User, repo *Repository, issue *Issue, content string, attachments []string) (*Comment, error) {
|
||||||
return CreateComment(&CreateCommentOptions{
|
comment, err := CreateComment(&CreateCommentOptions{
|
||||||
Type: CommentTypeComment,
|
Type: CommentTypeComment,
|
||||||
Doer: doer,
|
Doer: doer,
|
||||||
Repo: repo,
|
Repo: repo,
|
||||||
|
@ -584,6 +599,21 @@ func CreateIssueComment(doer *User, repo *Repository, issue *Issue, content stri
|
||||||
Content: content,
|
Content: content,
|
||||||
Attachments: attachments,
|
Attachments: attachments,
|
||||||
})
|
})
|
||||||
|
if err != nil {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
return comment, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateRefComment creates a commit reference comment to issue.
|
// CreateRefComment creates a commit reference comment to issue.
|
||||||
|
@ -696,17 +726,41 @@ func GetCommentsByRepoIDSince(repoID, since int64) ([]*Comment, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateComment updates information of comment.
|
// UpdateComment updates information of comment.
|
||||||
func UpdateComment(c *Comment) error {
|
func UpdateComment(doer *User, c *Comment, oldContent string) error {
|
||||||
if _, err := x.ID(c.ID).AllCols().Update(c); err != nil {
|
if _, err := x.ID(c.ID).AllCols().Update(c); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if c.Type == CommentTypeComment {
|
} else if c.Type == CommentTypeComment {
|
||||||
UpdateIssueIndexer(c.IssueID)
|
UpdateIssueIndexer(c.IssueID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := c.LoadIssue(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := c.Issue.LoadAttributes(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
mode, _ := AccessLevel(doer.ID, c.Issue.Repo)
|
||||||
|
if err := PrepareWebhooks(c.Issue.Repo, HookEventIssueComment, &api.IssueCommentPayload{
|
||||||
|
Action: api.HookIssueCommentEdited,
|
||||||
|
Issue: c.Issue.APIFormat(),
|
||||||
|
Comment: c.APIFormat(),
|
||||||
|
Changes: &api.ChangesPayload{
|
||||||
|
Body: &api.ChangesFromPayload{
|
||||||
|
From: oldContent,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Repository: c.Issue.Repo.APIFormat(mode),
|
||||||
|
Sender: doer.APIFormat(),
|
||||||
|
}); err != nil {
|
||||||
|
log.Error(2, "PrepareWebhooks [comment_id: %d]: %v", c.ID, err)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteComment deletes the comment
|
// DeleteComment deletes the comment
|
||||||
func DeleteComment(comment *Comment) error {
|
func DeleteComment(doer *User, comment *Comment) error {
|
||||||
sess := x.NewSession()
|
sess := x.NewSession()
|
||||||
defer sess.Close()
|
defer sess.Close()
|
||||||
if err := sess.Begin(); err != nil {
|
if err := sess.Begin(); err != nil {
|
||||||
|
@ -733,5 +787,25 @@ func DeleteComment(comment *Comment) error {
|
||||||
} else if comment.Type == CommentTypeComment {
|
} else if comment.Type == CommentTypeComment {
|
||||||
UpdateIssueIndexer(comment.IssueID)
|
UpdateIssueIndexer(comment.IssueID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := comment.LoadIssue(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := comment.Issue.LoadAttributes(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
mode, _ := AccessLevel(doer.ID, comment.Issue.Repo)
|
||||||
|
|
||||||
|
if err := PrepareWebhooks(comment.Issue.Repo, HookEventIssueComment, &api.IssueCommentPayload{
|
||||||
|
Action: api.HookIssueCommentDeleted,
|
||||||
|
Issue: comment.Issue.APIFormat(),
|
||||||
|
Comment: comment.APIFormat(),
|
||||||
|
Repository: comment.Issue.Repo.APIFormat(mode),
|
||||||
|
Sender: doer.APIFormat(),
|
||||||
|
}); err != nil {
|
||||||
|
log.Error(2, "PrepareWebhooks [comment_id: %d]: %v", comment.ID, err)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,9 @@
|
||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
api "code.gitea.io/sdk/gitea"
|
api "code.gitea.io/sdk/gitea"
|
||||||
|
@ -358,7 +361,49 @@ func ChangeMilestoneAssign(issue *Issue, doer *User, oldMilestoneID int64) (err
|
||||||
if err = changeMilestoneAssign(sess, doer, issue, oldMilestoneID); err != nil {
|
if err = changeMilestoneAssign(sess, doer, issue, oldMilestoneID); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return sess.Commit()
|
|
||||||
|
if err = sess.Commit(); err != nil {
|
||||||
|
return fmt.Errorf("Commit: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var hookAction api.HookIssueAction
|
||||||
|
if issue.MilestoneID > 0 {
|
||||||
|
hookAction = api.HookIssueMilestoned
|
||||||
|
} else {
|
||||||
|
hookAction = api.HookIssueDemilestoned
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = issue.LoadAttributes(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
mode, _ := AccessLevel(doer.ID, issue.Repo)
|
||||||
|
if issue.IsPull {
|
||||||
|
err = issue.PullRequest.LoadIssue()
|
||||||
|
if err != nil {
|
||||||
|
log.Error(2, "LoadIssue: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = PrepareWebhooks(issue.Repo, HookEventPullRequest, &api.PullRequestPayload{
|
||||||
|
Action: hookAction,
|
||||||
|
Index: issue.Index,
|
||||||
|
PullRequest: issue.PullRequest.APIFormat(),
|
||||||
|
Repository: issue.Repo.APIFormat(mode),
|
||||||
|
Sender: doer.APIFormat(),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
err = PrepareWebhooks(issue.Repo, HookEventIssues, &api.IssuePayload{
|
||||||
|
Action: hookAction,
|
||||||
|
Index: issue.Index,
|
||||||
|
Issue: issue.APIFormat(),
|
||||||
|
Repository: issue.Repo.APIFormat(mode),
|
||||||
|
Sender: doer.APIFormat(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Error(2, "PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteMilestoneByRepoID deletes a milestone from a repository.
|
// DeleteMilestoneByRepoID deletes a milestone from a repository.
|
||||||
|
|
|
@ -232,6 +232,8 @@ func TestChangeMilestoneAssign(t *testing.T) {
|
||||||
assert.NoError(t, PrepareTestDatabase())
|
assert.NoError(t, PrepareTestDatabase())
|
||||||
issue := AssertExistsAndLoadBean(t, &Issue{RepoID: 1}).(*Issue)
|
issue := AssertExistsAndLoadBean(t, &Issue{RepoID: 1}).(*Issue)
|
||||||
doer := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
|
doer := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
|
||||||
|
assert.NotNil(t, issue)
|
||||||
|
assert.NotNil(t, doer)
|
||||||
|
|
||||||
oldMilestoneID := issue.MilestoneID
|
oldMilestoneID := issue.MilestoneID
|
||||||
issue.MilestoneID = 2
|
issue.MilestoneID = 2
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/git"
|
"code.gitea.io/git"
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/process"
|
"code.gitea.io/gitea/modules/process"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
@ -190,10 +191,29 @@ func CreateRelease(gitRepo *git.Repository, rel *Release, attachmentUUIDs []stri
|
||||||
}
|
}
|
||||||
|
|
||||||
err = addReleaseAttachments(rel.ID, attachmentUUIDs)
|
err = addReleaseAttachments(rel.ID, attachmentUUIDs)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !rel.IsDraft {
|
||||||
|
if err := rel.LoadAttributes(); err != nil {
|
||||||
|
log.Error(2, "LoadAttributes: %v", err)
|
||||||
|
} else {
|
||||||
|
mode, _ := AccessLevel(rel.PublisherID, rel.Repo)
|
||||||
|
if err := PrepareWebhooks(rel.Repo, HookEventRelease, &api.ReleasePayload{
|
||||||
|
Action: api.HookReleasePublished,
|
||||||
|
Release: rel.APIFormat(),
|
||||||
|
Repository: rel.Repo.APIFormat(mode),
|
||||||
|
Sender: rel.Publisher.APIFormat(),
|
||||||
|
}); err != nil {
|
||||||
|
log.Error(2, "PrepareWebhooks: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetRelease returns release by given ID.
|
// GetRelease returns release by given ID.
|
||||||
func GetRelease(repoID int64, tagName string) (*Release, error) {
|
func GetRelease(repoID int64, tagName string) (*Release, error) {
|
||||||
isExist, err := IsReleaseExist(repoID, tagName)
|
isExist, err := IsReleaseExist(repoID, tagName)
|
||||||
|
|
|
@ -2456,6 +2456,17 @@ func ForkRepository(doer, u *User, oldRepo *Repository, name, desc string) (_ *R
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
oldMode, _ := AccessLevel(doer.ID, oldRepo)
|
||||||
|
mode, _ := AccessLevel(doer.ID, repo)
|
||||||
|
|
||||||
|
if err = PrepareWebhooks(oldRepo, HookEventFork, &api.ForkPayload{
|
||||||
|
Forkee: repo.APIFormat(mode),
|
||||||
|
Repo: oldRepo.APIFormat(oldMode),
|
||||||
|
Sender: doer.APIFormat(),
|
||||||
|
}); err != nil {
|
||||||
|
log.Error(2, "PrepareWebhooks [repo_id: %d]: %v", oldRepo.ID, err)
|
||||||
|
}
|
||||||
|
|
||||||
if err = repo.UpdateSize(); err != nil {
|
if err = repo.UpdateSize(); err != nil {
|
||||||
log.Error(4, "Failed to update size for repository: %v", err)
|
log.Error(4, "Failed to update size for repository: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,9 +67,14 @@ func IsValidHookContentType(name string) bool {
|
||||||
// HookEvents is a set of web hook events
|
// HookEvents is a set of web hook events
|
||||||
type HookEvents struct {
|
type HookEvents struct {
|
||||||
Create bool `json:"create"`
|
Create bool `json:"create"`
|
||||||
|
Delete bool `json:"delete"`
|
||||||
|
Fork bool `json:"fork"`
|
||||||
|
Issues bool `json:"issues"`
|
||||||
|
IssueComment bool `json:"issue_comment"`
|
||||||
Push bool `json:"push"`
|
Push bool `json:"push"`
|
||||||
PullRequest bool `json:"pull_request"`
|
PullRequest bool `json:"pull_request"`
|
||||||
Repository bool `json:"repository"`
|
Repository bool `json:"repository"`
|
||||||
|
Release bool `json:"release"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// HookEvent represents events that will delivery hook.
|
// HookEvent represents events that will delivery hook.
|
||||||
|
@ -155,6 +160,30 @@ func (w *Webhook) HasCreateEvent() bool {
|
||||||
(w.ChooseEvents && w.HookEvents.Create)
|
(w.ChooseEvents && w.HookEvents.Create)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HasDeleteEvent returns true if hook enabled delete event.
|
||||||
|
func (w *Webhook) HasDeleteEvent() bool {
|
||||||
|
return w.SendEverything ||
|
||||||
|
(w.ChooseEvents && w.HookEvents.Delete)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasForkEvent returns true if hook enabled fork event.
|
||||||
|
func (w *Webhook) HasForkEvent() bool {
|
||||||
|
return w.SendEverything ||
|
||||||
|
(w.ChooseEvents && w.HookEvents.Fork)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasIssuesEvent returns true if hook enabled issues event.
|
||||||
|
func (w *Webhook) HasIssuesEvent() bool {
|
||||||
|
return w.SendEverything ||
|
||||||
|
(w.ChooseEvents && w.HookEvents.Issues)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasIssueCommentEvent returns true if hook enabled issue_comment event.
|
||||||
|
func (w *Webhook) HasIssueCommentEvent() bool {
|
||||||
|
return w.SendEverything ||
|
||||||
|
(w.ChooseEvents && w.HookEvents.IssueComment)
|
||||||
|
}
|
||||||
|
|
||||||
// HasPushEvent returns true if hook enabled push event.
|
// HasPushEvent returns true if hook enabled push event.
|
||||||
func (w *Webhook) HasPushEvent() bool {
|
func (w *Webhook) HasPushEvent() bool {
|
||||||
return w.PushOnly || w.SendEverything ||
|
return w.PushOnly || w.SendEverything ||
|
||||||
|
@ -167,23 +196,46 @@ func (w *Webhook) HasPullRequestEvent() bool {
|
||||||
(w.ChooseEvents && w.HookEvents.PullRequest)
|
(w.ChooseEvents && w.HookEvents.PullRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HasReleaseEvent returns if hook enabled release event.
|
||||||
|
func (w *Webhook) HasReleaseEvent() bool {
|
||||||
|
return w.SendEverything ||
|
||||||
|
(w.ChooseEvents && w.HookEvents.Release)
|
||||||
|
}
|
||||||
|
|
||||||
// HasRepositoryEvent returns if hook enabled repository event.
|
// HasRepositoryEvent returns if hook enabled repository event.
|
||||||
func (w *Webhook) HasRepositoryEvent() bool {
|
func (w *Webhook) HasRepositoryEvent() bool {
|
||||||
return w.SendEverything ||
|
return w.SendEverything ||
|
||||||
(w.ChooseEvents && w.HookEvents.Repository)
|
(w.ChooseEvents && w.HookEvents.Repository)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *Webhook) eventCheckers() []struct {
|
||||||
|
has func() bool
|
||||||
|
typ HookEventType
|
||||||
|
} {
|
||||||
|
return []struct {
|
||||||
|
has func() bool
|
||||||
|
typ HookEventType
|
||||||
|
}{
|
||||||
|
{w.HasCreateEvent, HookEventCreate},
|
||||||
|
{w.HasDeleteEvent, HookEventDelete},
|
||||||
|
{w.HasForkEvent, HookEventFork},
|
||||||
|
{w.HasPushEvent, HookEventPush},
|
||||||
|
{w.HasIssuesEvent, HookEventIssues},
|
||||||
|
{w.HasIssueCommentEvent, HookEventIssueComment},
|
||||||
|
{w.HasPullRequestEvent, HookEventPullRequest},
|
||||||
|
{w.HasRepositoryEvent, HookEventRepository},
|
||||||
|
{w.HasReleaseEvent, HookEventRelease},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// EventsArray returns an array of hook events
|
// EventsArray returns an array of hook events
|
||||||
func (w *Webhook) EventsArray() []string {
|
func (w *Webhook) EventsArray() []string {
|
||||||
events := make([]string, 0, 3)
|
events := make([]string, 0, 7)
|
||||||
if w.HasCreateEvent() {
|
|
||||||
events = append(events, "create")
|
for _, c := range w.eventCheckers() {
|
||||||
|
if c.has() {
|
||||||
|
events = append(events, string(c.typ))
|
||||||
}
|
}
|
||||||
if w.HasPushEvent() {
|
|
||||||
events = append(events, "push")
|
|
||||||
}
|
|
||||||
if w.HasPullRequestEvent() {
|
|
||||||
events = append(events, "pull_request")
|
|
||||||
}
|
}
|
||||||
return events
|
return events
|
||||||
}
|
}
|
||||||
|
@ -374,9 +426,14 @@ type HookEventType string
|
||||||
// Types of hook events
|
// Types of hook events
|
||||||
const (
|
const (
|
||||||
HookEventCreate HookEventType = "create"
|
HookEventCreate HookEventType = "create"
|
||||||
|
HookEventDelete HookEventType = "delete"
|
||||||
|
HookEventFork HookEventType = "fork"
|
||||||
HookEventPush HookEventType = "push"
|
HookEventPush HookEventType = "push"
|
||||||
|
HookEventIssues HookEventType = "issues"
|
||||||
|
HookEventIssueComment HookEventType = "issue_comment"
|
||||||
HookEventPullRequest HookEventType = "pull_request"
|
HookEventPullRequest HookEventType = "pull_request"
|
||||||
HookEventRepository HookEventType = "repository"
|
HookEventRepository HookEventType = "repository"
|
||||||
|
HookEventRelease HookEventType = "release"
|
||||||
)
|
)
|
||||||
|
|
||||||
// HookRequest represents hook task request information.
|
// HookRequest represents hook task request information.
|
||||||
|
@ -488,22 +545,11 @@ func PrepareWebhook(w *Webhook, repo *Repository, event HookEventType, p api.Pay
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareWebhook(e Engine, w *Webhook, repo *Repository, event HookEventType, p api.Payloader) error {
|
func prepareWebhook(e Engine, w *Webhook, repo *Repository, event HookEventType, p api.Payloader) error {
|
||||||
switch event {
|
for _, e := range w.eventCheckers() {
|
||||||
case HookEventCreate:
|
if event == e.typ {
|
||||||
if !w.HasCreateEvent() {
|
if !e.has() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
case HookEventPush:
|
|
||||||
if !w.HasPushEvent() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
case HookEventPullRequest:
|
|
||||||
if !w.HasPullRequestEvent() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
case HookEventRepository:
|
|
||||||
if !w.HasRepositoryEvent() {
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,38 @@ func getDingtalkCreatePayload(p *api.CreatePayload) (*DingtalkPayload, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getDingtalkDeletePayload(p *api.DeletePayload) (*DingtalkPayload, error) {
|
||||||
|
// created tag/branch
|
||||||
|
refName := git.RefEndName(p.Ref)
|
||||||
|
title := fmt.Sprintf("[%s] %s %s deleted", p.Repo.FullName, p.RefType, refName)
|
||||||
|
|
||||||
|
return &DingtalkPayload{
|
||||||
|
MsgType: "actionCard",
|
||||||
|
ActionCard: dingtalk.ActionCard{
|
||||||
|
Text: title,
|
||||||
|
Title: title,
|
||||||
|
HideAvatar: "0",
|
||||||
|
SingleTitle: fmt.Sprintf("view branch %s", refName),
|
||||||
|
SingleURL: p.Repo.HTMLURL + "/src/" + refName,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getDingtalkForkPayload(p *api.ForkPayload) (*DingtalkPayload, error) {
|
||||||
|
title := fmt.Sprintf("%s is forked to %s", p.Forkee.FullName, p.Repo.FullName)
|
||||||
|
|
||||||
|
return &DingtalkPayload{
|
||||||
|
MsgType: "actionCard",
|
||||||
|
ActionCard: dingtalk.ActionCard{
|
||||||
|
Text: title,
|
||||||
|
Title: title,
|
||||||
|
HideAvatar: "0",
|
||||||
|
SingleTitle: fmt.Sprintf("view forked repo %s", p.Repo.FullName),
|
||||||
|
SingleURL: p.Repo.HTMLURL,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func getDingtalkPushPayload(p *api.PushPayload) (*DingtalkPayload, error) {
|
func getDingtalkPushPayload(p *api.PushPayload) (*DingtalkPayload, error) {
|
||||||
var (
|
var (
|
||||||
branchName = git.RefEndName(p.Ref)
|
branchName = git.RefEndName(p.Ref)
|
||||||
|
@ -98,6 +130,80 @@ func getDingtalkPushPayload(p *api.PushPayload) (*DingtalkPayload, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getDingtalkIssuesPayload(p *api.IssuePayload) (*DingtalkPayload, error) {
|
||||||
|
var text, title string
|
||||||
|
switch p.Action {
|
||||||
|
case api.HookIssueOpened:
|
||||||
|
title = fmt.Sprintf("[%s] Issue opened: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
|
||||||
|
text = p.Issue.Body
|
||||||
|
case api.HookIssueClosed:
|
||||||
|
title = fmt.Sprintf("[%s] Issue closed: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
|
||||||
|
text = p.Issue.Body
|
||||||
|
case api.HookIssueReOpened:
|
||||||
|
title = fmt.Sprintf("[%s] Issue re-opened: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
|
||||||
|
text = p.Issue.Body
|
||||||
|
case api.HookIssueEdited:
|
||||||
|
title = fmt.Sprintf("[%s] Issue edited: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
|
||||||
|
text = p.Issue.Body
|
||||||
|
case api.HookIssueAssigned:
|
||||||
|
title = fmt.Sprintf("[%s] Issue assigned to %s: #%d %s", p.Repository.FullName,
|
||||||
|
p.Issue.Assignee.UserName, p.Index, p.Issue.Title)
|
||||||
|
text = p.Issue.Body
|
||||||
|
case api.HookIssueUnassigned:
|
||||||
|
title = fmt.Sprintf("[%s] Issue unassigned: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
|
||||||
|
text = p.Issue.Body
|
||||||
|
case api.HookIssueLabelUpdated:
|
||||||
|
title = fmt.Sprintf("[%s] Pull request labels updated: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
|
||||||
|
text = p.Issue.Body
|
||||||
|
case api.HookIssueLabelCleared:
|
||||||
|
title = fmt.Sprintf("[%s] Pull request labels cleared: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
|
||||||
|
text = p.Issue.Body
|
||||||
|
case api.HookIssueSynchronized:
|
||||||
|
title = fmt.Sprintf("[%s] Pull request synchronized: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
|
||||||
|
text = p.Issue.Body
|
||||||
|
}
|
||||||
|
|
||||||
|
return &DingtalkPayload{
|
||||||
|
MsgType: "actionCard",
|
||||||
|
ActionCard: dingtalk.ActionCard{
|
||||||
|
Text: text,
|
||||||
|
Title: title,
|
||||||
|
HideAvatar: "0",
|
||||||
|
SingleTitle: "view pull request",
|
||||||
|
SingleURL: p.Issue.URL,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getDingtalkIssueCommentPayload(p *api.IssueCommentPayload) (*DingtalkPayload, error) {
|
||||||
|
title := fmt.Sprintf("#%d %s", p.Issue.Index, p.Issue.Title)
|
||||||
|
url := fmt.Sprintf("%s/issues/%d#%s", p.Repository.HTMLURL, p.Issue.Index, CommentHashTag(p.Comment.ID))
|
||||||
|
var content string
|
||||||
|
switch p.Action {
|
||||||
|
case api.HookIssueCommentCreated:
|
||||||
|
title = "New comment: " + title
|
||||||
|
content = p.Comment.Body
|
||||||
|
case api.HookIssueCommentEdited:
|
||||||
|
title = "Comment edited: " + title
|
||||||
|
content = p.Comment.Body
|
||||||
|
case api.HookIssueCommentDeleted:
|
||||||
|
title = "Comment deleted: " + title
|
||||||
|
url = fmt.Sprintf("%s/issues/%d", p.Repository.HTMLURL, p.Issue.Index)
|
||||||
|
content = p.Comment.Body
|
||||||
|
}
|
||||||
|
|
||||||
|
return &DingtalkPayload{
|
||||||
|
MsgType: "actionCard",
|
||||||
|
ActionCard: dingtalk.ActionCard{
|
||||||
|
Text: content,
|
||||||
|
Title: title,
|
||||||
|
HideAvatar: "0",
|
||||||
|
SingleTitle: "view pull request",
|
||||||
|
SingleURL: url,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func getDingtalkPullRequestPayload(p *api.PullRequestPayload) (*DingtalkPayload, error) {
|
func getDingtalkPullRequestPayload(p *api.PullRequestPayload) (*DingtalkPayload, error) {
|
||||||
var text, title string
|
var text, title string
|
||||||
switch p.Action {
|
switch p.Action {
|
||||||
|
@ -182,6 +288,27 @@ func getDingtalkRepositoryPayload(p *api.RepositoryPayload) (*DingtalkPayload, e
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getDingtalkReleasePayload(p *api.ReleasePayload) (*DingtalkPayload, error) {
|
||||||
|
var title, url string
|
||||||
|
switch p.Action {
|
||||||
|
case api.HookReleasePublished:
|
||||||
|
title = fmt.Sprintf("[%s] Release created", p.Release.TagName)
|
||||||
|
url = p.Release.URL
|
||||||
|
return &DingtalkPayload{
|
||||||
|
MsgType: "actionCard",
|
||||||
|
ActionCard: dingtalk.ActionCard{
|
||||||
|
Text: title,
|
||||||
|
Title: title,
|
||||||
|
HideAvatar: "0",
|
||||||
|
SingleTitle: "view repository",
|
||||||
|
SingleURL: url,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetDingtalkPayload converts a ding talk webhook into a DingtalkPayload
|
// GetDingtalkPayload converts a ding talk webhook into a DingtalkPayload
|
||||||
func GetDingtalkPayload(p api.Payloader, event HookEventType, meta string) (*DingtalkPayload, error) {
|
func GetDingtalkPayload(p api.Payloader, event HookEventType, meta string) (*DingtalkPayload, error) {
|
||||||
s := new(DingtalkPayload)
|
s := new(DingtalkPayload)
|
||||||
|
@ -189,12 +316,22 @@ func GetDingtalkPayload(p api.Payloader, event HookEventType, meta string) (*Din
|
||||||
switch event {
|
switch event {
|
||||||
case HookEventCreate:
|
case HookEventCreate:
|
||||||
return getDingtalkCreatePayload(p.(*api.CreatePayload))
|
return getDingtalkCreatePayload(p.(*api.CreatePayload))
|
||||||
|
case HookEventDelete:
|
||||||
|
return getDingtalkDeletePayload(p.(*api.DeletePayload))
|
||||||
|
case HookEventFork:
|
||||||
|
return getDingtalkForkPayload(p.(*api.ForkPayload))
|
||||||
|
case HookEventIssues:
|
||||||
|
return getDingtalkIssuesPayload(p.(*api.IssuePayload))
|
||||||
|
case HookEventIssueComment:
|
||||||
|
return getDingtalkIssueCommentPayload(p.(*api.IssueCommentPayload))
|
||||||
case HookEventPush:
|
case HookEventPush:
|
||||||
return getDingtalkPushPayload(p.(*api.PushPayload))
|
return getDingtalkPushPayload(p.(*api.PushPayload))
|
||||||
case HookEventPullRequest:
|
case HookEventPullRequest:
|
||||||
return getDingtalkPullRequestPayload(p.(*api.PullRequestPayload))
|
return getDingtalkPullRequestPayload(p.(*api.PullRequestPayload))
|
||||||
case HookEventRepository:
|
case HookEventRepository:
|
||||||
return getDingtalkRepositoryPayload(p.(*api.RepositoryPayload))
|
return getDingtalkRepositoryPayload(p.(*api.RepositoryPayload))
|
||||||
|
case HookEventRelease:
|
||||||
|
return getDingtalkReleasePayload(p.(*api.ReleasePayload))
|
||||||
}
|
}
|
||||||
|
|
||||||
return s, nil
|
return s, nil
|
||||||
|
|
|
@ -115,6 +115,51 @@ func getDiscordCreatePayload(p *api.CreatePayload, meta *DiscordMeta) (*DiscordP
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getDiscordDeletePayload(p *api.DeletePayload, meta *DiscordMeta) (*DiscordPayload, error) {
|
||||||
|
// deleted tag/branch
|
||||||
|
refName := git.RefEndName(p.Ref)
|
||||||
|
title := fmt.Sprintf("[%s] %s %s deleted", p.Repo.FullName, p.RefType, refName)
|
||||||
|
|
||||||
|
return &DiscordPayload{
|
||||||
|
Username: meta.Username,
|
||||||
|
AvatarURL: meta.IconURL,
|
||||||
|
Embeds: []DiscordEmbed{
|
||||||
|
{
|
||||||
|
Title: title,
|
||||||
|
URL: p.Repo.HTMLURL + "/src/" + refName,
|
||||||
|
Color: warnColor,
|
||||||
|
Author: DiscordEmbedAuthor{
|
||||||
|
Name: p.Sender.UserName,
|
||||||
|
URL: setting.AppURL + p.Sender.UserName,
|
||||||
|
IconURL: p.Sender.AvatarURL,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getDiscordForkPayload(p *api.ForkPayload, meta *DiscordMeta) (*DiscordPayload, error) {
|
||||||
|
// fork
|
||||||
|
title := fmt.Sprintf("%s is forked to %s", p.Forkee.FullName, p.Repo.FullName)
|
||||||
|
|
||||||
|
return &DiscordPayload{
|
||||||
|
Username: meta.Username,
|
||||||
|
AvatarURL: meta.IconURL,
|
||||||
|
Embeds: []DiscordEmbed{
|
||||||
|
{
|
||||||
|
Title: title,
|
||||||
|
URL: p.Repo.HTMLURL,
|
||||||
|
Color: successColor,
|
||||||
|
Author: DiscordEmbedAuthor{
|
||||||
|
Name: p.Sender.UserName,
|
||||||
|
URL: setting.AppURL + p.Sender.UserName,
|
||||||
|
IconURL: p.Sender.AvatarURL,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func getDiscordPushPayload(p *api.PushPayload, meta *DiscordMeta) (*DiscordPayload, error) {
|
func getDiscordPushPayload(p *api.PushPayload, meta *DiscordMeta) (*DiscordPayload, error) {
|
||||||
var (
|
var (
|
||||||
branchName = git.RefEndName(p.Ref)
|
branchName = git.RefEndName(p.Ref)
|
||||||
|
@ -165,6 +210,108 @@ func getDiscordPushPayload(p *api.PushPayload, meta *DiscordMeta) (*DiscordPaylo
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getDiscordIssuesPayload(p *api.IssuePayload, meta *DiscordMeta) (*DiscordPayload, error) {
|
||||||
|
var text, title string
|
||||||
|
var color int
|
||||||
|
switch p.Action {
|
||||||
|
case api.HookIssueOpened:
|
||||||
|
title = fmt.Sprintf("[%s] Issue opened: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
|
||||||
|
text = p.Issue.Body
|
||||||
|
color = warnColor
|
||||||
|
case api.HookIssueClosed:
|
||||||
|
title = fmt.Sprintf("[%s] Issue closed: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
|
||||||
|
color = failedColor
|
||||||
|
text = p.Issue.Body
|
||||||
|
case api.HookIssueReOpened:
|
||||||
|
title = fmt.Sprintf("[%s] Issue re-opened: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
|
||||||
|
text = p.Issue.Body
|
||||||
|
color = warnColor
|
||||||
|
case api.HookIssueEdited:
|
||||||
|
title = fmt.Sprintf("[%s] Issue edited: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
|
||||||
|
text = p.Issue.Body
|
||||||
|
color = warnColor
|
||||||
|
case api.HookIssueAssigned:
|
||||||
|
title = fmt.Sprintf("[%s] Issue assigned to %s: #%d %s", p.Repository.FullName,
|
||||||
|
p.Issue.Assignee.UserName, p.Index, p.Issue.Title)
|
||||||
|
text = p.Issue.Body
|
||||||
|
color = successColor
|
||||||
|
case api.HookIssueUnassigned:
|
||||||
|
title = fmt.Sprintf("[%s] Issue unassigned: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
|
||||||
|
text = p.Issue.Body
|
||||||
|
color = warnColor
|
||||||
|
case api.HookIssueLabelUpdated:
|
||||||
|
title = fmt.Sprintf("[%s] Issue labels updated: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
|
||||||
|
text = p.Issue.Body
|
||||||
|
color = warnColor
|
||||||
|
case api.HookIssueLabelCleared:
|
||||||
|
title = fmt.Sprintf("[%s] Issue labels cleared: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
|
||||||
|
text = p.Issue.Body
|
||||||
|
color = warnColor
|
||||||
|
case api.HookIssueSynchronized:
|
||||||
|
title = fmt.Sprintf("[%s] Issue synchronized: #%d %s", p.Repository.FullName, p.Index, p.Issue.Title)
|
||||||
|
text = p.Issue.Body
|
||||||
|
color = warnColor
|
||||||
|
}
|
||||||
|
|
||||||
|
return &DiscordPayload{
|
||||||
|
Username: meta.Username,
|
||||||
|
AvatarURL: meta.IconURL,
|
||||||
|
Embeds: []DiscordEmbed{
|
||||||
|
{
|
||||||
|
Title: title,
|
||||||
|
Description: text,
|
||||||
|
URL: p.Issue.URL,
|
||||||
|
Color: color,
|
||||||
|
Author: DiscordEmbedAuthor{
|
||||||
|
Name: p.Sender.UserName,
|
||||||
|
URL: setting.AppURL + p.Sender.UserName,
|
||||||
|
IconURL: p.Sender.AvatarURL,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getDiscordIssueCommentPayload(p *api.IssueCommentPayload, discord *DiscordMeta) (*DiscordPayload, error) {
|
||||||
|
title := fmt.Sprintf("#%d %s", p.Issue.Index, p.Issue.Title)
|
||||||
|
url := fmt.Sprintf("%s/issues/%d#%s", p.Repository.HTMLURL, p.Issue.Index, CommentHashTag(p.Comment.ID))
|
||||||
|
content := ""
|
||||||
|
var color int
|
||||||
|
switch p.Action {
|
||||||
|
case api.HookIssueCommentCreated:
|
||||||
|
title = "New comment: " + title
|
||||||
|
content = p.Comment.Body
|
||||||
|
color = successColor
|
||||||
|
case api.HookIssueCommentEdited:
|
||||||
|
title = "Comment edited: " + title
|
||||||
|
content = p.Comment.Body
|
||||||
|
color = warnColor
|
||||||
|
case api.HookIssueCommentDeleted:
|
||||||
|
title = "Comment deleted: " + title
|
||||||
|
url = fmt.Sprintf("%s/issues/%d", p.Repository.HTMLURL, p.Issue.Index)
|
||||||
|
content = p.Comment.Body
|
||||||
|
color = warnColor
|
||||||
|
}
|
||||||
|
|
||||||
|
return &DiscordPayload{
|
||||||
|
Username: discord.Username,
|
||||||
|
AvatarURL: discord.IconURL,
|
||||||
|
Embeds: []DiscordEmbed{
|
||||||
|
{
|
||||||
|
Title: title,
|
||||||
|
Description: content,
|
||||||
|
URL: url,
|
||||||
|
Color: color,
|
||||||
|
Author: DiscordEmbedAuthor{
|
||||||
|
Name: p.Sender.UserName,
|
||||||
|
URL: setting.AppURL + p.Sender.UserName,
|
||||||
|
IconURL: p.Sender.AvatarURL,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func getDiscordPullRequestPayload(p *api.PullRequestPayload, meta *DiscordMeta) (*DiscordPayload, error) {
|
func getDiscordPullRequestPayload(p *api.PullRequestPayload, meta *DiscordMeta) (*DiscordPayload, error) {
|
||||||
var text, title string
|
var text, title string
|
||||||
var color int
|
var color int
|
||||||
|
@ -267,6 +414,35 @@ func getDiscordRepositoryPayload(p *api.RepositoryPayload, meta *DiscordMeta) (*
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getDiscordReleasePayload(p *api.ReleasePayload, meta *DiscordMeta) (*DiscordPayload, error) {
|
||||||
|
var title, url string
|
||||||
|
var color int
|
||||||
|
switch p.Action {
|
||||||
|
case api.HookReleasePublished:
|
||||||
|
title = fmt.Sprintf("[%s] Release created", p.Release.TagName)
|
||||||
|
url = p.Release.URL
|
||||||
|
color = successColor
|
||||||
|
}
|
||||||
|
|
||||||
|
return &DiscordPayload{
|
||||||
|
Username: meta.Username,
|
||||||
|
AvatarURL: meta.IconURL,
|
||||||
|
Embeds: []DiscordEmbed{
|
||||||
|
{
|
||||||
|
Title: title,
|
||||||
|
Description: fmt.Sprintf("%s", p.Release.Note),
|
||||||
|
URL: url,
|
||||||
|
Color: color,
|
||||||
|
Author: DiscordEmbedAuthor{
|
||||||
|
Name: p.Sender.UserName,
|
||||||
|
URL: setting.AppURL + p.Sender.UserName,
|
||||||
|
IconURL: p.Sender.AvatarURL,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetDiscordPayload converts a discord webhook into a DiscordPayload
|
// GetDiscordPayload converts a discord webhook into a DiscordPayload
|
||||||
func GetDiscordPayload(p api.Payloader, event HookEventType, meta string) (*DiscordPayload, error) {
|
func GetDiscordPayload(p api.Payloader, event HookEventType, meta string) (*DiscordPayload, error) {
|
||||||
s := new(DiscordPayload)
|
s := new(DiscordPayload)
|
||||||
|
@ -279,12 +455,22 @@ func GetDiscordPayload(p api.Payloader, event HookEventType, meta string) (*Disc
|
||||||
switch event {
|
switch event {
|
||||||
case HookEventCreate:
|
case HookEventCreate:
|
||||||
return getDiscordCreatePayload(p.(*api.CreatePayload), discord)
|
return getDiscordCreatePayload(p.(*api.CreatePayload), discord)
|
||||||
|
case HookEventDelete:
|
||||||
|
return getDiscordDeletePayload(p.(*api.DeletePayload), discord)
|
||||||
|
case HookEventFork:
|
||||||
|
return getDiscordForkPayload(p.(*api.ForkPayload), discord)
|
||||||
|
case HookEventIssues:
|
||||||
|
return getDiscordIssuesPayload(p.(*api.IssuePayload), discord)
|
||||||
|
case HookEventIssueComment:
|
||||||
|
return getDiscordIssueCommentPayload(p.(*api.IssueCommentPayload), discord)
|
||||||
case HookEventPush:
|
case HookEventPush:
|
||||||
return getDiscordPushPayload(p.(*api.PushPayload), discord)
|
return getDiscordPushPayload(p.(*api.PushPayload), discord)
|
||||||
case HookEventPullRequest:
|
case HookEventPullRequest:
|
||||||
return getDiscordPullRequestPayload(p.(*api.PullRequestPayload), discord)
|
return getDiscordPullRequestPayload(p.(*api.PullRequestPayload), discord)
|
||||||
case HookEventRepository:
|
case HookEventRepository:
|
||||||
return getDiscordRepositoryPayload(p.(*api.RepositoryPayload), discord)
|
return getDiscordRepositoryPayload(p.(*api.RepositoryPayload), discord)
|
||||||
|
case HookEventRelease:
|
||||||
|
return getDiscordReleasePayload(p.(*api.ReleasePayload), discord)
|
||||||
}
|
}
|
||||||
|
|
||||||
return s, nil
|
return s, nil
|
||||||
|
|
|
@ -106,6 +106,122 @@ func getSlackCreatePayload(p *api.CreatePayload, slack *SlackMeta) (*SlackPayloa
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getSlackDeletePayload composes Slack payload for delete a branch or tag.
|
||||||
|
func getSlackDeletePayload(p *api.DeletePayload, slack *SlackMeta) (*SlackPayload, error) {
|
||||||
|
refName := git.RefEndName(p.Ref)
|
||||||
|
repoLink := SlackLinkFormatter(p.Repo.HTMLURL, p.Repo.Name)
|
||||||
|
text := fmt.Sprintf("[%s:%s] %s deleted by %s", repoLink, refName, p.RefType, p.Sender.UserName)
|
||||||
|
return &SlackPayload{
|
||||||
|
Channel: slack.Channel,
|
||||||
|
Text: text,
|
||||||
|
Username: slack.Username,
|
||||||
|
IconURL: slack.IconURL,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getSlackForkPayload composes Slack payload for forked by a repository.
|
||||||
|
func getSlackForkPayload(p *api.ForkPayload, slack *SlackMeta) (*SlackPayload, error) {
|
||||||
|
baseLink := SlackLinkFormatter(p.Repo.HTMLURL, p.Repo.Name)
|
||||||
|
forkLink := SlackLinkFormatter(p.Forkee.HTMLURL, p.Forkee.FullName)
|
||||||
|
text := fmt.Sprintf("%s is forked to %s", baseLink, forkLink)
|
||||||
|
return &SlackPayload{
|
||||||
|
Channel: slack.Channel,
|
||||||
|
Text: text,
|
||||||
|
Username: slack.Username,
|
||||||
|
IconURL: slack.IconURL,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getSlackIssuesPayload(p *api.IssuePayload, slack *SlackMeta) (*SlackPayload, error) {
|
||||||
|
senderLink := SlackLinkFormatter(setting.AppURL+p.Sender.UserName, p.Sender.UserName)
|
||||||
|
titleLink := SlackLinkFormatter(fmt.Sprintf("%s/pulls/%d", p.Repository.HTMLURL, p.Index),
|
||||||
|
fmt.Sprintf("#%d %s", p.Index, p.Issue.Title))
|
||||||
|
var text, title, attachmentText string
|
||||||
|
switch p.Action {
|
||||||
|
case api.HookIssueOpened:
|
||||||
|
text = fmt.Sprintf("[%s] Issue submitted by %s", p.Repository.FullName, senderLink)
|
||||||
|
title = titleLink
|
||||||
|
attachmentText = SlackTextFormatter(p.Issue.Body)
|
||||||
|
case api.HookIssueClosed:
|
||||||
|
text = fmt.Sprintf("[%s] Issue closed: %s by %s", p.Repository.FullName, titleLink, senderLink)
|
||||||
|
case api.HookIssueReOpened:
|
||||||
|
text = fmt.Sprintf("[%s] Issue re-opened: %s by %s", p.Repository.FullName, titleLink, senderLink)
|
||||||
|
case api.HookIssueEdited:
|
||||||
|
text = fmt.Sprintf("[%s] Issue edited: %s by %s", p.Repository.FullName, titleLink, senderLink)
|
||||||
|
attachmentText = SlackTextFormatter(p.Issue.Body)
|
||||||
|
case api.HookIssueAssigned:
|
||||||
|
text = fmt.Sprintf("[%s] Issue assigned to %s: %s by %s", p.Repository.FullName,
|
||||||
|
SlackLinkFormatter(setting.AppURL+p.Issue.Assignee.UserName, p.Issue.Assignee.UserName),
|
||||||
|
titleLink, senderLink)
|
||||||
|
case api.HookIssueUnassigned:
|
||||||
|
text = fmt.Sprintf("[%s] Issue unassigned: %s by %s", p.Repository.FullName, titleLink, senderLink)
|
||||||
|
case api.HookIssueLabelUpdated:
|
||||||
|
text = fmt.Sprintf("[%s] Issue labels updated: %s by %s", p.Repository.FullName, titleLink, senderLink)
|
||||||
|
case api.HookIssueLabelCleared:
|
||||||
|
text = fmt.Sprintf("[%s] Issue labels cleared: %s by %s", p.Repository.FullName, titleLink, senderLink)
|
||||||
|
case api.HookIssueSynchronized:
|
||||||
|
text = fmt.Sprintf("[%s] Issue synchronized: %s by %s", p.Repository.FullName, titleLink, senderLink)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &SlackPayload{
|
||||||
|
Channel: slack.Channel,
|
||||||
|
Text: text,
|
||||||
|
Username: slack.Username,
|
||||||
|
IconURL: slack.IconURL,
|
||||||
|
Attachments: []SlackAttachment{{
|
||||||
|
Color: slack.Color,
|
||||||
|
Title: title,
|
||||||
|
Text: attachmentText,
|
||||||
|
}},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getSlackIssueCommentPayload(p *api.IssueCommentPayload, slack *SlackMeta) (*SlackPayload, error) {
|
||||||
|
senderLink := SlackLinkFormatter(setting.AppURL+p.Sender.UserName, p.Sender.UserName)
|
||||||
|
titleLink := SlackLinkFormatter(fmt.Sprintf("%s/issues/%d#%s", p.Repository.HTMLURL, p.Issue.Index, CommentHashTag(p.Comment.ID)),
|
||||||
|
fmt.Sprintf("#%d %s", p.Issue.Index, p.Issue.Title))
|
||||||
|
var text, title, attachmentText string
|
||||||
|
switch p.Action {
|
||||||
|
case api.HookIssueCommentCreated:
|
||||||
|
text = fmt.Sprintf("[%s] New comment created by %s", p.Repository.FullName, senderLink)
|
||||||
|
title = titleLink
|
||||||
|
attachmentText = SlackTextFormatter(p.Comment.Body)
|
||||||
|
case api.HookIssueCommentEdited:
|
||||||
|
text = fmt.Sprintf("[%s] Comment edited by %s", p.Repository.FullName, senderLink)
|
||||||
|
title = titleLink
|
||||||
|
attachmentText = SlackTextFormatter(p.Comment.Body)
|
||||||
|
case api.HookIssueCommentDeleted:
|
||||||
|
text = fmt.Sprintf("[%s] Comment deleted by %s", p.Repository.FullName, senderLink)
|
||||||
|
title = SlackLinkFormatter(fmt.Sprintf("%s/issues/%d", p.Repository.HTMLURL, p.Issue.Index),
|
||||||
|
fmt.Sprintf("#%d %s", p.Issue.Index, p.Issue.Title))
|
||||||
|
attachmentText = SlackTextFormatter(p.Comment.Body)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &SlackPayload{
|
||||||
|
Channel: slack.Channel,
|
||||||
|
Text: text,
|
||||||
|
Username: slack.Username,
|
||||||
|
IconURL: slack.IconURL,
|
||||||
|
Attachments: []SlackAttachment{{
|
||||||
|
Color: slack.Color,
|
||||||
|
Title: title,
|
||||||
|
Text: attachmentText,
|
||||||
|
}},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getSlackReleasePayload(p *api.ReleasePayload, slack *SlackMeta) (*SlackPayload, error) {
|
||||||
|
repoLink := SlackLinkFormatter(p.Repository.HTMLURL, p.Repository.Name)
|
||||||
|
refLink := SlackLinkFormatter(p.Repository.HTMLURL+"/src/"+p.Release.TagName, p.Release.TagName)
|
||||||
|
text := fmt.Sprintf("[%s] new release %s published by %s", repoLink, refLink, p.Sender.UserName)
|
||||||
|
return &SlackPayload{
|
||||||
|
Channel: slack.Channel,
|
||||||
|
Text: text,
|
||||||
|
Username: slack.Username,
|
||||||
|
IconURL: slack.IconURL,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func getSlackPushPayload(p *api.PushPayload, slack *SlackMeta) (*SlackPayload, error) {
|
func getSlackPushPayload(p *api.PushPayload, slack *SlackMeta) (*SlackPayload, error) {
|
||||||
// n new commits
|
// n new commits
|
||||||
var (
|
var (
|
||||||
|
@ -238,12 +354,22 @@ func GetSlackPayload(p api.Payloader, event HookEventType, meta string) (*SlackP
|
||||||
switch event {
|
switch event {
|
||||||
case HookEventCreate:
|
case HookEventCreate:
|
||||||
return getSlackCreatePayload(p.(*api.CreatePayload), slack)
|
return getSlackCreatePayload(p.(*api.CreatePayload), slack)
|
||||||
|
case HookEventDelete:
|
||||||
|
return getSlackDeletePayload(p.(*api.DeletePayload), slack)
|
||||||
|
case HookEventFork:
|
||||||
|
return getSlackForkPayload(p.(*api.ForkPayload), slack)
|
||||||
|
case HookEventIssues:
|
||||||
|
return getSlackIssuesPayload(p.(*api.IssuePayload), slack)
|
||||||
|
case HookEventIssueComment:
|
||||||
|
return getSlackIssueCommentPayload(p.(*api.IssueCommentPayload), slack)
|
||||||
case HookEventPush:
|
case HookEventPush:
|
||||||
return getSlackPushPayload(p.(*api.PushPayload), slack)
|
return getSlackPushPayload(p.(*api.PushPayload), slack)
|
||||||
case HookEventPullRequest:
|
case HookEventPullRequest:
|
||||||
return getSlackPullRequestPayload(p.(*api.PullRequestPayload), slack)
|
return getSlackPullRequestPayload(p.(*api.PullRequestPayload), slack)
|
||||||
case HookEventRepository:
|
case HookEventRepository:
|
||||||
return getSlackRepositoryPayload(p.(*api.RepositoryPayload), slack)
|
return getSlackRepositoryPayload(p.(*api.RepositoryPayload), slack)
|
||||||
|
case HookEventRelease:
|
||||||
|
return getSlackReleasePayload(p.(*api.ReleasePayload), slack)
|
||||||
}
|
}
|
||||||
|
|
||||||
return s, nil
|
return s, nil
|
||||||
|
|
|
@ -73,7 +73,7 @@ func TestWebhook_UpdateEvent(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWebhook_EventsArray(t *testing.T) {
|
func TestWebhook_EventsArray(t *testing.T) {
|
||||||
assert.Equal(t, []string{"create", "push", "pull_request"},
|
assert.Equal(t, []string{"create", "delete", "fork", "push", "issues", "issue_comment", "pull_request", "repository", "release"},
|
||||||
(&Webhook{
|
(&Webhook{
|
||||||
HookEvent: &HookEvent{SendEverything: true},
|
HookEvent: &HookEvent{SendEverything: true},
|
||||||
}).EventsArray(),
|
}).EventsArray(),
|
||||||
|
|
|
@ -157,6 +157,11 @@ func (f *ProtectBranchForm) Validate(ctx *macaron.Context, errs binding.Errors)
|
||||||
type WebhookForm struct {
|
type WebhookForm struct {
|
||||||
Events string
|
Events string
|
||||||
Create bool
|
Create bool
|
||||||
|
Delete bool
|
||||||
|
Fork bool
|
||||||
|
Issues bool
|
||||||
|
IssueComment bool
|
||||||
|
Release bool
|
||||||
Push bool
|
Push bool
|
||||||
PullRequest bool
|
PullRequest bool
|
||||||
Repository bool
|
Repository bool
|
||||||
|
|
|
@ -1000,6 +1000,16 @@ settings.event_send_everything = All Events
|
||||||
settings.event_choose = Custom Events…
|
settings.event_choose = Custom 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_desc = Branch or tag deleted
|
||||||
|
settings.event_fork = Fork
|
||||||
|
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_desc = Release published in a repository.
|
||||||
settings.event_pull_request = Pull Request
|
settings.event_pull_request = Pull Request
|
||||||
settings.event_pull_request_desc = Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared or synchronized.
|
settings.event_pull_request_desc = Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared or synchronized.
|
||||||
settings.event_push = Push
|
settings.event_push = Push
|
||||||
|
|
|
@ -261,8 +261,9 @@ func editIssueComment(ctx *context.APIContext, form api.EditIssueCommentOption)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
oldContent := comment.Content
|
||||||
comment.Content = form.Body
|
comment.Content = form.Body
|
||||||
if err := models.UpdateComment(comment); err != nil {
|
if err := models.UpdateComment(ctx.User, comment, oldContent); err != nil {
|
||||||
ctx.Error(500, "UpdateComment", err)
|
ctx.Error(500, "UpdateComment", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -348,7 +349,7 @@ func deleteIssueComment(ctx *context.APIContext) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = models.DeleteComment(comment); err != nil {
|
if err = models.DeleteComment(ctx.User, comment); err != nil {
|
||||||
ctx.Error(500, "DeleteCommentByID", err)
|
ctx.Error(500, "DeleteCommentByID", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,12 +7,13 @@ package utils
|
||||||
import (
|
import (
|
||||||
api "code.gitea.io/sdk/gitea"
|
api "code.gitea.io/sdk/gitea"
|
||||||
|
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"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/routers/api/v1/convert"
|
"code.gitea.io/gitea/routers/api/v1/convert"
|
||||||
"encoding/json"
|
|
||||||
"github.com/Unknwon/com"
|
"github.com/Unknwon/com"
|
||||||
"net/http"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetOrgHook get an organization's webhook. If there is an error, write to
|
// GetOrgHook get an organization's webhook. If there is an error, write to
|
||||||
|
@ -99,8 +100,14 @@ func addHook(ctx *context.APIContext, form *api.CreateHookOption, orgID, repoID
|
||||||
ChooseEvents: true,
|
ChooseEvents: true,
|
||||||
HookEvents: models.HookEvents{
|
HookEvents: models.HookEvents{
|
||||||
Create: com.IsSliceContainsStr(form.Events, string(models.HookEventCreate)),
|
Create: com.IsSliceContainsStr(form.Events, string(models.HookEventCreate)),
|
||||||
|
Delete: com.IsSliceContainsStr(form.Events, string(models.HookEventDelete)),
|
||||||
|
Fork: com.IsSliceContainsStr(form.Events, string(models.HookEventFork)),
|
||||||
|
Issues: com.IsSliceContainsStr(form.Events, string(models.HookEventIssues)),
|
||||||
|
IssueComment: com.IsSliceContainsStr(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: com.IsSliceContainsStr(form.Events, string(models.HookEventPullRequest)),
|
||||||
|
Repository: com.IsSliceContainsStr(form.Events, string(models.HookEventRepository)),
|
||||||
|
Release: com.IsSliceContainsStr(form.Events, string(models.HookEventRelease)),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
IsActive: form.Active,
|
IsActive: form.Active,
|
||||||
|
@ -211,6 +218,16 @@ func editHook(ctx *context.APIContext, form *api.EditHookOption, w *models.Webho
|
||||||
w.Create = com.IsSliceContainsStr(form.Events, string(models.HookEventCreate))
|
w.Create = com.IsSliceContainsStr(form.Events, string(models.HookEventCreate))
|
||||||
w.Push = com.IsSliceContainsStr(form.Events, string(models.HookEventPush))
|
w.Push = com.IsSliceContainsStr(form.Events, string(models.HookEventPush))
|
||||||
w.PullRequest = com.IsSliceContainsStr(form.Events, string(models.HookEventPullRequest))
|
w.PullRequest = com.IsSliceContainsStr(form.Events, string(models.HookEventPullRequest))
|
||||||
|
w.Create = com.IsSliceContainsStr(form.Events, string(models.HookEventCreate))
|
||||||
|
w.Delete = com.IsSliceContainsStr(form.Events, string(models.HookEventDelete))
|
||||||
|
w.Fork = com.IsSliceContainsStr(form.Events, string(models.HookEventFork))
|
||||||
|
w.Issues = com.IsSliceContainsStr(form.Events, string(models.HookEventIssues))
|
||||||
|
w.IssueComment = com.IsSliceContainsStr(form.Events, string(models.HookEventIssueComment))
|
||||||
|
w.Push = com.IsSliceContainsStr(form.Events, string(models.HookEventPush))
|
||||||
|
w.PullRequest = com.IsSliceContainsStr(form.Events, string(models.HookEventPullRequest))
|
||||||
|
w.Repository = com.IsSliceContainsStr(form.Events, string(models.HookEventRepository))
|
||||||
|
w.Release = com.IsSliceContainsStr(form.Events, string(models.HookEventRelease))
|
||||||
|
|
||||||
if err := w.UpdateEvent(); err != nil {
|
if err := w.UpdateEvent(); err != nil {
|
||||||
ctx.Error(500, "UpdateEvent", err)
|
ctx.Error(500, "UpdateEvent", err)
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -1086,6 +1086,7 @@ func UpdateCommentContent(ctx *context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
oldContent := comment.Content
|
||||||
comment.Content = ctx.Query("content")
|
comment.Content = ctx.Query("content")
|
||||||
if len(comment.Content) == 0 {
|
if len(comment.Content) == 0 {
|
||||||
ctx.JSON(200, map[string]interface{}{
|
ctx.JSON(200, map[string]interface{}{
|
||||||
|
@ -1093,7 +1094,7 @@ func UpdateCommentContent(ctx *context.Context) {
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err = models.UpdateComment(comment); err != nil {
|
if err = models.UpdateComment(ctx.User, comment, oldContent); err != nil {
|
||||||
ctx.ServerError("UpdateComment", err)
|
ctx.ServerError("UpdateComment", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1119,7 +1120,7 @@ func DeleteComment(ctx *context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = models.DeleteComment(comment); err != nil {
|
if err = models.DeleteComment(ctx.User, comment); err != nil {
|
||||||
ctx.ServerError("DeleteCommentByID", err)
|
ctx.ServerError("DeleteCommentByID", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,9 +23,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
tplHooks base.TplName = "repo/settings/hooks"
|
tplHooks base.TplName = "repo/settings/webhook/base"
|
||||||
tplHookNew base.TplName = "repo/settings/hook_new"
|
tplHookNew base.TplName = "repo/settings/webhook/new"
|
||||||
tplOrgHookNew base.TplName = "org/settings/hook_new"
|
tplOrgHookNew base.TplName = "org/settings/webhook/new"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Webhooks render web hooks list page
|
// Webhooks render web hooks list page
|
||||||
|
@ -119,6 +119,11 @@ func ParseHookEvent(form auth.WebhookForm) *models.HookEvent {
|
||||||
ChooseEvents: form.ChooseEvents(),
|
ChooseEvents: form.ChooseEvents(),
|
||||||
HookEvents: models.HookEvents{
|
HookEvents: models.HookEvents{
|
||||||
Create: form.Create,
|
Create: form.Create,
|
||||||
|
Delete: form.Delete,
|
||||||
|
Fork: form.Fork,
|
||||||
|
Issues: form.Issues,
|
||||||
|
IssueComment: form.IssueComment,
|
||||||
|
Release: form.Release,
|
||||||
Push: form.Push,
|
Push: form.Push,
|
||||||
PullRequest: form.PullRequest,
|
PullRequest: form.PullRequest,
|
||||||
Repository: form.Repository,
|
Repository: form.Repository,
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
{{template "repo/header" .}}
|
{{template "repo/header" .}}
|
||||||
{{template "repo/settings/navbar" .}}
|
{{template "repo/settings/navbar" .}}
|
||||||
<div class="ui container">
|
<div class="ui container">
|
||||||
{{template "repo/settings/hook_list" .}}
|
{{template "repo/settings/webhook/list" .}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{template "base/footer" .}}
|
{{template "base/footer" .}}
|
|
@ -6,6 +6,6 @@
|
||||||
<label for="payload_url">{{.i18n.Tr "repo.settings.payload_url"}}</label>
|
<label for="payload_url">{{.i18n.Tr "repo.settings.payload_url"}}</label>
|
||||||
<input id="payload_url" name="payload_url" type="url" value="{{.Webhook.URL}}" autofocus required>
|
<input id="payload_url" name="payload_url" type="url" value="{{.Webhook.URL}}" autofocus required>
|
||||||
</div>
|
</div>
|
||||||
{{template "repo/settings/hook_settings" .}}
|
{{template "repo/settings/webhook/settings" .}}
|
||||||
</form>
|
</form>
|
||||||
{{end}}
|
{{end}}
|
|
@ -14,6 +14,6 @@
|
||||||
<label for="icon_url">{{.i18n.Tr "repo.settings.discord_icon_url"}}</label>
|
<label for="icon_url">{{.i18n.Tr "repo.settings.discord_icon_url"}}</label>
|
||||||
<input id="icon_url" name="icon_url" value="{{.DiscordHook.IconURL}}" placeholder="e.g. https://example.com/img/favicon.png">
|
<input id="icon_url" name="icon_url" value="{{.DiscordHook.IconURL}}" placeholder="e.g. https://example.com/img/favicon.png">
|
||||||
</div>
|
</div>
|
||||||
{{template "repo/settings/hook_settings" .}}
|
{{template "repo/settings/webhook/settings" .}}
|
||||||
</form>
|
</form>
|
||||||
{{end}}
|
{{end}}
|
|
@ -23,6 +23,6 @@
|
||||||
<label for="secret">{{.i18n.Tr "repo.settings.secret"}}</label>
|
<label for="secret">{{.i18n.Tr "repo.settings.secret"}}</label>
|
||||||
<input id="secret" name="secret" type="password" value="{{.Webhook.Secret}}" autocomplete="off">
|
<input id="secret" name="secret" type="password" value="{{.Webhook.Secret}}" autocomplete="off">
|
||||||
</div>
|
</div>
|
||||||
{{template "repo/settings/hook_settings" .}}
|
{{template "repo/settings/webhook/settings" .}}
|
||||||
</form>
|
</form>
|
||||||
{{end}}
|
{{end}}
|
|
@ -23,6 +23,6 @@
|
||||||
<label for="secret">{{.i18n.Tr "repo.settings.secret"}}</label>
|
<label for="secret">{{.i18n.Tr "repo.settings.secret"}}</label>
|
||||||
<input id="secret" name="secret" type="password" value="{{.Webhook.Secret}}" autocomplete="off">
|
<input id="secret" name="secret" type="password" value="{{.Webhook.Secret}}" autocomplete="off">
|
||||||
</div>
|
</div>
|
||||||
{{template "repo/settings/hook_settings" .}}
|
{{template "repo/settings/webhook/settings" .}}
|
||||||
</form>
|
</form>
|
||||||
{{end}}
|
{{end}}
|
|
@ -48,4 +48,4 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{template "repo/settings/hook_delete_modal" .}}
|
{{template "repo/settings/webhook/delete_modal" .}}
|
|
@ -21,14 +21,14 @@
|
||||||
</div>
|
</div>
|
||||||
</h4>
|
</h4>
|
||||||
<div class="ui attached segment">
|
<div class="ui attached segment">
|
||||||
{{template "repo/settings/hook_gitea" .}}
|
{{template "repo/settings/webhook/gitea" .}}
|
||||||
{{template "repo/settings/hook_gogs" .}}
|
{{template "repo/settings/webhook/gogs" .}}
|
||||||
{{template "repo/settings/hook_slack" .}}
|
{{template "repo/settings/webhook/slack" .}}
|
||||||
{{template "repo/settings/hook_discord" .}}
|
{{template "repo/settings/webhook/discord" .}}
|
||||||
{{template "repo/settings/hook_dingtalk" .}}
|
{{template "repo/settings/webhook/dingtalk" .}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{template "repo/settings/hook_history" .}}
|
{{template "repo/settings/webhook/history" .}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{template "base/footer" .}}
|
{{template "base/footer" .}}
|
|
@ -32,6 +32,26 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- Delete -->
|
||||||
|
<div class="seven wide column">
|
||||||
|
<div class="field">
|
||||||
|
<div class="ui checkbox">
|
||||||
|
<input class="hidden" name="delete" type="checkbox" tabindex="0" {{if .Webhook.Delete}}checked{{end}}>
|
||||||
|
<label>{{.i18n.Tr "repo.settings.event_delete"}}</label>
|
||||||
|
<span class="help">{{.i18n.Tr "repo.settings.event_delete_desc"}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Fork -->
|
||||||
|
<div class="seven wide column">
|
||||||
|
<div class="field">
|
||||||
|
<div class="ui checkbox">
|
||||||
|
<input class="hidden" name="fork" type="checkbox" tabindex="0" {{if .Webhook.Fork}}checked{{end}}>
|
||||||
|
<label>{{.i18n.Tr "repo.settings.event_fork"}}</label>
|
||||||
|
<span class="help">{{.i18n.Tr "repo.settings.event_fork_desc"}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<!-- Push -->
|
<!-- Push -->
|
||||||
<div class="seven wide column">
|
<div class="seven wide column">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
|
@ -42,6 +62,26 @@
|
||||||
</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 -->
|
<!-- Pull Request -->
|
||||||
<div class="seven wide column">
|
<div class="seven wide column">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
|
@ -62,6 +102,16 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- Release -->
|
||||||
|
<div class="seven wide column">
|
||||||
|
<div class="field">
|
||||||
|
<div class="ui checkbox">
|
||||||
|
<input class="hidden" name="release" type="checkbox" tabindex="0" {{if .Webhook.Release}}checked{{end}}>
|
||||||
|
<label>{{.i18n.Tr "repo.settings.event_release"}}</label>
|
||||||
|
<span class="help">{{.i18n.Tr "repo.settings.event_release_desc"}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -83,4 +133,4 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{template "repo/settings/hook_delete_modal" .}}
|
{{template "repo/settings/webhook/delete_modal" .}}
|
|
@ -23,6 +23,6 @@
|
||||||
<label for="color">{{.i18n.Tr "repo.settings.slack_color"}}</label>
|
<label for="color">{{.i18n.Tr "repo.settings.slack_color"}}</label>
|
||||||
<input id="color" name="color" value="{{.SlackHook.Color}}" placeholder="e.g. #dd4b39, good, warning, danger">
|
<input id="color" name="color" value="{{.SlackHook.Color}}" placeholder="e.g. #dd4b39, good, warning, danger">
|
||||||
</div>
|
</div>
|
||||||
{{template "repo/settings/hook_settings" .}}
|
{{template "repo/settings/webhook/settings" .}}
|
||||||
</form>
|
</form>
|
||||||
{{end}}
|
{{end}}
|
122
vendor/code.gitea.io/sdk/gitea/hook.go
generated
vendored
122
vendor/code.gitea.io/sdk/gitea/hook.go
generated
vendored
|
@ -172,9 +172,14 @@ type PayloadCommitVerification struct {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
_ Payloader = &CreatePayload{}
|
_ Payloader = &CreatePayload{}
|
||||||
|
_ Payloader = &DeletePayload{}
|
||||||
|
_ Payloader = &ForkPayload{}
|
||||||
_ Payloader = &PushPayload{}
|
_ Payloader = &PushPayload{}
|
||||||
_ Payloader = &IssuePayload{}
|
_ Payloader = &IssuePayload{}
|
||||||
|
_ Payloader = &IssueCommentPayload{}
|
||||||
_ Payloader = &PullRequestPayload{}
|
_ Payloader = &PullRequestPayload{}
|
||||||
|
_ Payloader = &RepositoryPayload{}
|
||||||
|
_ Payloader = &ReleasePayload{}
|
||||||
)
|
)
|
||||||
|
|
||||||
// _________ __
|
// _________ __
|
||||||
|
@ -224,6 +229,123 @@ func ParseCreateHook(raw []byte) (*CreatePayload, error) {
|
||||||
return hook, nil
|
return hook, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ________ .__ __
|
||||||
|
// \______ \ ____ | | _____/ |_ ____
|
||||||
|
// | | \_/ __ \| | _/ __ \ __\/ __ \
|
||||||
|
// | ` \ ___/| |_\ ___/| | \ ___/
|
||||||
|
// /_______ /\___ >____/\___ >__| \___ >
|
||||||
|
// \/ \/ \/ \/
|
||||||
|
|
||||||
|
// PusherType define the type to push
|
||||||
|
type PusherType string
|
||||||
|
|
||||||
|
// describe all the PusherTypes
|
||||||
|
const (
|
||||||
|
PusherTypeUser PusherType = "user"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DeletePayload represents delete payload
|
||||||
|
type DeletePayload struct {
|
||||||
|
Ref string `json:"ref"`
|
||||||
|
RefType string `json:"ref_type"`
|
||||||
|
PusherType PusherType `json:"pusher_type"`
|
||||||
|
Repo *Repository `json:"repository"`
|
||||||
|
Sender *User `json:"sender"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetSecret implements Payload
|
||||||
|
func (p *DeletePayload) SetSecret(secret string) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSONPayload implements Payload
|
||||||
|
func (p *DeletePayload) JSONPayload() ([]byte, error) {
|
||||||
|
return json.MarshalIndent(p, "", " ")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ___________ __
|
||||||
|
// \_ _____/__________| | __
|
||||||
|
// | __)/ _ \_ __ \ |/ /
|
||||||
|
// | \( <_> ) | \/ <
|
||||||
|
// \___ / \____/|__| |__|_ \
|
||||||
|
// \/ \/
|
||||||
|
|
||||||
|
// ForkPayload represents fork payload
|
||||||
|
type ForkPayload struct {
|
||||||
|
Forkee *Repository `json:"forkee"`
|
||||||
|
Repo *Repository `json:"repository"`
|
||||||
|
Sender *User `json:"sender"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetSecret implements Payload
|
||||||
|
func (p *ForkPayload) SetSecret(secret string) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSONPayload implements Payload
|
||||||
|
func (p *ForkPayload) JSONPayload() ([]byte, error) {
|
||||||
|
return json.MarshalIndent(p, "", " ")
|
||||||
|
}
|
||||||
|
|
||||||
|
// HookIssueCommentAction defines hook issue comment action
|
||||||
|
type HookIssueCommentAction string
|
||||||
|
|
||||||
|
// all issue comment actions
|
||||||
|
const (
|
||||||
|
HookIssueCommentCreated HookIssueCommentAction = "created"
|
||||||
|
HookIssueCommentEdited HookIssueCommentAction = "edited"
|
||||||
|
HookIssueCommentDeleted HookIssueCommentAction = "deleted"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IssueCommentPayload represents a payload information of issue comment event.
|
||||||
|
type IssueCommentPayload struct {
|
||||||
|
Action HookIssueCommentAction `json:"action"`
|
||||||
|
Issue *Issue `json:"issue"`
|
||||||
|
Comment *Comment `json:"comment"`
|
||||||
|
Changes *ChangesPayload `json:"changes,omitempty"`
|
||||||
|
Repository *Repository `json:"repository"`
|
||||||
|
Sender *User `json:"sender"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetSecret implements Payload
|
||||||
|
func (p *IssueCommentPayload) SetSecret(secret string) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSONPayload implements Payload
|
||||||
|
func (p *IssueCommentPayload) JSONPayload() ([]byte, error) {
|
||||||
|
return json.MarshalIndent(p, "", " ")
|
||||||
|
}
|
||||||
|
|
||||||
|
// __________ .__
|
||||||
|
// \______ \ ____ | | ____ _____ ______ ____
|
||||||
|
// | _// __ \| | _/ __ \\__ \ / ___// __ \
|
||||||
|
// | | \ ___/| |_\ ___/ / __ \_\___ \\ ___/
|
||||||
|
// |____|_ /\___ >____/\___ >____ /____ >\___ >
|
||||||
|
// \/ \/ \/ \/ \/ \/
|
||||||
|
|
||||||
|
// HookReleaseAction defines hook release action type
|
||||||
|
type HookReleaseAction string
|
||||||
|
|
||||||
|
// all release actions
|
||||||
|
const (
|
||||||
|
HookReleasePublished HookReleaseAction = "published"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ReleasePayload represents a payload information of release event.
|
||||||
|
type ReleasePayload struct {
|
||||||
|
Action HookReleaseAction `json:"action"`
|
||||||
|
Release *Release `json:"release"`
|
||||||
|
Repository *Repository `json:"repository"`
|
||||||
|
Sender *User `json:"sender"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetSecret implements Payload
|
||||||
|
func (p *ReleasePayload) SetSecret(secret string) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSONPayload implements Payload
|
||||||
|
func (p *ReleasePayload) JSONPayload() ([]byte, error) {
|
||||||
|
return json.MarshalIndent(p, "", " ")
|
||||||
|
}
|
||||||
|
|
||||||
// __________ .__
|
// __________ .__
|
||||||
// \______ \__ __ _____| |__
|
// \______ \__ __ _____| |__
|
||||||
// | ___/ | \/ ___/ | \
|
// | ___/ | \/ ___/ | \
|
||||||
|
|
14
vendor/code.gitea.io/sdk/gitea/issue.go
generated
vendored
14
vendor/code.gitea.io/sdk/gitea/issue.go
generated
vendored
|
@ -138,3 +138,17 @@ func (c *Client) EditIssue(owner, repo string, index int64, opt EditIssueOption)
|
||||||
return issue, c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/issues/%d", owner, repo, index),
|
return issue, c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/issues/%d", owner, repo, index),
|
||||||
jsonHeader, bytes.NewReader(body), issue)
|
jsonHeader, bytes.NewReader(body), issue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EditDeadlineOption options for creating a deadline
|
||||||
|
type EditDeadlineOption struct {
|
||||||
|
// required:true
|
||||||
|
// swagger:strfmt date-time
|
||||||
|
Deadline *time.Time `json:"due_date"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// IssueDeadline represents an issue deadline
|
||||||
|
// swagger:model
|
||||||
|
type IssueDeadline struct {
|
||||||
|
// swagger:strfmt date-time
|
||||||
|
Deadline *time.Time `json:"due_date"`
|
||||||
|
}
|
||||||
|
|
6
vendor/vendor.json
vendored
6
vendor/vendor.json
vendored
|
@ -9,10 +9,10 @@
|
||||||
"revisionTime": "2018-04-21T01:08:19Z"
|
"revisionTime": "2018-04-21T01:08:19Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "WMD6+Qh2+5hd9uiq910pF/Ihylw=",
|
"checksumSHA1": "LnxY/6xD4h9dCCJ5nxKEfZZs1Vk=",
|
||||||
"path": "code.gitea.io/sdk/gitea",
|
"path": "code.gitea.io/sdk/gitea",
|
||||||
"revision": "1c8d12f79a51605ed91587aa6b86cf38fc0f987f",
|
"revision": "7fa627fa5d67d18c39d6dd3c6c4db836916bf234",
|
||||||
"revisionTime": "2018-05-01T11:15:19Z"
|
"revisionTime": "2018-05-10T12:54:05Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "bOODD4Gbw3GfcuQPU2dI40crxxk=",
|
"checksumSHA1": "bOODD4Gbw3GfcuQPU2dI40crxxk=",
|
||||||
|
|
Loading…
Reference in New Issue
Block a user