aboutsummaryrefslogtreecommitdiff
path: root/models
diff options
context:
space:
mode:
authorUnknwon <u@gogs.io>2017-02-24 15:35:20 -0500
committerUnknwon <u@gogs.io>2017-02-27 22:47:21 -0500
commitf0086e66aef31573c7f00e0c3cd7725fb6d65f5c (patch)
tree865fd5787c6f714add7be9da1e8cf19d4bc887cc /models
parent7fe13e72d8f8c0e61abbc4068ecb965347fe0331 (diff)
webhook: able to detect delete branch or tag (#2315)
Diffstat (limited to 'models')
-rw-r--r--models/action.go74
-rw-r--r--models/update.go45
-rw-r--r--models/webhook.go12
-rw-r--r--models/webhook_discord.go53
-rw-r--r--models/webhook_slack.go45
5 files changed, 154 insertions, 75 deletions
diff --git a/models/action.go b/models/action.go
index d0a4b545..f10da4c7 100644
--- a/models/action.go
+++ b/models/action.go
@@ -458,18 +458,16 @@ func CommitRepoAction(opts CommitRepoActionOptions) error {
return fmt.Errorf("UpdateRepository: %v", err)
}
- isNewBranch := false
+ isNewRef := opts.OldCommitID == git.EMPTY_SHA
+ isDelRef := opts.NewCommitID == git.EMPTY_SHA
+
opType := ACTION_COMMIT_REPO
- // Check it's tag push or branch.
+ // Check if it's tag push or branch.
if strings.HasPrefix(opts.RefFullName, git.TAG_PREFIX) {
opType = ACTION_PUSH_TAG
- opts.Commits = &PushCommits{}
} else {
- // TODO: detect branch deletion
// if not the first commit, set the compare URL.
- if opts.OldCommitID == git.EMPTY_SHA {
- isNewBranch = true
- } else {
+ if !isNewRef && !isDelRef {
opts.Commits.CompareURL = repo.ComposeCompareURL(opts.OldCommitID, opts.NewCommitID)
}
@@ -506,20 +504,36 @@ func CommitRepoAction(opts CommitRepoActionOptions) error {
go HookQueue.Add(repo.ID)
}()
- apiPusher := pusher.APIFormat()
apiRepo := repo.APIFormat(nil)
+ apiPusher := pusher.APIFormat()
switch opType {
case ACTION_COMMIT_REPO: // Push
+ if isDelRef {
+ if err = PrepareWebhooks(repo, HOOK_EVENT_DELETE, &api.DeletePayload{
+ Ref: refName,
+ RefType: "branch",
+ PusherType: api.PUSHER_TYPE_USER,
+ Repo: apiRepo,
+ Sender: apiPusher,
+ }); err != nil {
+ return fmt.Errorf("PrepareWebhooks.(delete branch): %v", err)
+ }
+
+ // Delete branch doesn't have anything to push or compare
+ return nil
+ }
+
compareURL := setting.AppUrl + opts.Commits.CompareURL
- if isNewBranch {
+ if isNewRef {
compareURL = ""
if err = PrepareWebhooks(repo, HOOK_EVENT_CREATE, &api.CreatePayload{
- Ref: refName,
- RefType: "branch",
- Repo: apiRepo,
- Sender: apiPusher,
+ Ref: refName,
+ RefType: "branch",
+ DefaultBranch: repo.DefaultBranch,
+ Repo: apiRepo,
+ Sender: apiPusher,
}); err != nil {
- return fmt.Errorf("PrepareWebhooks (new branch): %v", err)
+ return fmt.Errorf("PrepareWebhooks.(new branch): %v", err)
}
}
@@ -533,16 +547,32 @@ func CommitRepoAction(opts CommitRepoActionOptions) error {
Pusher: apiPusher,
Sender: apiPusher,
}); err != nil {
- return fmt.Errorf("PrepareWebhooks (new commit): %v", err)
+ return fmt.Errorf("PrepareWebhooks.(new commit): %v", err)
}
- case ACTION_PUSH_TAG: // Create
- return PrepareWebhooks(repo, HOOK_EVENT_CREATE, &api.CreatePayload{
- Ref: refName,
- RefType: "tag",
- Repo: apiRepo,
- Sender: apiPusher,
- })
+ case ACTION_PUSH_TAG: // Tag
+ if isDelRef {
+ if err = PrepareWebhooks(repo, HOOK_EVENT_DELETE, &api.DeletePayload{
+ Ref: refName,
+ RefType: "tag",
+ PusherType: api.PUSHER_TYPE_USER,
+ Repo: apiRepo,
+ Sender: apiPusher,
+ }); err != nil {
+ return fmt.Errorf("PrepareWebhooks.(delete tag): %v", err)
+ }
+ return nil
+ }
+
+ if err = PrepareWebhooks(repo, HOOK_EVENT_CREATE, &api.CreatePayload{
+ Ref: refName,
+ RefType: "tag",
+ DefaultBranch: repo.DefaultBranch,
+ Repo: apiRepo,
+ Sender: apiPusher,
+ }); err != nil {
+ return fmt.Errorf("PrepareWebhooks.(new tag): %v", err)
+ }
}
return nil
diff --git a/models/update.go b/models/update.go
index 507150be..77336ac9 100644
--- a/models/update.go
+++ b/models/update.go
@@ -10,8 +10,6 @@ import (
"os/exec"
"strings"
- log "gopkg.in/clog.v1"
-
git "github.com/gogits/git-module"
)
@@ -29,6 +27,10 @@ func CommitToPushCommit(commit *git.Commit) *PushCommit {
}
func ListToPushCommits(l *list.List) *PushCommits {
+ if l == nil {
+ return &PushCommits{}
+ }
+
commits := make([]*PushCommit, 0)
var actEmail string
for e := l.Front(); e != nil; e = e.Next() {
@@ -68,12 +70,6 @@ func PushUpdate(opts PushUpdateOptions) (err error) {
return fmt.Errorf("Fail to call 'git update-server-info': %v", err)
}
- if isDelRef {
- log.Trace("Reference '%s' has been deleted from '%s/%s' by %s",
- opts.RefFullName, opts.RepoUserName, opts.RepoName, opts.PusherName)
- return nil
- }
-
gitRepo, err := git.OpenRepository(repoPath)
if err != nil {
return fmt.Errorf("OpenRepository: %v", err)
@@ -100,27 +96,30 @@ func PushUpdate(opts PushUpdateOptions) (err error) {
NewCommitID: opts.NewCommitID,
Commits: &PushCommits{},
}); err != nil {
- return fmt.Errorf("CommitRepoAction (tag): %v", err)
+ return fmt.Errorf("CommitRepoAction.(tag): %v", err)
}
return nil
}
- newCommit, err := gitRepo.GetCommit(opts.NewCommitID)
- if err != nil {
- return fmt.Errorf("gitRepo.GetCommit: %v", err)
- }
-
- // Push new branch.
var l *list.List
- if isNewRef {
- l, err = newCommit.CommitsBeforeLimit(10)
+ // Skip read parent commits when delete branch
+ if !isDelRef {
+ // Push new branch.
+ newCommit, err := gitRepo.GetCommit(opts.NewCommitID)
if err != nil {
- return fmt.Errorf("newCommit.CommitsBeforeLimit: %v", err)
+ return fmt.Errorf("GetCommit [commit_id: %s]: %v", opts.NewCommitID, err)
}
- } else {
- l, err = newCommit.CommitsBeforeUntil(opts.OldCommitID)
- if err != nil {
- return fmt.Errorf("newCommit.CommitsBeforeUntil: %v", err)
+
+ if isNewRef {
+ l, err = newCommit.CommitsBeforeLimit(10)
+ if err != nil {
+ return fmt.Errorf("CommitsBeforeLimit [commit_id: %s]: %v", newCommit.ID, err)
+ }
+ } else {
+ l, err = newCommit.CommitsBeforeUntil(opts.OldCommitID)
+ if err != nil {
+ return fmt.Errorf("CommitsBeforeUntil [commit_id: %s]: %v", opts.OldCommitID, err)
+ }
}
}
@@ -133,7 +132,7 @@ func PushUpdate(opts PushUpdateOptions) (err error) {
NewCommitID: opts.NewCommitID,
Commits: ListToPushCommits(l),
}); err != nil {
- return fmt.Errorf("CommitRepoAction (branch): %v", err)
+ return fmt.Errorf("CommitRepoAction.(branch): %v", err)
}
return nil
}
diff --git a/models/webhook.go b/models/webhook.go
index feabf03b..a55fcfa7 100644
--- a/models/webhook.go
+++ b/models/webhook.go
@@ -63,6 +63,7 @@ func IsValidHookContentType(name string) bool {
type HookEvents struct {
Create bool `json:"create"`
+ Delete bool `json:"delete"`
Push bool `json:"push"`
PullRequest bool `json:"pull_request"`
}
@@ -156,6 +157,12 @@ func (w *Webhook) HasCreateEvent() bool {
(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)
+}
+
// HasPushEvent returns true if hook enabled push event.
func (w *Webhook) HasPushEvent() bool {
return w.PushOnly || w.SendEverything ||
@@ -337,6 +344,7 @@ type HookEventType string
const (
HOOK_EVENT_CREATE HookEventType = "create"
+ HOOK_EVENT_DELETE HookEventType = "delete"
HOOK_EVENT_PUSH HookEventType = "push"
HOOK_EVENT_PULL_REQUEST HookEventType = "pull_request"
)
@@ -462,6 +470,10 @@ func prepareWebhooks(repo *Repository, event HookEventType, p api.Payloader, web
if !w.HasCreateEvent() {
continue
}
+ case HOOK_EVENT_DELETE:
+ if !w.HasDeleteEvent() {
+ continue
+ }
case HOOK_EVENT_PUSH:
if !w.HasPushEvent() {
continue
diff --git a/models/webhook_discord.go b/models/webhook_discord.go
index 27b01bc3..3755d3b5 100644
--- a/models/webhook_discord.go
+++ b/models/webhook_discord.go
@@ -68,22 +68,35 @@ func DiscordSHALinkFormatter(url string, text string) string {
return fmt.Sprintf("[`%s`](%s)", text, url)
}
-func getDiscordCreatePayload(p *api.CreatePayload, slack *SlackMeta) (*DiscordPayload, error) {
- // Created tag/branch
+// getDiscordCreatePayload composes Discord payload for create new branch or tag.
+func getDiscordCreatePayload(p *api.CreatePayload) (*DiscordPayload, error) {
refName := git.RefEndName(p.Ref)
-
repoLink := DiscordLinkFormatter(p.Repo.HTMLURL, p.Repo.Name)
refLink := DiscordLinkFormatter(p.Repo.HTMLURL+"/src/"+refName, refName)
content := fmt.Sprintf("Created new %s: %s/%s", p.RefType, repoLink, refLink)
- color, _ := strconv.ParseInt(strings.TrimLeft(slack.Color, "#"), 16, 32)
return &DiscordPayload{
- Username: slack.Username,
- AvatarURL: slack.IconURL,
Embeds: []*DiscordEmbedObject{{
Description: content,
URL: setting.AppUrl + p.Sender.UserName,
- Color: int(color),
+ Author: &DiscordEmbedAuthorObject{
+ Name: p.Sender.UserName,
+ IconURL: p.Sender.AvatarUrl,
+ },
+ }},
+ }, nil
+}
+
+// getDiscordDeletePayload composes Discord payload for delete a branch or tag.
+func getDiscordDeletePayload(p *api.DeletePayload) (*DiscordPayload, error) {
+ refName := git.RefEndName(p.Ref)
+ repoLink := DiscordLinkFormatter(p.Repo.HTMLURL, p.Repo.Name)
+ content := fmt.Sprintf("Deleted %s: %s/%s", p.RefType, repoLink, refName)
+
+ return &DiscordPayload{
+ Embeds: []*DiscordEmbedObject{{
+ Description: content,
+ URL: setting.AppUrl + p.Sender.UserName,
Author: &DiscordEmbedAuthorObject{
Name: p.Sender.UserName,
IconURL: p.Sender.AvatarUrl,
@@ -206,22 +219,32 @@ func getDiscordPullRequestPayload(p *api.PullRequestPayload, slack *SlackMeta) (
}, nil
}
-func GetDiscordPayload(p api.Payloader, event HookEventType, meta string) (*DiscordPayload, error) {
- d := new(DiscordPayload)
-
+func GetDiscordPayload(p api.Payloader, event HookEventType, meta string) (payload *DiscordPayload, err error) {
slack := &SlackMeta{}
if err := json.Unmarshal([]byte(meta), &slack); err != nil {
- return d, fmt.Errorf("GetDiscordPayload meta json: %v", err)
+ return nil, fmt.Errorf("json.Unmarshal: %v", err)
}
switch event {
case HOOK_EVENT_CREATE:
- return getDiscordCreatePayload(p.(*api.CreatePayload), slack)
+ payload, err = getDiscordCreatePayload(p.(*api.CreatePayload))
+ case HOOK_EVENT_DELETE:
+ payload, err = getDiscordDeletePayload(p.(*api.DeletePayload))
case HOOK_EVENT_PUSH:
- return getDiscordPushPayload(p.(*api.PushPayload), slack)
+ payload, err = getDiscordPushPayload(p.(*api.PushPayload), slack)
case HOOK_EVENT_PULL_REQUEST:
- return getDiscordPullRequestPayload(p.(*api.PullRequestPayload), slack)
+ payload, err = getDiscordPullRequestPayload(p.(*api.PullRequestPayload), slack)
+ }
+ if err != nil {
+ return nil, fmt.Errorf("event '%s': %v", event, err)
+ }
+
+ payload.Username = slack.Username
+ payload.AvatarURL = slack.IconURL
+ if len(payload.Embeds) > 0 {
+ color, _ := strconv.ParseInt(strings.TrimLeft(slack.Color, "#"), 16, 32)
+ payload.Embeds[0].Color = int(color)
}
- return d, nil
+ return payload, nil
}
diff --git a/models/webhook_slack.go b/models/webhook_slack.go
index 5943a9e5..f785bb68 100644
--- a/models/webhook_slack.go
+++ b/models/webhook_slack.go
@@ -69,19 +69,24 @@ func SlackLinkFormatter(url string, text string) string {
return fmt.Sprintf("<%s|%s>", url, SlackTextFormatter(text))
}
-func getSlackCreatePayload(p *api.CreatePayload, slack *SlackMeta) (*SlackPayload, error) {
- // Created tag/branch
+// getSlackCreatePayload composes Slack payload for create new branch or tag.
+func getSlackCreatePayload(p *api.CreatePayload) (*SlackPayload, error) {
refName := git.RefEndName(p.Ref)
-
repoLink := SlackLinkFormatter(p.Repo.HTMLURL, p.Repo.Name)
refLink := SlackLinkFormatter(p.Repo.HTMLURL+"/src/"+refName, refName)
text := fmt.Sprintf("[%s:%s] %s created by %s", repoLink, refLink, p.RefType, p.Sender.UserName)
+ return &SlackPayload{
+ Text: text,
+ }, nil
+}
+// getSlackDeletePayload composes Slack payload for delete a branch or tag.
+func getSlackDeletePayload(p *api.DeletePayload) (*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,
+ Text: text,
}, nil
}
@@ -178,22 +183,32 @@ func getSlackPullRequestPayload(p *api.PullRequestPayload, slack *SlackMeta) (*S
}, nil
}
-func GetSlackPayload(p api.Payloader, event HookEventType, meta string) (*SlackPayload, error) {
- s := new(SlackPayload)
-
+func GetSlackPayload(p api.Payloader, event HookEventType, meta string) (payload *SlackPayload, err error) {
slack := &SlackMeta{}
if err := json.Unmarshal([]byte(meta), &slack); err != nil {
- return s, fmt.Errorf("GetSlackPayload meta json: %v", err)
+ return nil, fmt.Errorf("json.Unmarshal: %v", err)
}
switch event {
case HOOK_EVENT_CREATE:
- return getSlackCreatePayload(p.(*api.CreatePayload), slack)
+ payload, err = getSlackCreatePayload(p.(*api.CreatePayload))
+ case HOOK_EVENT_DELETE:
+ payload, err = getSlackDeletePayload(p.(*api.DeletePayload))
case HOOK_EVENT_PUSH:
- return getSlackPushPayload(p.(*api.PushPayload), slack)
+ payload, err = getSlackPushPayload(p.(*api.PushPayload), slack)
case HOOK_EVENT_PULL_REQUEST:
- return getSlackPullRequestPayload(p.(*api.PullRequestPayload), slack)
+ payload, err = getSlackPullRequestPayload(p.(*api.PullRequestPayload), slack)
+ }
+ if err != nil {
+ return nil, fmt.Errorf("event '%s': %v", event, err)
+ }
+
+ payload.Channel = slack.Channel
+ payload.Username = slack.Username
+ payload.IconURL = slack.IconURL
+ if len(payload.Attachments) > 0 {
+ payload.Attachments[0].Color = slack.Color
}
- return s, nil
+ return payload, nil
}