mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 16:40:24 +08:00 
			
		
		
		
	Webhook for Pull Request approval/rejection (#5027)
This commit is contained in:
		
				
					committed by
					
						
						techknowlogick
					
				
			
			
				
	
			
			
			
						parent
						
							8bb0a6f425
						
					
				
				
					commit
					945804f800
				
			@@ -9,10 +9,11 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	"code.gitea.io/gitea/modules/log"
 | 
						"code.gitea.io/gitea/modules/log"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/util"
 | 
						"code.gitea.io/gitea/modules/util"
 | 
				
			||||||
	"github.com/go-xorm/core"
 | 
						api "code.gitea.io/sdk/gitea"
 | 
				
			||||||
	"github.com/go-xorm/xorm"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/go-xorm/builder"
 | 
						"github.com/go-xorm/builder"
 | 
				
			||||||
 | 
						"github.com/go-xorm/core"
 | 
				
			||||||
 | 
						"github.com/go-xorm/xorm"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ReviewType defines the sort of feedback a review gives
 | 
					// ReviewType defines the sort of feedback a review gives
 | 
				
			||||||
@@ -233,6 +234,43 @@ func createReview(e Engine, opts CreateReviewOptions) (*Review, error) {
 | 
				
			|||||||
	if _, err := e.Insert(review); err != nil {
 | 
						if _, err := e.Insert(review); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var reviewHookType HookEventType
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch opts.Type {
 | 
				
			||||||
 | 
						case ReviewTypeApprove:
 | 
				
			||||||
 | 
							reviewHookType = HookEventPullRequestApproved
 | 
				
			||||||
 | 
						case ReviewTypeComment:
 | 
				
			||||||
 | 
							reviewHookType = HookEventPullRequestComment
 | 
				
			||||||
 | 
						case ReviewTypeReject:
 | 
				
			||||||
 | 
							reviewHookType = HookEventPullRequestRejected
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							// unsupported review webhook type here
 | 
				
			||||||
 | 
							return review, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pr := opts.Issue.PullRequest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := pr.LoadIssue(); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mode, err := AccessLevel(opts.Issue.Poster, opts.Issue.Repo)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := PrepareWebhooks(opts.Issue.Repo, reviewHookType, &api.PullRequestPayload{
 | 
				
			||||||
 | 
							Action:      api.HookIssueSynchronized,
 | 
				
			||||||
 | 
							Index:       opts.Issue.Index,
 | 
				
			||||||
 | 
							PullRequest: pr.APIFormat(),
 | 
				
			||||||
 | 
							Repository:  opts.Issue.Repo.APIFormat(mode),
 | 
				
			||||||
 | 
							Sender:      opts.Reviewer.APIFormat(),
 | 
				
			||||||
 | 
						}); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						go HookQueue.Add(opts.Issue.Repo.ID)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return review, nil
 | 
						return review, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -285,10 +323,10 @@ type PullReviewersWithType struct {
 | 
				
			|||||||
func GetReviewersByPullID(pullID int64) (issueReviewers []*PullReviewersWithType, err error) {
 | 
					func GetReviewersByPullID(pullID int64) (issueReviewers []*PullReviewersWithType, err error) {
 | 
				
			||||||
	irs := []*PullReviewersWithType{}
 | 
						irs := []*PullReviewersWithType{}
 | 
				
			||||||
	if x.Dialect().DBType() == core.MSSQL {
 | 
						if x.Dialect().DBType() == core.MSSQL {
 | 
				
			||||||
		err = x.SQL(`SELECT [user].*, review.type, review.review_updated_unix FROM 
 | 
							err = x.SQL(`SELECT [user].*, review.type, review.review_updated_unix FROM
 | 
				
			||||||
(SELECT review.id, review.type, review.reviewer_id, max(review.updated_unix) as review_updated_unix 
 | 
					(SELECT review.id, review.type, review.reviewer_id, max(review.updated_unix) as review_updated_unix
 | 
				
			||||||
FROM review WHERE review.issue_id=? AND (review.type = ? OR review.type = ?) 
 | 
					FROM review WHERE review.issue_id=? AND (review.type = ? OR review.type = ?)
 | 
				
			||||||
GROUP BY review.id, review.type, review.reviewer_id) as review 
 | 
					GROUP BY review.id, review.type, review.reviewer_id) as review
 | 
				
			||||||
INNER JOIN [user] ON review.reviewer_id = [user].id ORDER BY review_updated_unix DESC`,
 | 
					INNER JOIN [user] ON review.reviewer_id = [user].id ORDER BY review_updated_unix DESC`,
 | 
				
			||||||
			pullID, ReviewTypeApprove, ReviewTypeReject).
 | 
								pullID, ReviewTypeApprove, ReviewTypeReject).
 | 
				
			||||||
			Find(&irs)
 | 
								Find(&irs)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,7 +19,6 @@ import (
 | 
				
			|||||||
	"code.gitea.io/gitea/modules/sync"
 | 
						"code.gitea.io/gitea/modules/sync"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/util"
 | 
						"code.gitea.io/gitea/modules/util"
 | 
				
			||||||
	api "code.gitea.io/sdk/gitea"
 | 
						api "code.gitea.io/sdk/gitea"
 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/Unknwon/com"
 | 
						"github.com/Unknwon/com"
 | 
				
			||||||
	gouuid "github.com/satori/go.uuid"
 | 
						gouuid "github.com/satori/go.uuid"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -425,15 +424,18 @@ type HookEventType string
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Types of hook events
 | 
					// Types of hook events
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	HookEventCreate       HookEventType = "create"
 | 
						HookEventCreate              HookEventType = "create"
 | 
				
			||||||
	HookEventDelete       HookEventType = "delete"
 | 
						HookEventDelete              HookEventType = "delete"
 | 
				
			||||||
	HookEventFork         HookEventType = "fork"
 | 
						HookEventFork                HookEventType = "fork"
 | 
				
			||||||
	HookEventPush         HookEventType = "push"
 | 
						HookEventPush                HookEventType = "push"
 | 
				
			||||||
	HookEventIssues       HookEventType = "issues"
 | 
						HookEventIssues              HookEventType = "issues"
 | 
				
			||||||
	HookEventIssueComment HookEventType = "issue_comment"
 | 
						HookEventIssueComment        HookEventType = "issue_comment"
 | 
				
			||||||
	HookEventPullRequest  HookEventType = "pull_request"
 | 
						HookEventPullRequest         HookEventType = "pull_request"
 | 
				
			||||||
	HookEventRepository   HookEventType = "repository"
 | 
						HookEventRepository          HookEventType = "repository"
 | 
				
			||||||
	HookEventRelease      HookEventType = "release"
 | 
						HookEventRelease             HookEventType = "release"
 | 
				
			||||||
 | 
						HookEventPullRequestApproved HookEventType = "pull_request_approved"
 | 
				
			||||||
 | 
						HookEventPullRequestRejected HookEventType = "pull_request_rejected"
 | 
				
			||||||
 | 
						HookEventPullRequestComment  HookEventType = "pull_request_comment"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// HookRequest represents hook task request information.
 | 
					// HookRequest represents hook task request information.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,7 +11,6 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	"code.gitea.io/git"
 | 
						"code.gitea.io/git"
 | 
				
			||||||
	api "code.gitea.io/sdk/gitea"
 | 
						api "code.gitea.io/sdk/gitea"
 | 
				
			||||||
 | 
					 | 
				
			||||||
	dingtalk "github.com/lunny/dingtalk_webhook"
 | 
						dingtalk "github.com/lunny/dingtalk_webhook"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -271,6 +270,32 @@ func getDingtalkPullRequestPayload(p *api.PullRequestPayload) (*DingtalkPayload,
 | 
				
			|||||||
	}, nil
 | 
						}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getDingtalkPullRequestApprovalPayload(p *api.PullRequestPayload, event HookEventType) (*DingtalkPayload, error) {
 | 
				
			||||||
 | 
						var text, title string
 | 
				
			||||||
 | 
						switch p.Action {
 | 
				
			||||||
 | 
						case api.HookIssueSynchronized:
 | 
				
			||||||
 | 
							action, err := parseHookPullRequestEventType(event)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							title = fmt.Sprintf("[%s] Pull request review %s : #%d %s", p.Repository.FullName, action, p.Index, p.PullRequest.Title)
 | 
				
			||||||
 | 
							text = p.PullRequest.Body
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &DingtalkPayload{
 | 
				
			||||||
 | 
							MsgType: "actionCard",
 | 
				
			||||||
 | 
							ActionCard: dingtalk.ActionCard{
 | 
				
			||||||
 | 
								Text:        title + "\r\n\r\n" + text,
 | 
				
			||||||
 | 
								Title:       title,
 | 
				
			||||||
 | 
								HideAvatar:  "0",
 | 
				
			||||||
 | 
								SingleTitle: "view pull request",
 | 
				
			||||||
 | 
								SingleURL:   p.PullRequest.HTMLURL,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getDingtalkRepositoryPayload(p *api.RepositoryPayload) (*DingtalkPayload, error) {
 | 
					func getDingtalkRepositoryPayload(p *api.RepositoryPayload) (*DingtalkPayload, error) {
 | 
				
			||||||
	var title, url string
 | 
						var title, url string
 | 
				
			||||||
	switch p.Action {
 | 
						switch p.Action {
 | 
				
			||||||
@@ -369,6 +394,8 @@ func GetDingtalkPayload(p api.Payloader, event HookEventType, meta string) (*Din
 | 
				
			|||||||
		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 HookEventPullRequestApproved, HookEventPullRequestRejected, HookEventPullRequestComment:
 | 
				
			||||||
 | 
							return getDingtalkPullRequestApprovalPayload(p.(*api.PullRequestPayload), event)
 | 
				
			||||||
	case HookEventRepository:
 | 
						case HookEventRepository:
 | 
				
			||||||
		return getDingtalkRepositoryPayload(p.(*api.RepositoryPayload))
 | 
							return getDingtalkRepositoryPayload(p.(*api.RepositoryPayload))
 | 
				
			||||||
	case HookEventRelease:
 | 
						case HookEventRelease:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -400,6 +400,40 @@ func getDiscordPullRequestPayload(p *api.PullRequestPayload, meta *DiscordMeta)
 | 
				
			|||||||
	}, nil
 | 
						}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getDiscordPullRequestApprovalPayload(p *api.PullRequestPayload, meta *DiscordMeta, event HookEventType) (*DiscordPayload, error) {
 | 
				
			||||||
 | 
						var text, title string
 | 
				
			||||||
 | 
						var color int
 | 
				
			||||||
 | 
						switch p.Action {
 | 
				
			||||||
 | 
						case api.HookIssueSynchronized:
 | 
				
			||||||
 | 
							action, err := parseHookPullRequestEventType(event)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							title = fmt.Sprintf("[%s] Pull request review %s: #%d %s", p.Repository.FullName, action, p.Index, p.PullRequest.Title)
 | 
				
			||||||
 | 
							text = p.PullRequest.Body
 | 
				
			||||||
 | 
							color = warnColor
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &DiscordPayload{
 | 
				
			||||||
 | 
							Username:  meta.Username,
 | 
				
			||||||
 | 
							AvatarURL: meta.IconURL,
 | 
				
			||||||
 | 
							Embeds: []DiscordEmbed{
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									Title:       title,
 | 
				
			||||||
 | 
									Description: text,
 | 
				
			||||||
 | 
									URL:         p.PullRequest.HTMLURL,
 | 
				
			||||||
 | 
									Color:       color,
 | 
				
			||||||
 | 
									Author: DiscordEmbedAuthor{
 | 
				
			||||||
 | 
										Name:    p.Sender.UserName,
 | 
				
			||||||
 | 
										URL:     setting.AppURL + p.Sender.UserName,
 | 
				
			||||||
 | 
										IconURL: p.Sender.AvatarURL,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getDiscordRepositoryPayload(p *api.RepositoryPayload, meta *DiscordMeta) (*DiscordPayload, error) {
 | 
					func getDiscordRepositoryPayload(p *api.RepositoryPayload, meta *DiscordMeta) (*DiscordPayload, error) {
 | 
				
			||||||
	var title, url string
 | 
						var title, url string
 | 
				
			||||||
	var color int
 | 
						var color int
 | 
				
			||||||
@@ -492,6 +526,8 @@ func GetDiscordPayload(p api.Payloader, event HookEventType, meta string) (*Disc
 | 
				
			|||||||
		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 HookEventPullRequestRejected, HookEventPullRequestApproved, HookEventPullRequestComment:
 | 
				
			||||||
 | 
							return getDiscordPullRequestApprovalPayload(p.(*api.PullRequestPayload), discord, event)
 | 
				
			||||||
	case HookEventRepository:
 | 
						case HookEventRepository:
 | 
				
			||||||
		return getDiscordRepositoryPayload(p.(*api.RepositoryPayload), discord)
 | 
							return getDiscordRepositoryPayload(p.(*api.RepositoryPayload), discord)
 | 
				
			||||||
	case HookEventRelease:
 | 
						case HookEventRelease:
 | 
				
			||||||
@@ -500,3 +536,19 @@ func GetDiscordPayload(p api.Payloader, event HookEventType, meta string) (*Disc
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	return s, nil
 | 
						return s, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func parseHookPullRequestEventType(event HookEventType) (string, error) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch event {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case HookEventPullRequestApproved:
 | 
				
			||||||
 | 
							return "approved", nil
 | 
				
			||||||
 | 
						case HookEventPullRequestRejected:
 | 
				
			||||||
 | 
							return "rejected", nil
 | 
				
			||||||
 | 
						case HookEventPullRequestComment:
 | 
				
			||||||
 | 
							return "comment", nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return "", errors.New("unknown event type")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,9 +11,8 @@ import (
 | 
				
			|||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"code.gitea.io/git"
 | 
						"code.gitea.io/git"
 | 
				
			||||||
	api "code.gitea.io/sdk/gitea"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"code.gitea.io/gitea/modules/setting"
 | 
						"code.gitea.io/gitea/modules/setting"
 | 
				
			||||||
 | 
						api "code.gitea.io/sdk/gitea"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SlackMeta contains the slack metadata
 | 
					// SlackMeta contains the slack metadata
 | 
				
			||||||
@@ -328,6 +327,34 @@ func getSlackPullRequestPayload(p *api.PullRequestPayload, slack *SlackMeta) (*S
 | 
				
			|||||||
	}, nil
 | 
						}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getSlackPullRequestApprovalPayload(p *api.PullRequestPayload, slack *SlackMeta, event HookEventType) (*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.PullRequest.Title))
 | 
				
			||||||
 | 
						var text, title, attachmentText string
 | 
				
			||||||
 | 
						switch p.Action {
 | 
				
			||||||
 | 
						case api.HookIssueSynchronized:
 | 
				
			||||||
 | 
							action, err := parseHookPullRequestEventType(event)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							text = fmt.Sprintf("[%s] Pull request review %s : %s by %s", p.Repository.FullName, action, 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 getSlackRepositoryPayload(p *api.RepositoryPayload, slack *SlackMeta) (*SlackPayload, error) {
 | 
					func getSlackRepositoryPayload(p *api.RepositoryPayload, slack *SlackMeta) (*SlackPayload, error) {
 | 
				
			||||||
	senderLink := SlackLinkFormatter(setting.AppURL+p.Sender.UserName, p.Sender.UserName)
 | 
						senderLink := SlackLinkFormatter(setting.AppURL+p.Sender.UserName, p.Sender.UserName)
 | 
				
			||||||
	var text, title, attachmentText string
 | 
						var text, title, attachmentText string
 | 
				
			||||||
@@ -376,6 +403,8 @@ func GetSlackPayload(p api.Payloader, event HookEventType, meta string) (*SlackP
 | 
				
			|||||||
		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 HookEventPullRequestRejected, HookEventPullRequestApproved, HookEventPullRequestComment:
 | 
				
			||||||
 | 
							return getSlackPullRequestApprovalPayload(p.(*api.PullRequestPayload), slack, event)
 | 
				
			||||||
	case HookEventRepository:
 | 
						case HookEventRepository:
 | 
				
			||||||
		return getSlackRepositoryPayload(p.(*api.RepositoryPayload), slack)
 | 
							return getSlackRepositoryPayload(p.(*api.RepositoryPayload), slack)
 | 
				
			||||||
	case HookEventRelease:
 | 
						case HookEventRelease:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1101,7 +1101,7 @@ settings.event_issue_comment_desc = Issue comment created, edited, or deleted.
 | 
				
			|||||||
settings.event_release = Release
 | 
					settings.event_release = Release
 | 
				
			||||||
settings.event_release_desc = Release published, updated or deleted in a repository.
 | 
					settings.event_release_desc = Release published, updated or deleted in a repository.
 | 
				
			||||||
settings.event_pull_request = Pull Request
 | 
					settings.event_pull_request = 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, approved, rejected, review comment, assigned, unassigned, label updated, label cleared or synchronized.
 | 
				
			||||||
settings.event_push = Push
 | 
					settings.event_push = Push
 | 
				
			||||||
settings.event_push_desc = Git push to a repository.
 | 
					settings.event_push_desc = Git push to a repository.
 | 
				
			||||||
settings.event_repository = Repository
 | 
					settings.event_repository = Repository
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user