mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-11-26 15:25:43 +03:00
new create webhook event
This commit is contained in:
parent
a541ca16b6
commit
f509c59ac1
16 changed files with 449 additions and 306 deletions
|
@ -531,6 +531,12 @@ settings.content_type = Content Type
|
||||||
settings.secret = Secret
|
settings.secret = Secret
|
||||||
settings.event_desc = Upon which events should this webhook be triggered?
|
settings.event_desc = Upon which events should this webhook be triggered?
|
||||||
settings.event_push_only = Just the <code>push</code> event.
|
settings.event_push_only = Just the <code>push</code> event.
|
||||||
|
settings.event_send_everything = I need <strong>everything</strong>.
|
||||||
|
settings.event_choose = Let me choose what I need.
|
||||||
|
settings.event_create = Create
|
||||||
|
settings.event_create_desc = Branch, or tag created
|
||||||
|
settings.event_push = Push
|
||||||
|
settings.event_push_desc = Git push to a repository
|
||||||
settings.active = Active
|
settings.active = Active
|
||||||
settings.active_helper = Details regarding the event which triggered the hook will be delivered as well.
|
settings.active_helper = Details regarding the event which triggered the hook will be delivered as well.
|
||||||
settings.add_hook_success = New webhook has been added.
|
settings.add_hook_success = New webhook has been added.
|
||||||
|
|
189
models/action.go
189
models/action.go
|
@ -16,6 +16,8 @@ import (
|
||||||
|
|
||||||
"github.com/go-xorm/xorm"
|
"github.com/go-xorm/xorm"
|
||||||
|
|
||||||
|
api "github.com/gogits/go-gogs-client"
|
||||||
|
|
||||||
"github.com/gogits/gogs/modules/base"
|
"github.com/gogits/gogs/modules/base"
|
||||||
"github.com/gogits/gogs/modules/git"
|
"github.com/gogits/gogs/modules/git"
|
||||||
"github.com/gogits/gogs/modules/log"
|
"github.com/gogits/gogs/modules/log"
|
||||||
|
@ -290,20 +292,50 @@ func updateIssuesCommit(u *User, repo *Repository, repoUserName, repoName string
|
||||||
}
|
}
|
||||||
|
|
||||||
// CommitRepoAction adds new action for committing repository.
|
// CommitRepoAction adds new action for committing repository.
|
||||||
func CommitRepoAction(userID, repoUserID int64, userName, actEmail string,
|
func CommitRepoAction(
|
||||||
repoID int64, repoUserName, repoName string, refFullName string, commit *base.PushCommits, oldCommitID string, newCommitID string) error {
|
userID, repoUserID int64,
|
||||||
|
userName, actEmail string,
|
||||||
|
repoID int64,
|
||||||
|
repoUserName, repoName string,
|
||||||
|
refFullName string,
|
||||||
|
commit *base.PushCommits,
|
||||||
|
oldCommitID string, newCommitID string) error {
|
||||||
|
|
||||||
|
u, err := GetUserByID(userID)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("GetUserByID: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
repo, err := GetRepositoryByName(repoUserID, repoName)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("GetRepositoryByName: %v", err)
|
||||||
|
} else if err = repo.GetOwner(); err != nil {
|
||||||
|
return fmt.Errorf("GetOwner: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
isNewBranch := false
|
||||||
opType := COMMIT_REPO
|
opType := COMMIT_REPO
|
||||||
// Check it's tag push or branch.
|
// Check it's tag push or branch.
|
||||||
if strings.HasPrefix(refFullName, "refs/tags/") {
|
if strings.HasPrefix(refFullName, "refs/tags/") {
|
||||||
opType = PUSH_TAG
|
opType = PUSH_TAG
|
||||||
commit = &base.PushCommits{}
|
commit = &base.PushCommits{}
|
||||||
}
|
} else {
|
||||||
|
|
||||||
repoLink := fmt.Sprintf("%s%s/%s", setting.AppUrl, repoUserName, repoName)
|
|
||||||
// if not the first commit, set the compareUrl
|
// if not the first commit, set the compareUrl
|
||||||
if !strings.HasPrefix(oldCommitID, "0000000") {
|
if !strings.HasPrefix(oldCommitID, "0000000") {
|
||||||
commit.CompareUrl = fmt.Sprintf("%s/%s/compare/%s...%s", repoUserName, repoName, oldCommitID, newCommitID)
|
commit.CompareUrl = fmt.Sprintf("%s/%s/compare/%s...%s", repoUserName, repoName, oldCommitID, newCommitID)
|
||||||
|
} else {
|
||||||
|
isNewBranch = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change repository bare status and update last updated time.
|
||||||
|
repo.IsBare = false
|
||||||
|
if err = UpdateRepository(repo, false); err != nil {
|
||||||
|
return fmt.Errorf("UpdateRepository: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = updateIssuesCommit(u, repo, repoUserName, repoName, commit.Commits); err != nil {
|
||||||
|
log.Debug("updateIssuesCommit: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bs, err := json.Marshal(commit)
|
bs, err := json.Marshal(commit)
|
||||||
|
@ -313,26 +345,6 @@ func CommitRepoAction(userID, repoUserID int64, userName, actEmail string,
|
||||||
|
|
||||||
refName := git.RefEndName(refFullName)
|
refName := git.RefEndName(refFullName)
|
||||||
|
|
||||||
// Change repository bare status and update last updated time.
|
|
||||||
repo, err := GetRepositoryByName(repoUserID, repoName)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("GetRepositoryByName: %v", err)
|
|
||||||
}
|
|
||||||
repo.IsBare = false
|
|
||||||
if err = UpdateRepository(repo, false); err != nil {
|
|
||||||
return fmt.Errorf("UpdateRepository: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
u, err := GetUserByID(userID)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("GetUserByID: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = updateIssuesCommit(u, repo, repoUserName, repoName, commit.Commits)
|
|
||||||
if err != nil {
|
|
||||||
log.Debug("updateIssuesCommit: ", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = NotifyWatchers(&Action{
|
if err = NotifyWatchers(&Action{
|
||||||
ActUserID: u.Id,
|
ActUserID: u.Id,
|
||||||
ActUserName: userName,
|
ActUserName: userName,
|
||||||
|
@ -345,32 +357,24 @@ func CommitRepoAction(userID, repoUserID int64, userName, actEmail string,
|
||||||
RefName: refName,
|
RefName: refName,
|
||||||
IsPrivate: repo.IsPrivate,
|
IsPrivate: repo.IsPrivate,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return errors.New("NotifyWatchers: " + err.Error())
|
return fmt.Errorf("NotifyWatchers: %v", err)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// New push event hook.
|
repoLink := fmt.Sprintf("%s%s/%s", setting.AppUrl, repoUserName, repoName)
|
||||||
if err := repo.GetOwner(); err != nil {
|
payloadRepo := &api.PayloadRepo{
|
||||||
return errors.New("GetOwner: " + err.Error())
|
ID: repo.ID,
|
||||||
}
|
Name: repo.LowerName,
|
||||||
|
URL: repoLink,
|
||||||
ws, err := GetActiveWebhooksByRepoId(repo.ID)
|
Description: repo.Description,
|
||||||
if err != nil {
|
Website: repo.Website,
|
||||||
return errors.New("GetActiveWebhooksByRepoId: " + err.Error())
|
Watchers: repo.NumWatches,
|
||||||
}
|
Owner: &api.PayloadAuthor{
|
||||||
|
Name: repo.Owner.DisplayName(),
|
||||||
// check if repo belongs to org and append additional webhooks
|
Email: repo.Owner.Email,
|
||||||
if repo.Owner.IsOrganization() {
|
UserName: repo.Owner.Name,
|
||||||
// get hooks for org
|
},
|
||||||
orgws, err := GetActiveWebhooksByOrgId(repo.OwnerID)
|
Private: repo.IsPrivate,
|
||||||
if err != nil {
|
|
||||||
return errors.New("GetActiveWebhooksByOrgId: " + err.Error())
|
|
||||||
}
|
|
||||||
ws = append(ws, orgws...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(ws) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pusher_email, pusher_name := "", ""
|
pusher_email, pusher_name := "", ""
|
||||||
|
@ -379,83 +383,66 @@ func CommitRepoAction(userID, repoUserID int64, userName, actEmail string,
|
||||||
pusher_email = pusher.Email
|
pusher_email = pusher.Email
|
||||||
pusher_name = pusher.DisplayName()
|
pusher_name = pusher.DisplayName()
|
||||||
}
|
}
|
||||||
|
payloadSender := &api.PayloadUser{
|
||||||
|
UserName: pusher.Name,
|
||||||
|
ID: pusher.Id,
|
||||||
|
AvatarUrl: setting.AppUrl + pusher.RelAvatarLink(),
|
||||||
|
}
|
||||||
|
|
||||||
commits := make([]*PayloadCommit, len(commit.Commits))
|
switch opType {
|
||||||
|
case COMMIT_REPO: // Push
|
||||||
|
commits := make([]*api.PayloadCommit, len(commit.Commits))
|
||||||
for i, cmt := range commit.Commits {
|
for i, cmt := range commit.Commits {
|
||||||
author_username := ""
|
author_username := ""
|
||||||
author, err := GetUserByEmail(cmt.AuthorEmail)
|
author, err := GetUserByEmail(cmt.AuthorEmail)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
author_username = author.Name
|
author_username = author.Name
|
||||||
}
|
}
|
||||||
commits[i] = &PayloadCommit{
|
commits[i] = &api.PayloadCommit{
|
||||||
Id: cmt.Sha1,
|
ID: cmt.Sha1,
|
||||||
Message: cmt.Message,
|
Message: cmt.Message,
|
||||||
Url: fmt.Sprintf("%s/commit/%s", repoLink, cmt.Sha1),
|
URL: fmt.Sprintf("%s/commit/%s", repoLink, cmt.Sha1),
|
||||||
Author: &PayloadAuthor{
|
Author: &api.PayloadAuthor{
|
||||||
Name: cmt.AuthorName,
|
Name: cmt.AuthorName,
|
||||||
Email: cmt.AuthorEmail,
|
Email: cmt.AuthorEmail,
|
||||||
UserName: author_username,
|
UserName: author_username,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p := &Payload{
|
p := &api.PushPayload{
|
||||||
Ref: refFullName,
|
Ref: refFullName,
|
||||||
|
Before: oldCommitID,
|
||||||
|
After: newCommitID,
|
||||||
|
CompareUrl: setting.AppUrl + commit.CompareUrl,
|
||||||
Commits: commits,
|
Commits: commits,
|
||||||
Repo: &PayloadRepo{
|
Repo: payloadRepo,
|
||||||
Id: repo.ID,
|
Pusher: &api.PayloadAuthor{
|
||||||
Name: repo.LowerName,
|
|
||||||
Url: repoLink,
|
|
||||||
Description: repo.Description,
|
|
||||||
Website: repo.Website,
|
|
||||||
Watchers: repo.NumWatches,
|
|
||||||
Owner: &PayloadAuthor{
|
|
||||||
Name: repo.Owner.DisplayName(),
|
|
||||||
Email: repo.Owner.Email,
|
|
||||||
UserName: repo.Owner.Name,
|
|
||||||
},
|
|
||||||
Private: repo.IsPrivate,
|
|
||||||
},
|
|
||||||
Pusher: &PayloadAuthor{
|
|
||||||
Name: pusher_name,
|
Name: pusher_name,
|
||||||
Email: pusher_email,
|
Email: pusher_email,
|
||||||
UserName: userName,
|
UserName: userName,
|
||||||
},
|
},
|
||||||
Before: oldCommitID,
|
Sender: payloadSender,
|
||||||
After: newCommitID,
|
}
|
||||||
CompareUrl: setting.AppUrl + commit.CompareUrl,
|
if err = PrepareWebhooks(repo, HOOK_EVENT_PUSH, p); err != nil {
|
||||||
|
return fmt.Errorf("PrepareWebhooks: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, w := range ws {
|
if isNewBranch {
|
||||||
w.GetEvent()
|
return PrepareWebhooks(repo, HOOK_EVENT_CREATE, &api.CreatePayload{
|
||||||
if !w.HasPushEvent() {
|
Ref: refName,
|
||||||
continue
|
RefType: "branch",
|
||||||
|
Repo: payloadRepo,
|
||||||
|
Sender: payloadSender,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
var payload BasePayload
|
case PUSH_TAG: // Create
|
||||||
switch w.HookTaskType {
|
return PrepareWebhooks(repo, HOOK_EVENT_CREATE, &api.CreatePayload{
|
||||||
case SLACK:
|
Ref: refName,
|
||||||
s, err := GetSlackPayload(p, w.Meta)
|
RefType: "tag",
|
||||||
if err != nil {
|
Repo: payloadRepo,
|
||||||
return errors.New("action.GetSlackPayload: " + err.Error())
|
Sender: payloadSender,
|
||||||
}
|
})
|
||||||
payload = s
|
|
||||||
default:
|
|
||||||
payload = p
|
|
||||||
p.Secret = w.Secret
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = CreateHookTask(&HookTask{
|
|
||||||
RepoID: repo.ID,
|
|
||||||
HookID: w.ID,
|
|
||||||
Type: w.HookTaskType,
|
|
||||||
URL: w.URL,
|
|
||||||
BasePayload: payload,
|
|
||||||
ContentType: w.ContentType,
|
|
||||||
EventType: HOOK_EVENT_PUSH,
|
|
||||||
IsSSL: w.IsSSL,
|
|
||||||
}); err != nil {
|
|
||||||
return fmt.Errorf("CreateHookTask: %v", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -122,9 +122,8 @@ func (u *User) HomeLink() string {
|
||||||
return setting.AppSubUrl + "/" + u.Name
|
return setting.AppSubUrl + "/" + u.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
// AvatarLink returns user gravatar link.
|
func (u *User) RelAvatarLink() string {
|
||||||
func (u *User) AvatarLink() string {
|
defaultImgUrl := "/img/avatar_default.jpg"
|
||||||
defaultImgUrl := setting.AppSubUrl + "/img/avatar_default.jpg"
|
|
||||||
if u.Id == -1 {
|
if u.Id == -1 {
|
||||||
return defaultImgUrl
|
return defaultImgUrl
|
||||||
}
|
}
|
||||||
|
@ -135,7 +134,7 @@ func (u *User) AvatarLink() string {
|
||||||
if !com.IsExist(imgPath) {
|
if !com.IsExist(imgPath) {
|
||||||
return defaultImgUrl
|
return defaultImgUrl
|
||||||
}
|
}
|
||||||
return setting.AppSubUrl + "/avatars/" + com.ToStr(u.Id)
|
return "/avatars/" + com.ToStr(u.Id)
|
||||||
case setting.DisableGravatar, setting.OfflineMode:
|
case setting.DisableGravatar, setting.OfflineMode:
|
||||||
if !com.IsExist(imgPath) {
|
if !com.IsExist(imgPath) {
|
||||||
img, err := avatar.RandomImage([]byte(u.Email))
|
img, err := avatar.RandomImage([]byte(u.Email))
|
||||||
|
@ -161,13 +160,22 @@ func (u *User) AvatarLink() string {
|
||||||
log.Info("New random avatar created: %d", u.Id)
|
log.Info("New random avatar created: %d", u.Id)
|
||||||
}
|
}
|
||||||
|
|
||||||
return setting.AppSubUrl + "/avatars/" + com.ToStr(u.Id)
|
return "/avatars/" + com.ToStr(u.Id)
|
||||||
case setting.Service.EnableCacheAvatar:
|
case setting.Service.EnableCacheAvatar:
|
||||||
return setting.AppSubUrl + "/avatar/" + u.Avatar
|
return "/avatar/" + u.Avatar
|
||||||
}
|
}
|
||||||
return setting.GravatarSource + u.Avatar
|
return setting.GravatarSource + u.Avatar
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AvatarLink returns user gravatar link.
|
||||||
|
func (u *User) AvatarLink() string {
|
||||||
|
link := u.RelAvatarLink()
|
||||||
|
if link[0] == '/' {
|
||||||
|
return setting.AppSubUrl + link
|
||||||
|
}
|
||||||
|
return link
|
||||||
|
}
|
||||||
|
|
||||||
// NewGitSig generates and returns the signature of given user.
|
// NewGitSig generates and returns the signature of given user.
|
||||||
func (u *User) NewGitSig() *git.Signature {
|
func (u *User) NewGitSig() *git.Signature {
|
||||||
return &git.Signature{
|
return &git.Signature{
|
||||||
|
|
|
@ -15,6 +15,8 @@ import (
|
||||||
|
|
||||||
"github.com/go-xorm/xorm"
|
"github.com/go-xorm/xorm"
|
||||||
|
|
||||||
|
api "github.com/gogits/go-gogs-client"
|
||||||
|
|
||||||
"github.com/gogits/gogs/modules/httplib"
|
"github.com/gogits/gogs/modules/httplib"
|
||||||
"github.com/gogits/gogs/modules/log"
|
"github.com/gogits/gogs/modules/log"
|
||||||
"github.com/gogits/gogs/modules/setting"
|
"github.com/gogits/gogs/modules/setting"
|
||||||
|
@ -54,9 +56,18 @@ func IsValidHookContentType(name string) bool {
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type HookEvents struct {
|
||||||
|
Create bool `json:"create"`
|
||||||
|
Push bool `json:"push"`
|
||||||
|
}
|
||||||
|
|
||||||
// HookEvent represents events that will delivery hook.
|
// HookEvent represents events that will delivery hook.
|
||||||
type HookEvent struct {
|
type HookEvent struct {
|
||||||
PushOnly bool `json:"push_only"`
|
PushOnly bool `json:"push_only"`
|
||||||
|
SendEverything bool `json:"send_everything"`
|
||||||
|
ChooseEvents bool `json:"choose_events"`
|
||||||
|
|
||||||
|
HookEvents `json:"events"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type HookStatus int
|
type HookStatus int
|
||||||
|
@ -94,8 +105,8 @@ func (w *Webhook) GetEvent() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Webhook) GetSlackHook() *Slack {
|
func (w *Webhook) GetSlackHook() *SlackMeta {
|
||||||
s := &Slack{}
|
s := &SlackMeta{}
|
||||||
if err := json.Unmarshal([]byte(w.Meta), s); err != nil {
|
if err := json.Unmarshal([]byte(w.Meta), s); err != nil {
|
||||||
log.Error(4, "webhook.GetSlackHook(%d): %v", w.ID, err)
|
log.Error(4, "webhook.GetSlackHook(%d): %v", w.ID, err)
|
||||||
}
|
}
|
||||||
|
@ -114,12 +125,16 @@ func (w *Webhook) UpdateEvent() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HasCreateEvent returns true if hook enabled create event.
|
||||||
|
func (w *Webhook) HasCreateEvent() bool {
|
||||||
|
return w.SendEverything ||
|
||||||
|
(w.ChooseEvents && w.HookEvents.Create)
|
||||||
|
}
|
||||||
|
|
||||||
// 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 {
|
||||||
if w.PushOnly {
|
return w.PushOnly || w.SendEverything ||
|
||||||
return true
|
(w.ChooseEvents && w.HookEvents.Push)
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateWebhook creates a new web hook.
|
// CreateWebhook creates a new web hook.
|
||||||
|
@ -140,9 +155,9 @@ func GetWebhookByID(id int64) (*Webhook, error) {
|
||||||
return w, nil
|
return w, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetActiveWebhooksByRepoId returns all active webhooks of repository.
|
// GetActiveWebhooksByRepoID returns all active webhooks of repository.
|
||||||
func GetActiveWebhooksByRepoId(repoId int64) (ws []*Webhook, err error) {
|
func GetActiveWebhooksByRepoID(repoID int64) (ws []*Webhook, err error) {
|
||||||
err = x.Where("repo_id=?", repoId).And("is_active=?", true).Find(&ws)
|
err = x.Where("repo_id=?", repoID).And("is_active=?", true).Find(&ws)
|
||||||
return ws, err
|
return ws, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,9 +196,9 @@ func GetWebhooksByOrgId(orgID int64) (ws []*Webhook, err error) {
|
||||||
return ws, err
|
return ws, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetActiveWebhooksByOrgId returns all active webhooks for an organization.
|
// GetActiveWebhooksByOrgID returns all active webhooks for an organization.
|
||||||
func GetActiveWebhooksByOrgId(orgId int64) (ws []*Webhook, err error) {
|
func GetActiveWebhooksByOrgID(orgID int64) (ws []*Webhook, err error) {
|
||||||
err = x.Where("org_id=?", orgId).And("is_active=?", true).Find(&ws)
|
err = x.Where("org_id=?", orgID).And("is_active=?", true).Find(&ws)
|
||||||
return ws, err
|
return ws, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,58 +245,10 @@ func IsValidHookTaskType(name string) bool {
|
||||||
type HookEventType string
|
type HookEventType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
HOOK_EVENT_CREATE HookEventType = "create"
|
||||||
HOOK_EVENT_PUSH HookEventType = "push"
|
HOOK_EVENT_PUSH HookEventType = "push"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FIXME: just use go-gogs-client structs maybe?
|
|
||||||
type PayloadAuthor struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Email string `json:"email"`
|
|
||||||
UserName string `json:"username"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type PayloadCommit struct {
|
|
||||||
Id string `json:"id"`
|
|
||||||
Message string `json:"message"`
|
|
||||||
Url string `json:"url"`
|
|
||||||
Author *PayloadAuthor `json:"author"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type PayloadRepo struct {
|
|
||||||
Id int64 `json:"id"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Url string `json:"url"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
Website string `json:"website"`
|
|
||||||
Watchers int `json:"watchers"`
|
|
||||||
Owner *PayloadAuthor `json:"owner"`
|
|
||||||
Private bool `json:"private"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type BasePayload interface {
|
|
||||||
GetJSONPayload() ([]byte, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Payload represents a payload information of hook.
|
|
||||||
type Payload struct {
|
|
||||||
Secret string `json:"secret"`
|
|
||||||
Ref string `json:"ref"`
|
|
||||||
Commits []*PayloadCommit `json:"commits"`
|
|
||||||
Repo *PayloadRepo `json:"repository"`
|
|
||||||
Pusher *PayloadAuthor `json:"pusher"`
|
|
||||||
Before string `json:"before"`
|
|
||||||
After string `json:"after"`
|
|
||||||
CompareUrl string `json:"compare_url"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p Payload) GetJSONPayload() ([]byte, error) {
|
|
||||||
data, err := json.MarshalIndent(p, "", " ")
|
|
||||||
if err != nil {
|
|
||||||
return []byte{}, err
|
|
||||||
}
|
|
||||||
return data, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// HookRequest represents hook task request information.
|
// HookRequest represents hook task request information.
|
||||||
type HookRequest struct {
|
type HookRequest struct {
|
||||||
Headers map[string]string `json:"headers"`
|
Headers map[string]string `json:"headers"`
|
||||||
|
@ -302,7 +269,7 @@ type HookTask struct {
|
||||||
UUID string
|
UUID string
|
||||||
Type HookTaskType
|
Type HookTaskType
|
||||||
URL string
|
URL string
|
||||||
BasePayload `xorm:"-"`
|
api.Payloader `xorm:"-"`
|
||||||
PayloadContent string `xorm:"TEXT"`
|
PayloadContent string `xorm:"TEXT"`
|
||||||
ContentType HookContentType
|
ContentType HookContentType
|
||||||
EventType HookEventType
|
EventType HookEventType
|
||||||
|
@ -367,13 +334,13 @@ func (t *HookTask) MarshalJSON(v interface{}) string {
|
||||||
// HookTasks returns a list of hook tasks by given conditions.
|
// HookTasks returns a list of hook tasks by given conditions.
|
||||||
func HookTasks(hookID int64, page int) ([]*HookTask, error) {
|
func HookTasks(hookID int64, page int) ([]*HookTask, error) {
|
||||||
tasks := make([]*HookTask, 0, setting.Webhook.PagingNum)
|
tasks := make([]*HookTask, 0, setting.Webhook.PagingNum)
|
||||||
return tasks, x.Limit(setting.Webhook.PagingNum, (page-1)*setting.Webhook.PagingNum).Desc("id").Find(&tasks)
|
return tasks, x.Limit(setting.Webhook.PagingNum, (page-1)*setting.Webhook.PagingNum).Where("hook_id=?", hookID).Desc("id").Find(&tasks)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateHookTask creates a new hook task,
|
// CreateHookTask creates a new hook task,
|
||||||
// it handles conversion from Payload to PayloadContent.
|
// it handles conversion from Payload to PayloadContent.
|
||||||
func CreateHookTask(t *HookTask) error {
|
func CreateHookTask(t *HookTask) error {
|
||||||
data, err := t.BasePayload.GetJSONPayload()
|
data, err := t.Payloader.JSONPayload()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -389,6 +356,71 @@ func UpdateHookTask(t *HookTask) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PrepareWebhooks adds new webhooks to task queue for given payload.
|
||||||
|
func PrepareWebhooks(repo *Repository, event HookEventType, p api.Payloader) error {
|
||||||
|
if err := repo.GetOwner(); err != nil {
|
||||||
|
return fmt.Errorf("GetOwner: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ws, err := GetActiveWebhooksByRepoID(repo.ID)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("GetActiveWebhooksByRepoID: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if repo belongs to org and append additional webhooks
|
||||||
|
if repo.Owner.IsOrganization() {
|
||||||
|
// get hooks for org
|
||||||
|
orgws, err := GetActiveWebhooksByOrgID(repo.OwnerID)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("GetActiveWebhooksByOrgID: %v", err)
|
||||||
|
}
|
||||||
|
ws = append(ws, orgws...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ws) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, w := range ws {
|
||||||
|
w.GetEvent()
|
||||||
|
|
||||||
|
switch event {
|
||||||
|
case HOOK_EVENT_CREATE:
|
||||||
|
if !w.HasCreateEvent() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
case HOOK_EVENT_PUSH:
|
||||||
|
if !w.HasPushEvent() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch w.HookTaskType {
|
||||||
|
case SLACK:
|
||||||
|
p, err = GetSlackPayload(p, event, w.Meta)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("GetSlackPayload: %v", err)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
p.SetSecret(w.Secret)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = CreateHookTask(&HookTask{
|
||||||
|
RepoID: repo.ID,
|
||||||
|
HookID: w.ID,
|
||||||
|
Type: w.HookTaskType,
|
||||||
|
URL: w.URL,
|
||||||
|
Payloader: p,
|
||||||
|
ContentType: w.ContentType,
|
||||||
|
EventType: HOOK_EVENT_PUSH,
|
||||||
|
IsSSL: w.IsSSL,
|
||||||
|
}); err != nil {
|
||||||
|
return fmt.Errorf("CreateHookTask: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type hookQueue struct {
|
type hookQueue struct {
|
||||||
// Make sure one repository only occur once in the queue.
|
// Make sure one repository only occur once in the queue.
|
||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
|
|
|
@ -9,13 +9,18 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
api "github.com/gogits/go-gogs-client"
|
||||||
|
|
||||||
|
"github.com/gogits/gogs/modules/git"
|
||||||
|
"github.com/gogits/gogs/modules/setting"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SLACK_COLOR string = "#dd4b39"
|
SLACK_COLOR string = "#dd4b39"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Slack struct {
|
type SlackMeta struct {
|
||||||
Channel string `json:"channel"`
|
Channel string `json:"channel"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +39,9 @@ type SlackAttachment struct {
|
||||||
Text string `json:"text"`
|
Text string `json:"text"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p SlackPayload) GetJSONPayload() ([]byte, error) {
|
func (p *SlackPayload) SetSecret(_ string) {}
|
||||||
|
|
||||||
|
func (p *SlackPayload) JSONPayload() ([]byte, error) {
|
||||||
data, err := json.Marshal(p)
|
data, err := json.Marshal(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []byte{}, err
|
return []byte{}, err
|
||||||
|
@ -42,63 +49,6 @@ func (p SlackPayload) GetJSONPayload() ([]byte, error) {
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetSlackPayload(p *Payload, meta string) (*SlackPayload, error) {
|
|
||||||
slack := &Slack{}
|
|
||||||
slackPayload := &SlackPayload{}
|
|
||||||
if err := json.Unmarshal([]byte(meta), &slack); err != nil {
|
|
||||||
return slackPayload, errors.New("GetSlackPayload meta json:" + err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: handle different payload types: push, new branch, delete branch etc.
|
|
||||||
// when they are added to gogs. Only handles push now
|
|
||||||
return getSlackPushPayload(p, slack)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getSlackPushPayload(p *Payload, slack *Slack) (*SlackPayload, error) {
|
|
||||||
// n new commits
|
|
||||||
refSplit := strings.Split(p.Ref, "/")
|
|
||||||
branchName := refSplit[len(refSplit)-1]
|
|
||||||
var commitString string
|
|
||||||
|
|
||||||
if len(p.Commits) == 1 {
|
|
||||||
commitString = "1 new commit"
|
|
||||||
if p.CompareUrl != "" {
|
|
||||||
commitString = SlackLinkFormatter(p.CompareUrl, commitString)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
commitString = fmt.Sprintf("%d new commits", len(p.Commits))
|
|
||||||
if p.CompareUrl != "" {
|
|
||||||
commitString = SlackLinkFormatter(p.CompareUrl, commitString)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
repoLink := SlackLinkFormatter(p.Repo.Url, p.Repo.Name)
|
|
||||||
branchLink := SlackLinkFormatter(p.Repo.Url+"/src/"+branchName, branchName)
|
|
||||||
text := fmt.Sprintf("[%s:%s] %s pushed by %s", repoLink, branchLink, commitString, p.Pusher.Name)
|
|
||||||
var attachmentText string
|
|
||||||
|
|
||||||
// for each commit, generate attachment text
|
|
||||||
for i, commit := range p.Commits {
|
|
||||||
attachmentText += fmt.Sprintf("%s: %s - %s", SlackLinkFormatter(commit.Url, commit.Id[:7]), SlackTextFormatter(commit.Message), SlackTextFormatter(commit.Author.Name))
|
|
||||||
// add linebreak to each commit but the last
|
|
||||||
if i < len(p.Commits)-1 {
|
|
||||||
attachmentText += "\n"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
slackAttachments := []SlackAttachment{{Color: SLACK_COLOR, Text: attachmentText}}
|
|
||||||
|
|
||||||
return &SlackPayload{
|
|
||||||
Channel: slack.Channel,
|
|
||||||
Text: text,
|
|
||||||
Username: "gogs",
|
|
||||||
IconUrl: "https://raw.githubusercontent.com/gogits/gogs/master/public/img/favicon.png",
|
|
||||||
UnfurlLinks: 0,
|
|
||||||
LinkNames: 0,
|
|
||||||
Attachments: slackAttachments,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// see: https://api.slack.com/docs/formatting
|
// see: https://api.slack.com/docs/formatting
|
||||||
func SlackTextFormatter(s string) string {
|
func SlackTextFormatter(s string) string {
|
||||||
// take only first line of commit
|
// take only first line of commit
|
||||||
|
@ -113,3 +63,81 @@ func SlackTextFormatter(s string) string {
|
||||||
func SlackLinkFormatter(url string, text string) string {
|
func SlackLinkFormatter(url string, text string) string {
|
||||||
return fmt.Sprintf("<%s|%s>", url, SlackTextFormatter(text))
|
return fmt.Sprintf("<%s|%s>", url, SlackTextFormatter(text))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getSlackCreatePayload(p *api.CreatePayload, slack *SlackMeta) (*SlackPayload, error) {
|
||||||
|
// created tag/branch
|
||||||
|
refName := git.RefEndName(p.Ref)
|
||||||
|
|
||||||
|
repoLink := SlackLinkFormatter(p.Repo.URL, p.Repo.Name)
|
||||||
|
refLink := SlackLinkFormatter(p.Repo.URL+"/src/"+refName, refName)
|
||||||
|
text := fmt.Sprintf("[%s:%s] %s created by %s", repoLink, refLink, p.RefType, p.Sender.UserName)
|
||||||
|
|
||||||
|
return &SlackPayload{
|
||||||
|
Channel: slack.Channel,
|
||||||
|
Text: text,
|
||||||
|
Username: setting.AppName,
|
||||||
|
IconUrl: setting.AppUrl + "/img/favicon.png",
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getSlackPushPayload(p *api.PushPayload, slack *SlackMeta) (*SlackPayload, error) {
|
||||||
|
// n new commits
|
||||||
|
var (
|
||||||
|
branchName = git.RefEndName(p.Ref)
|
||||||
|
commitString string
|
||||||
|
)
|
||||||
|
|
||||||
|
if len(p.Commits) == 1 {
|
||||||
|
commitString = "1 new commit"
|
||||||
|
if len(p.CompareUrl) > 0 {
|
||||||
|
commitString = SlackLinkFormatter(p.CompareUrl, commitString)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
commitString = fmt.Sprintf("%d new commits", len(p.Commits))
|
||||||
|
if p.CompareUrl != "" {
|
||||||
|
commitString = SlackLinkFormatter(p.CompareUrl, commitString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
repoLink := SlackLinkFormatter(p.Repo.URL, p.Repo.Name)
|
||||||
|
branchLink := SlackLinkFormatter(p.Repo.URL+"/src/"+branchName, branchName)
|
||||||
|
text := fmt.Sprintf("[%s:%s] %s pushed by %s", repoLink, branchLink, commitString, p.Pusher.Name)
|
||||||
|
|
||||||
|
var attachmentText string
|
||||||
|
// for each commit, generate attachment text
|
||||||
|
for i, commit := range p.Commits {
|
||||||
|
attachmentText += fmt.Sprintf("%s: %s - %s", SlackLinkFormatter(commit.URL, commit.ID[:7]), SlackTextFormatter(commit.Message), SlackTextFormatter(commit.Author.Name))
|
||||||
|
// add linebreak to each commit but the last
|
||||||
|
if i < len(p.Commits)-1 {
|
||||||
|
attachmentText += "\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
slackAttachments := []SlackAttachment{{Color: SLACK_COLOR, Text: attachmentText}}
|
||||||
|
|
||||||
|
return &SlackPayload{
|
||||||
|
Channel: slack.Channel,
|
||||||
|
Text: text,
|
||||||
|
Username: setting.AppName,
|
||||||
|
IconUrl: setting.AppUrl + "/img/favicon.png",
|
||||||
|
Attachments: slackAttachments,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetSlackPayload(p api.Payloader, event HookEventType, meta string) (*SlackPayload, error) {
|
||||||
|
s := new(SlackPayload)
|
||||||
|
|
||||||
|
slack := &SlackMeta{}
|
||||||
|
if err := json.Unmarshal([]byte(meta), &slack); err != nil {
|
||||||
|
return s, errors.New("GetSlackPayload meta json:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
switch event {
|
||||||
|
case HOOK_EVENT_CREATE:
|
||||||
|
return getSlackCreatePayload(p.(*api.CreatePayload), slack)
|
||||||
|
case HOOK_EVENT_PUSH:
|
||||||
|
return getSlackPushPayload(p.(*api.PushPayload), slack)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
|
@ -67,10 +67,24 @@ func (f *RepoSettingForm) Validate(ctx *macaron.Context, errs binding.Errors) bi
|
||||||
// \/ \/ \/ \/ \/ \/
|
// \/ \/ \/ \/ \/ \/
|
||||||
|
|
||||||
type WebhookForm struct {
|
type WebhookForm struct {
|
||||||
PushOnly bool
|
Events string
|
||||||
|
Create bool
|
||||||
|
Push bool
|
||||||
Active bool
|
Active bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f WebhookForm) PushOnly() bool {
|
||||||
|
return f.Events == "push_only"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f WebhookForm) SendEverything() bool {
|
||||||
|
return f.Events == "send_everything"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f WebhookForm) ChooseEvents() bool {
|
||||||
|
return f.Events == "choose_events"
|
||||||
|
}
|
||||||
|
|
||||||
type NewWebhookForm struct {
|
type NewWebhookForm struct {
|
||||||
PayloadURL string `binding:"Required;Url"`
|
PayloadURL string `binding:"Required;Url"`
|
||||||
ContentType int `binding:"Required"`
|
ContentType int `binding:"Required"`
|
||||||
|
|
File diff suppressed because one or more lines are too long
2
public/css/gogs.min.css
vendored
2
public/css/gogs.min.css
vendored
File diff suppressed because one or more lines are too long
|
@ -367,6 +367,23 @@ function initRepository() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function initWebhook() {
|
||||||
|
if ($('.new.webhook').length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$('.events.checkbox input').change(function () {
|
||||||
|
if ($(this).is(':checked')) {
|
||||||
|
$('.events.fields').show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$('.non-events.checkbox input').change(function () {
|
||||||
|
if ($(this).is(':checked')) {
|
||||||
|
$('.events.fields').hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
csrf = $('meta[name=_csrf]').attr("content");
|
csrf = $('meta[name=_csrf]').attr("content");
|
||||||
|
|
||||||
|
@ -473,4 +490,5 @@ $(document).ready(function () {
|
||||||
initCommentForm();
|
initCommentForm();
|
||||||
initInstall();
|
initInstall();
|
||||||
initRepository();
|
initRepository();
|
||||||
|
initWebhook();
|
||||||
});
|
});
|
|
@ -77,3 +77,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.new.webhook {
|
||||||
|
.events.fields {
|
||||||
|
.column {
|
||||||
|
padding-left: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -83,7 +83,7 @@ func CreateRepoHook(ctx *middleware.Context, form api.CreateHookOption) {
|
||||||
ctx.JSON(422, &base.ApiJsonErr{"missing config option: channel", base.DOC_URL})
|
ctx.JSON(422, &base.ApiJsonErr{"missing config option: channel", base.DOC_URL})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
meta, err := json.Marshal(&models.Slack{
|
meta, err := json.Marshal(&models.SlackMeta{
|
||||||
Channel: channel,
|
Channel: channel,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -141,7 +141,7 @@ func EditRepoHook(ctx *middleware.Context, form api.EditHookOption) {
|
||||||
|
|
||||||
if w.HookTaskType == models.SLACK {
|
if w.HookTaskType == models.SLACK {
|
||||||
if channel, ok := form.Config["channel"]; ok {
|
if channel, ok := form.Config["channel"]; ok {
|
||||||
meta, err := json.Marshal(&models.Slack{
|
meta, err := json.Marshal(&models.SlackMeta{
|
||||||
Channel: channel,
|
Channel: channel,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -320,6 +320,18 @@ func WebhooksNew(ctx *middleware.Context) {
|
||||||
ctx.HTML(200, orCtx.NewTemplate)
|
ctx.HTML(200, orCtx.NewTemplate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ParseHookEvent(form auth.WebhookForm) *models.HookEvent {
|
||||||
|
return &models.HookEvent{
|
||||||
|
PushOnly: form.PushOnly(),
|
||||||
|
SendEverything: form.SendEverything(),
|
||||||
|
ChooseEvents: form.ChooseEvents(),
|
||||||
|
HookEvents: models.HookEvents{
|
||||||
|
Create: form.Create,
|
||||||
|
Push: form.Push,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func WebHooksNewPost(ctx *middleware.Context, form auth.NewWebhookForm) {
|
func WebHooksNewPost(ctx *middleware.Context, form auth.NewWebhookForm) {
|
||||||
ctx.Data["Title"] = ctx.Tr("repo.settings.add_webhook")
|
ctx.Data["Title"] = ctx.Tr("repo.settings.add_webhook")
|
||||||
ctx.Data["PageIsSettingsHooks"] = true
|
ctx.Data["PageIsSettingsHooks"] = true
|
||||||
|
@ -349,9 +361,7 @@ func WebHooksNewPost(ctx *middleware.Context, form auth.NewWebhookForm) {
|
||||||
URL: form.PayloadURL,
|
URL: form.PayloadURL,
|
||||||
ContentType: contentType,
|
ContentType: contentType,
|
||||||
Secret: form.Secret,
|
Secret: form.Secret,
|
||||||
HookEvent: &models.HookEvent{
|
HookEvent: ParseHookEvent(form.WebhookForm),
|
||||||
PushOnly: form.PushOnly,
|
|
||||||
},
|
|
||||||
IsActive: form.Active,
|
IsActive: form.Active,
|
||||||
HookTaskType: models.GOGS,
|
HookTaskType: models.GOGS,
|
||||||
OrgID: orCtx.OrgID,
|
OrgID: orCtx.OrgID,
|
||||||
|
@ -385,7 +395,7 @@ func SlackHooksNewPost(ctx *middleware.Context, form auth.NewSlackHookForm) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
meta, err := json.Marshal(&models.Slack{
|
meta, err := json.Marshal(&models.SlackMeta{
|
||||||
Channel: form.Channel,
|
Channel: form.Channel,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -397,9 +407,7 @@ func SlackHooksNewPost(ctx *middleware.Context, form auth.NewSlackHookForm) {
|
||||||
RepoID: orCtx.RepoID,
|
RepoID: orCtx.RepoID,
|
||||||
URL: form.PayloadURL,
|
URL: form.PayloadURL,
|
||||||
ContentType: models.JSON,
|
ContentType: models.JSON,
|
||||||
HookEvent: &models.HookEvent{
|
HookEvent: ParseHookEvent(form.WebhookForm),
|
||||||
PushOnly: form.PushOnly,
|
|
||||||
},
|
|
||||||
IsActive: form.Active,
|
IsActive: form.Active,
|
||||||
HookTaskType: models.SLACK,
|
HookTaskType: models.SLACK,
|
||||||
Meta: string(meta),
|
Meta: string(meta),
|
||||||
|
@ -491,9 +499,7 @@ func WebHooksEditPost(ctx *middleware.Context, form auth.NewWebhookForm) {
|
||||||
w.URL = form.PayloadURL
|
w.URL = form.PayloadURL
|
||||||
w.ContentType = contentType
|
w.ContentType = contentType
|
||||||
w.Secret = form.Secret
|
w.Secret = form.Secret
|
||||||
w.HookEvent = &models.HookEvent{
|
w.HookEvent = ParseHookEvent(form.WebhookForm)
|
||||||
PushOnly: form.PushOnly,
|
|
||||||
}
|
|
||||||
w.IsActive = form.Active
|
w.IsActive = form.Active
|
||||||
if err := w.UpdateEvent(); err != nil {
|
if err := w.UpdateEvent(); err != nil {
|
||||||
ctx.Handle(500, "UpdateEvent", err)
|
ctx.Handle(500, "UpdateEvent", err)
|
||||||
|
@ -523,7 +529,7 @@ func SlackHooksEditPost(ctx *middleware.Context, form auth.NewSlackHookForm) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
meta, err := json.Marshal(&models.Slack{
|
meta, err := json.Marshal(&models.SlackMeta{
|
||||||
Channel: form.Channel,
|
Channel: form.Channel,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -533,9 +539,7 @@ func SlackHooksEditPost(ctx *middleware.Context, form auth.NewSlackHookForm) {
|
||||||
|
|
||||||
w.URL = form.PayloadURL
|
w.URL = form.PayloadURL
|
||||||
w.Meta = string(meta)
|
w.Meta = string(meta)
|
||||||
w.HookEvent = &models.HookEvent{
|
w.HookEvent = ParseHookEvent(form.WebhookForm)
|
||||||
PushOnly: form.PushOnly,
|
|
||||||
}
|
|
||||||
w.IsActive = form.Active
|
w.IsActive = form.Active
|
||||||
if err := w.UpdateEvent(); err != nil {
|
if err := w.UpdateEvent(); err != nil {
|
||||||
ctx.Handle(500, "UpdateEvent", err)
|
ctx.Handle(500, "UpdateEvent", err)
|
||||||
|
|
|
@ -26,4 +26,22 @@
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
<!-- Third-party libraries -->
|
||||||
|
{{if .RequireHighlightJS}}
|
||||||
|
<link rel="stylesheet" href="{{AppSubUrl}}/css/highlight-8.7/default.css">
|
||||||
|
<script src="{{AppSubUrl}}/js/libs/highlight-8.7.pack.js"></script>
|
||||||
|
{{end}}
|
||||||
|
{{if .RequireMinicolors}}
|
||||||
|
<link rel="stylesheet" href="{{AppSubUrl}}/css/jquery.minicolors-2.1.12.css">
|
||||||
|
<script src="{{AppSubUrl}}/js/libs/jquery.minicolors-2.1.12.min.js"></script>
|
||||||
|
{{end}}
|
||||||
|
{{if .RequireDatetimepicker}}
|
||||||
|
<link rel="stylesheet" href="{{AppSubUrl}}/css/jquery.datetimepicker-2.4.5.css">
|
||||||
|
<script src="{{AppSubUrl}}/js/libs/jquery.datetimepicker-2.4.5.js"></script>
|
||||||
|
{{end}}
|
||||||
|
{{if .RequireDropzone}}
|
||||||
|
<link rel="stylesheet" href="{{AppSubUrl}}/css/dropzone-4.0.1.css">
|
||||||
|
<script src="{{AppSubUrl}}/js/libs/dropzone-4.0.1.js"></script>
|
||||||
|
{{end}}
|
||||||
</html>
|
</html>
|
|
@ -25,24 +25,6 @@
|
||||||
<script src="{{AppSubUrl}}/js/semantic-2.0.8.min.js"></script>
|
<script src="{{AppSubUrl}}/js/semantic-2.0.8.min.js"></script>
|
||||||
<script src="{{AppSubUrl}}/js/gogs.js?v={{AppVer}}"></script>
|
<script src="{{AppSubUrl}}/js/gogs.js?v={{AppVer}}"></script>
|
||||||
|
|
||||||
<!-- Third-party libraries -->
|
|
||||||
{{if .RequireHighlightJS}}
|
|
||||||
<link rel="stylesheet" href="{{AppSubUrl}}/css/highlight-8.7/default.css">
|
|
||||||
<script src="{{AppSubUrl}}/js/libs/highlight-8.7.pack.js"></script>
|
|
||||||
{{end}}
|
|
||||||
{{if .RequireMinicolors}}
|
|
||||||
<link rel="stylesheet" href="{{AppSubUrl}}/css/jquery.minicolors-2.1.12.css">
|
|
||||||
<script src="{{AppSubUrl}}/js/libs/jquery.minicolors-2.1.12.min.js"></script>
|
|
||||||
{{end}}
|
|
||||||
{{if .RequireDatetimepicker}}
|
|
||||||
<link rel="stylesheet" href="{{AppSubUrl}}/css/jquery.datetimepicker-2.4.5.css">
|
|
||||||
<script src="{{AppSubUrl}}/js/libs/jquery.datetimepicker-2.4.5.js"></script>
|
|
||||||
{{end}}
|
|
||||||
{{if .RequireDropzone}}
|
|
||||||
<link rel="stylesheet" href="{{AppSubUrl}}/css/dropzone-4.0.1.css">
|
|
||||||
<script src="{{AppSubUrl}}/js/libs/dropzone-4.0.1.js"></script>
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
<title>{{if .Title}}{{.Title}} - {{end}}{{AppName}}</title>
|
<title>{{if .Title}}{{.Title}} - {{end}}{{AppName}}</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
{{if .IsSucceed}}
|
{{if .IsSucceed}}
|
||||||
<span class="ui green label">{{.ResponseInfo.Status}}</span>
|
<span class="ui green label">{{.ResponseInfo.Status}}</span>
|
||||||
{{else}}
|
{{else}}
|
||||||
<span class="ui red label">500</span>
|
<span class="ui red label">{{.ResponseInfo.Status}}</span>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{else}}
|
{{else}}
|
||||||
<span class="ui label">N/A</span>
|
<span class="ui label">N/A</span>
|
||||||
|
|
|
@ -1,14 +1,52 @@
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<h4>{{.i18n.Tr "repo.settings.event_desc"}}</h4>
|
<h4>{{.i18n.Tr "repo.settings.event_desc"}}</h4>
|
||||||
<div class="grouped fields">
|
<div class="grouped event type fields">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<div class="ui radio checkbox checked">
|
<div class="ui radio non-events checkbox">
|
||||||
<input class="hidden" name="push_only" type="radio" {{if or .PageIsSettingsHooksNew .Webhook.PushOnly}}checked{{end}}>
|
<input class="hidden" name="events" type="radio" value="push_only" {{if or .PageIsSettingsHooksNew .Webhook.PushOnly}}checked{{end}}>
|
||||||
<label>{{.i18n.Tr "repo.settings.event_push_only" | Str2html}}</label>
|
<label>{{.i18n.Tr "repo.settings.event_push_only" | Str2html}}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<div class="ui radio non-events checkbox">
|
||||||
|
<input class="hidden" name="events" type="radio" value="send_everything" {{if .Webhook.SendEverything}}checked{{end}}>
|
||||||
|
<label>{{.i18n.Tr "repo.settings.event_send_everything" | Str2html}}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<div class="ui radio events checkbox">
|
||||||
|
<input class="hidden" name="events" type="radio" value="choose_events" {{if .Webhook.ChooseEvents}}checked{{end}}>
|
||||||
|
<label>{{.i18n.Tr "repo.settings.event_choose" | Str2html}}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="events fields ui grid" {{if not .Webhook.ChooseEvents}}style="display:none"{{end}}>
|
||||||
|
<!-- Create -->
|
||||||
|
<div class="seven wide column">
|
||||||
|
<div class="field">
|
||||||
|
<div class="ui checkbox">
|
||||||
|
<input class="hidden" name="create" type="checkbox" tabindex="0" {{if .Webhook.Create}}checked{{end}}>
|
||||||
|
<label>{{.i18n.Tr "repo.settings.event_create"}}</label>
|
||||||
|
<span class="help">{{.i18n.Tr "repo.settings.event_create_desc"}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Push -->
|
||||||
|
<div class="seven wide column">
|
||||||
|
<div class="field">
|
||||||
|
<div class="ui checkbox">
|
||||||
|
<input class="hidden" name="push" type="checkbox" tabindex="0" {{if .Webhook.Push}}checked{{end}}>
|
||||||
|
<label>{{.i18n.Tr "repo.settings.event_push"}}</label>
|
||||||
|
<span class="help">{{.i18n.Tr "repo.settings.event_push_desc"}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ui divider"></div>
|
||||||
|
|
||||||
<div class="inline field">
|
<div class="inline field">
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input class="hidden" name="active" type="checkbox" tabindex="0" {{if or .PageIsSettingsHooksNew .Webhook.IsActive}}checked{{end}}>
|
<input class="hidden" name="active" type="checkbox" tabindex="0" {{if or .PageIsSettingsHooksNew .Webhook.IsActive}}checked{{end}}>
|
||||||
|
|
Loading…
Reference in a new issue