mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-12-21 12:44:49 -05:00
Webhooks for repo creation/deletion (#1663)
* Webhooks for repo creation/deletion * add createHookTask * Add handles for GetSlackPayload and GetDiscordPayload
This commit is contained in:
parent
79f7839633
commit
b689bb6180
16 changed files with 163 additions and 39 deletions
|
@ -835,8 +835,8 @@ func wikiRemoteURL(remote string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// MigrateRepository migrates a existing repository from other project hosting.
|
// MigrateRepository migrates a existing repository from other project hosting.
|
||||||
func MigrateRepository(u *User, opts MigrateRepoOptions) (*Repository, error) {
|
func MigrateRepository(doer, u *User, opts MigrateRepoOptions) (*Repository, error) {
|
||||||
repo, err := CreateRepository(u, CreateRepoOptions{
|
repo, err := CreateRepository(doer, u, CreateRepoOptions{
|
||||||
Name: opts.Name,
|
Name: opts.Name,
|
||||||
Description: opts.Description,
|
Description: opts.Description,
|
||||||
IsPrivate: opts.IsPrivate,
|
IsPrivate: opts.IsPrivate,
|
||||||
|
@ -1202,7 +1202,7 @@ func IsUsableRepoName(name string) error {
|
||||||
return isUsableName(reservedRepoNames, reservedRepoPatterns, name)
|
return isUsableName(reservedRepoNames, reservedRepoPatterns, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func createRepository(e *xorm.Session, u *User, repo *Repository) (err error) {
|
func createRepository(e *xorm.Session, doer, u *User, repo *Repository) (err error) {
|
||||||
if err = IsUsableRepoName(repo.Name); err != nil {
|
if err = IsUsableRepoName(repo.Name); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -1249,7 +1249,15 @@ func createRepository(e *xorm.Session, u *User, repo *Repository) (err error) {
|
||||||
return fmt.Errorf("getOwnerTeam: %v", err)
|
return fmt.Errorf("getOwnerTeam: %v", err)
|
||||||
} else if err = t.addRepository(e, repo); err != nil {
|
} else if err = t.addRepository(e, repo); err != nil {
|
||||||
return fmt.Errorf("addRepository: %v", err)
|
return fmt.Errorf("addRepository: %v", err)
|
||||||
|
} else if err = prepareWebhooks(e, repo, HookEventRepository, &api.RepositoryPayload{
|
||||||
|
Action: api.HookRepoCreated,
|
||||||
|
Repository: repo.APIFormat(AccessModeOwner),
|
||||||
|
Organization: u.APIFormat(),
|
||||||
|
Sender: doer.APIFormat(),
|
||||||
|
}); err != nil {
|
||||||
|
return fmt.Errorf("prepareWebhooks: %v", err)
|
||||||
}
|
}
|
||||||
|
go HookQueue.Add(repo.ID)
|
||||||
} else {
|
} else {
|
||||||
// Organization automatically called this in addRepository method.
|
// Organization automatically called this in addRepository method.
|
||||||
if err = repo.recalculateAccesses(e); err != nil {
|
if err = repo.recalculateAccesses(e); err != nil {
|
||||||
|
@ -1266,8 +1274,8 @@ func createRepository(e *xorm.Session, u *User, repo *Repository) (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateRepository creates a repository for given user or organization.
|
// CreateRepository creates a repository for the user/organization u.
|
||||||
func CreateRepository(u *User, opts CreateRepoOptions) (_ *Repository, err error) {
|
func CreateRepository(doer, u *User, opts CreateRepoOptions) (_ *Repository, err error) {
|
||||||
if !u.CanCreateRepo() {
|
if !u.CanCreateRepo() {
|
||||||
return nil, ErrReachLimitOfRepo{u.MaxRepoCreation}
|
return nil, ErrReachLimitOfRepo{u.MaxRepoCreation}
|
||||||
}
|
}
|
||||||
|
@ -1287,7 +1295,7 @@ func CreateRepository(u *User, opts CreateRepoOptions) (_ *Repository, err error
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = createRepository(sess, u, repo); err != nil {
|
if err = createRepository(sess, doer, u, repo); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1623,7 +1631,7 @@ func UpdateRepositoryUnits(repo *Repository, units []RepoUnit) (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteRepository deletes a repository for a user or organization.
|
// DeleteRepository deletes a repository for a user or organization.
|
||||||
func DeleteRepository(uid, repoID int64) error {
|
func DeleteRepository(doer *User, uid, repoID int64) error {
|
||||||
// In case is a organization.
|
// In case is a organization.
|
||||||
org, err := GetUserByID(uid)
|
org, err := GetUserByID(uid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1781,6 +1789,18 @@ func DeleteRepository(uid, repoID int64) error {
|
||||||
return fmt.Errorf("Commit: %v", err)
|
return fmt.Errorf("Commit: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if org.IsOrganization() {
|
||||||
|
if err = PrepareWebhooks(repo, HookEventRepository, &api.RepositoryPayload{
|
||||||
|
Action: api.HookRepoDeleted,
|
||||||
|
Repository: repo.APIFormat(AccessModeOwner),
|
||||||
|
Organization: org.APIFormat(),
|
||||||
|
Sender: doer.APIFormat(),
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
go HookQueue.Add(repo.ID)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1974,7 +1994,7 @@ func gatherMissingRepoRecords() ([]*Repository, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteMissingRepositories deletes all repository records that lost Git files.
|
// DeleteMissingRepositories deletes all repository records that lost Git files.
|
||||||
func DeleteMissingRepositories() error {
|
func DeleteMissingRepositories(doer *User) error {
|
||||||
repos, err := gatherMissingRepoRecords()
|
repos, err := gatherMissingRepoRecords()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("gatherMissingRepoRecords: %v", err)
|
return fmt.Errorf("gatherMissingRepoRecords: %v", err)
|
||||||
|
@ -1986,7 +2006,7 @@ func DeleteMissingRepositories() error {
|
||||||
|
|
||||||
for _, repo := range repos {
|
for _, repo := range repos {
|
||||||
log.Trace("Deleting %d/%d...", repo.OwnerID, repo.ID)
|
log.Trace("Deleting %d/%d...", repo.OwnerID, repo.ID)
|
||||||
if err := DeleteRepository(repo.OwnerID, repo.ID); err != nil {
|
if err := DeleteRepository(doer, repo.OwnerID, repo.ID); err != nil {
|
||||||
if err2 := CreateRepositoryNotice(fmt.Sprintf("DeleteRepository [%d]: %v", repo.ID, err)); err2 != nil {
|
if err2 := CreateRepositoryNotice(fmt.Sprintf("DeleteRepository [%d]: %v", repo.ID, err)); err2 != nil {
|
||||||
return fmt.Errorf("CreateRepositoryNotice: %v", err)
|
return fmt.Errorf("CreateRepositoryNotice: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -2226,7 +2246,7 @@ func HasForkedRepo(ownerID, repoID int64) (*Repository, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ForkRepository forks a repository
|
// ForkRepository forks a repository
|
||||||
func ForkRepository(u *User, oldRepo *Repository, name, desc string) (_ *Repository, err error) {
|
func ForkRepository(doer, u *User, oldRepo *Repository, name, desc string) (_ *Repository, err error) {
|
||||||
forkedRepo, err := oldRepo.GetUserFork(u.ID)
|
forkedRepo, err := oldRepo.GetUserFork(u.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -2256,7 +2276,7 @@ func ForkRepository(u *User, oldRepo *Repository, name, desc string) (_ *Reposit
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = createRepository(sess, u, repo); err != nil {
|
if err = createRepository(sess, doer, u, repo); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -118,13 +118,12 @@ func TestGetUserFork(t *testing.T) {
|
||||||
func TestForkRepository(t *testing.T) {
|
func TestForkRepository(t *testing.T) {
|
||||||
assert.NoError(t, PrepareTestDatabase())
|
assert.NoError(t, PrepareTestDatabase())
|
||||||
|
|
||||||
// User13 has repo 11 forked from repo10
|
// user 13 has already forked repo10
|
||||||
repo, err := GetRepositoryByID(10)
|
user := AssertExistsAndLoadBean(t, &User{ID: 13}).(*User)
|
||||||
assert.NoError(t, err)
|
repo := AssertExistsAndLoadBean(t, &Repository{ID: 10}).(*Repository)
|
||||||
assert.NotNil(t, repo)
|
|
||||||
|
|
||||||
repo, err = ForkRepository(&User{ID: 13}, repo, "test", "test")
|
fork, err := ForkRepository(user, user, repo, "test", "test")
|
||||||
assert.Nil(t, repo)
|
assert.Nil(t, fork)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.True(t, IsErrRepoAlreadyExist(err))
|
assert.True(t, IsErrRepoAlreadyExist(err))
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,6 +68,7 @@ type HookEvents struct {
|
||||||
Create bool `json:"create"`
|
Create bool `json:"create"`
|
||||||
Push bool `json:"push"`
|
Push bool `json:"push"`
|
||||||
PullRequest bool `json:"pull_request"`
|
PullRequest bool `json:"pull_request"`
|
||||||
|
Repository bool `json:"repository"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// HookEvent represents events that will delivery hook.
|
// HookEvent represents events that will delivery hook.
|
||||||
|
@ -188,6 +189,12 @@ func (w *Webhook) HasPullRequestEvent() bool {
|
||||||
(w.ChooseEvents && w.HookEvents.PullRequest)
|
(w.ChooseEvents && w.HookEvents.PullRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HasRepositoryEvent returns if hook enabled repository event.
|
||||||
|
func (w *Webhook) HasRepositoryEvent() bool {
|
||||||
|
return w.SendEverything ||
|
||||||
|
(w.ChooseEvents && w.HookEvents.Repository)
|
||||||
|
}
|
||||||
|
|
||||||
// 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, 3)
|
||||||
|
@ -246,8 +253,12 @@ func GetWebhookByOrgID(orgID, id int64) (*Webhook, error) {
|
||||||
|
|
||||||
// GetActiveWebhooksByRepoID returns all active webhooks of repository.
|
// GetActiveWebhooksByRepoID returns all active webhooks of repository.
|
||||||
func GetActiveWebhooksByRepoID(repoID int64) ([]*Webhook, error) {
|
func GetActiveWebhooksByRepoID(repoID int64) ([]*Webhook, error) {
|
||||||
|
return getActiveWebhooksByRepoID(x, repoID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getActiveWebhooksByRepoID(e Engine, repoID int64) ([]*Webhook, error) {
|
||||||
webhooks := make([]*Webhook, 0, 5)
|
webhooks := make([]*Webhook, 0, 5)
|
||||||
return webhooks, x.Where("is_active=?", true).
|
return webhooks, e.Where("is_active=?", true).
|
||||||
Find(&webhooks, &Webhook{RepoID: repoID})
|
Find(&webhooks, &Webhook{RepoID: repoID})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,7 +270,11 @@ func GetWebhooksByRepoID(repoID int64) ([]*Webhook, error) {
|
||||||
|
|
||||||
// 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.
|
return getActiveWebhooksByOrgID(x, orgID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getActiveWebhooksByOrgID(e Engine, orgID int64) (ws []*Webhook, err error) {
|
||||||
|
err = e.
|
||||||
Where("org_id=?", orgID).
|
Where("org_id=?", orgID).
|
||||||
And("is_active=?", true).
|
And("is_active=?", true).
|
||||||
Find(&ws)
|
Find(&ws)
|
||||||
|
@ -379,6 +394,7 @@ const (
|
||||||
HookEventCreate HookEventType = "create"
|
HookEventCreate HookEventType = "create"
|
||||||
HookEventPush HookEventType = "push"
|
HookEventPush HookEventType = "push"
|
||||||
HookEventPullRequest HookEventType = "pull_request"
|
HookEventPullRequest HookEventType = "pull_request"
|
||||||
|
HookEventRepository HookEventType = "repository"
|
||||||
)
|
)
|
||||||
|
|
||||||
// HookRequest represents hook task request information.
|
// HookRequest represents hook task request information.
|
||||||
|
@ -479,13 +495,17 @@ func HookTasks(hookID int64, page int) ([]*HookTask, error) {
|
||||||
// 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 {
|
||||||
|
return createHookTask(x, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func createHookTask(e Engine, t *HookTask) error {
|
||||||
data, err := t.Payloader.JSONPayload()
|
data, err := t.Payloader.JSONPayload()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
t.UUID = gouuid.NewV4().String()
|
t.UUID = gouuid.NewV4().String()
|
||||||
t.PayloadContent = string(data)
|
t.PayloadContent = string(data)
|
||||||
_, err = x.Insert(t)
|
_, err = e.Insert(t)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -497,6 +517,10 @@ func UpdateHookTask(t *HookTask) error {
|
||||||
|
|
||||||
// PrepareWebhook adds special webhook to task queue for given payload.
|
// PrepareWebhook adds special webhook to task queue for given payload.
|
||||||
func PrepareWebhook(w *Webhook, repo *Repository, event HookEventType, p api.Payloader) error {
|
func PrepareWebhook(w *Webhook, repo *Repository, event HookEventType, p api.Payloader) error {
|
||||||
|
return prepareWebhook(x, w, repo, event, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func prepareWebhook(e Engine, w *Webhook, repo *Repository, event HookEventType, p api.Payloader) error {
|
||||||
switch event {
|
switch event {
|
||||||
case HookEventCreate:
|
case HookEventCreate:
|
||||||
if !w.HasCreateEvent() {
|
if !w.HasCreateEvent() {
|
||||||
|
@ -510,6 +534,10 @@ func PrepareWebhook(w *Webhook, repo *Repository, event HookEventType, p api.Pay
|
||||||
if !w.HasPullRequestEvent() {
|
if !w.HasPullRequestEvent() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
case HookEventRepository:
|
||||||
|
if !w.HasRepositoryEvent() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var payloader api.Payloader
|
var payloader api.Payloader
|
||||||
|
@ -531,7 +559,7 @@ func PrepareWebhook(w *Webhook, repo *Repository, event HookEventType, p api.Pay
|
||||||
payloader = p
|
payloader = p
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = CreateHookTask(&HookTask{
|
if err = createHookTask(e, &HookTask{
|
||||||
RepoID: repo.ID,
|
RepoID: repo.ID,
|
||||||
HookID: w.ID,
|
HookID: w.ID,
|
||||||
Type: w.HookTaskType,
|
Type: w.HookTaskType,
|
||||||
|
@ -548,15 +576,19 @@ func PrepareWebhook(w *Webhook, repo *Repository, event HookEventType, p api.Pay
|
||||||
|
|
||||||
// PrepareWebhooks adds new webhooks to task queue for given payload.
|
// PrepareWebhooks adds new webhooks to task queue for given payload.
|
||||||
func PrepareWebhooks(repo *Repository, event HookEventType, p api.Payloader) error {
|
func PrepareWebhooks(repo *Repository, event HookEventType, p api.Payloader) error {
|
||||||
ws, err := GetActiveWebhooksByRepoID(repo.ID)
|
return prepareWebhooks(x, repo, event, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func prepareWebhooks(e Engine, repo *Repository, event HookEventType, p api.Payloader) error {
|
||||||
|
ws, err := getActiveWebhooksByRepoID(e, repo.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("GetActiveWebhooksByRepoID: %v", err)
|
return fmt.Errorf("GetActiveWebhooksByRepoID: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if repo belongs to org and append additional webhooks
|
// check if repo belongs to org and append additional webhooks
|
||||||
if repo.MustOwner().IsOrganization() {
|
if repo.mustOwner(e).IsOrganization() {
|
||||||
// get hooks for org
|
// get hooks for org
|
||||||
orgHooks, err := GetActiveWebhooksByOrgID(repo.OwnerID)
|
orgHooks, err := getActiveWebhooksByOrgID(e, repo.OwnerID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("GetActiveWebhooksByOrgID: %v", err)
|
return fmt.Errorf("GetActiveWebhooksByOrgID: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -568,7 +600,7 @@ func PrepareWebhooks(repo *Repository, event HookEventType, p api.Payloader) err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, w := range ws {
|
for _, w := range ws {
|
||||||
if err = PrepareWebhook(w, repo, event, p); err != nil {
|
if err = prepareWebhook(e, w, repo, event, p); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -228,6 +228,37 @@ func getDiscordPullRequestPayload(p *api.PullRequestPayload, meta *DiscordMeta)
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getDiscordRepositoryPayload(p *api.RepositoryPayload, meta *DiscordMeta) (*DiscordPayload, error) {
|
||||||
|
var title, url string
|
||||||
|
var color int
|
||||||
|
switch p.Action {
|
||||||
|
case api.HookRepoCreated:
|
||||||
|
title = fmt.Sprintf("[%s] Repository created", p.Repository.FullName)
|
||||||
|
url = p.Repository.HTMLURL
|
||||||
|
color = successColor
|
||||||
|
case api.HookRepoDeleted:
|
||||||
|
title = fmt.Sprintf("[%s] Repository deleted", p.Repository.FullName)
|
||||||
|
color = warnColor
|
||||||
|
}
|
||||||
|
|
||||||
|
return &DiscordPayload{
|
||||||
|
Username: meta.Username,
|
||||||
|
AvatarURL: meta.IconURL,
|
||||||
|
Embeds: []DiscordEmbed{
|
||||||
|
{
|
||||||
|
Title: title,
|
||||||
|
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)
|
||||||
|
@ -244,6 +275,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 HookEventRepository:
|
||||||
|
return getDiscordRepositoryPayload(p.(*api.RepositoryPayload), discord)
|
||||||
}
|
}
|
||||||
|
|
||||||
return s, nil
|
return s, nil
|
||||||
|
|
|
@ -189,6 +189,30 @@ func getSlackPullRequestPayload(p *api.PullRequestPayload, slack *SlackMeta) (*S
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getSlackRepositoryPayload(p *api.RepositoryPayload, slack *SlackMeta) (*SlackPayload, error) {
|
||||||
|
senderLink := SlackLinkFormatter(setting.AppURL+p.Sender.UserName, p.Sender.UserName)
|
||||||
|
var text, title, attachmentText string
|
||||||
|
switch p.Action {
|
||||||
|
case api.HookRepoCreated:
|
||||||
|
text = fmt.Sprintf("[%s] Repository created by %s", p.Repository.FullName, senderLink)
|
||||||
|
title = p.Repository.HTMLURL
|
||||||
|
case api.HookRepoDeleted:
|
||||||
|
text = fmt.Sprintf("[%s] Repository deleted by %s", p.Repository.FullName, senderLink)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &SlackPayload{
|
||||||
|
Channel: slack.Channel,
|
||||||
|
Text: text,
|
||||||
|
Username: slack.Username,
|
||||||
|
IconURL: slack.IconURL,
|
||||||
|
Attachments: []SlackAttachment{{
|
||||||
|
Color: slack.Color,
|
||||||
|
Title: title,
|
||||||
|
Text: attachmentText,
|
||||||
|
}},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetSlackPayload converts a slack webhook into a SlackPayload
|
// GetSlackPayload converts a slack webhook into a SlackPayload
|
||||||
func GetSlackPayload(p api.Payloader, event HookEventType, meta string) (*SlackPayload, error) {
|
func GetSlackPayload(p api.Payloader, event HookEventType, meta string) (*SlackPayload, error) {
|
||||||
s := new(SlackPayload)
|
s := new(SlackPayload)
|
||||||
|
@ -205,6 +229,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 HookEventRepository:
|
||||||
|
return getSlackRepositoryPayload(p.(*api.RepositoryPayload), slack)
|
||||||
}
|
}
|
||||||
|
|
||||||
return s, nil
|
return s, nil
|
||||||
|
|
|
@ -124,6 +124,7 @@ type WebhookForm struct {
|
||||||
Create bool
|
Create bool
|
||||||
Push bool
|
Push bool
|
||||||
PullRequest bool
|
PullRequest bool
|
||||||
|
Repository bool
|
||||||
Active bool
|
Active bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -892,6 +892,8 @@ 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
|
||||||
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_desc = Repository created or deleted
|
||||||
settings.active = Active
|
settings.active = Active
|
||||||
settings.active_helper = Information about the event which triggered the hook will be sent as well.
|
settings.active_helper = Information about the event which triggered the hook will be sent as well.
|
||||||
settings.add_hook_success = New webhook has been added.
|
settings.add_hook_success = New webhook has been added.
|
||||||
|
|
|
@ -145,7 +145,7 @@ func Dashboard(ctx *context.Context) {
|
||||||
err = models.DeleteRepositoryArchives()
|
err = models.DeleteRepositoryArchives()
|
||||||
case cleanMissingRepos:
|
case cleanMissingRepos:
|
||||||
success = ctx.Tr("admin.dashboard.delete_missing_repos_success")
|
success = ctx.Tr("admin.dashboard.delete_missing_repos_success")
|
||||||
err = models.DeleteMissingRepositories()
|
err = models.DeleteMissingRepositories(ctx.User)
|
||||||
case gitGCRepos:
|
case gitGCRepos:
|
||||||
success = ctx.Tr("admin.dashboard.git_gc_repos_success")
|
success = ctx.Tr("admin.dashboard.git_gc_repos_success")
|
||||||
err = models.GitGcRepos()
|
err = models.GitGcRepos()
|
||||||
|
|
|
@ -39,7 +39,7 @@ func DeleteRepo(ctx *context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := models.DeleteRepository(repo.MustOwner().ID, repo.ID); err != nil {
|
if err := models.DeleteRepository(ctx.User, repo.MustOwner().ID, repo.ID); err != nil {
|
||||||
ctx.Handle(500, "DeleteRepository", err)
|
ctx.Handle(500, "DeleteRepository", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ func CreateFork(ctx *context.APIContext, form api.CreateForkOption) {
|
||||||
}
|
}
|
||||||
forker = org
|
forker = org
|
||||||
}
|
}
|
||||||
fork, err := models.ForkRepository(forker, repo, repo.Name, repo.Description)
|
fork, err := models.ForkRepository(ctx.User, forker, repo, repo.Name, repo.Description)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(500, "ForkRepository", err)
|
ctx.Error(500, "ForkRepository", err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -105,7 +105,7 @@ func Search(ctx *context.APIContext) {
|
||||||
|
|
||||||
// CreateUserRepo create a repository for a user
|
// CreateUserRepo create a repository for a user
|
||||||
func CreateUserRepo(ctx *context.APIContext, owner *models.User, opt api.CreateRepoOption) {
|
func CreateUserRepo(ctx *context.APIContext, owner *models.User, opt api.CreateRepoOption) {
|
||||||
repo, err := models.CreateRepository(owner, models.CreateRepoOptions{
|
repo, err := models.CreateRepository(ctx.User, owner, models.CreateRepoOptions{
|
||||||
Name: opt.Name,
|
Name: opt.Name,
|
||||||
Description: opt.Description,
|
Description: opt.Description,
|
||||||
Gitignores: opt.Gitignores,
|
Gitignores: opt.Gitignores,
|
||||||
|
@ -121,7 +121,7 @@ func CreateUserRepo(ctx *context.APIContext, owner *models.User, opt api.CreateR
|
||||||
ctx.Error(422, "", err)
|
ctx.Error(422, "", err)
|
||||||
} else {
|
} else {
|
||||||
if repo != nil {
|
if repo != nil {
|
||||||
if err = models.DeleteRepository(ctx.User.ID, repo.ID); err != nil {
|
if err = models.DeleteRepository(ctx.User, ctx.User.ID, repo.ID); err != nil {
|
||||||
log.Error(4, "DeleteRepository: %v", err)
|
log.Error(4, "DeleteRepository: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -254,7 +254,7 @@ func Migrate(ctx *context.APIContext, form auth.MigrateRepoForm) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
repo, err := models.MigrateRepository(ctxUser, models.MigrateRepoOptions{
|
repo, err := models.MigrateRepository(ctx.User, ctxUser, models.MigrateRepoOptions{
|
||||||
Name: form.RepoName,
|
Name: form.RepoName,
|
||||||
Description: form.Description,
|
Description: form.Description,
|
||||||
IsPrivate: form.Private || setting.Repository.ForcePrivate,
|
IsPrivate: form.Private || setting.Repository.ForcePrivate,
|
||||||
|
@ -263,7 +263,7 @@ func Migrate(ctx *context.APIContext, form auth.MigrateRepoForm) {
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if repo != nil {
|
if repo != nil {
|
||||||
if errDelete := models.DeleteRepository(ctxUser.ID, repo.ID); errDelete != nil {
|
if errDelete := models.DeleteRepository(ctx.User, ctxUser.ID, repo.ID); errDelete != nil {
|
||||||
log.Error(4, "DeleteRepository: %v", errDelete)
|
log.Error(4, "DeleteRepository: %v", errDelete)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -345,7 +345,7 @@ func Delete(ctx *context.APIContext) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := models.DeleteRepository(owner.ID, repo.ID); err != nil {
|
if err := models.DeleteRepository(ctx.User, owner.ID, repo.ID); err != nil {
|
||||||
ctx.Error(500, "DeleteRepository", err)
|
ctx.Error(500, "DeleteRepository", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,7 +125,7 @@ func ForkPost(ctx *context.Context, form auth.CreateRepoForm) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
repo, err := models.ForkRepository(ctxUser, forkRepo, form.RepoName, form.Description)
|
repo, err := models.ForkRepository(ctx.User, ctxUser, forkRepo, form.RepoName, form.Description)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Data["Err_RepoName"] = true
|
ctx.Data["Err_RepoName"] = true
|
||||||
switch {
|
switch {
|
||||||
|
|
|
@ -127,7 +127,7 @@ func CreatePost(ctx *context.Context, form auth.CreateRepoForm) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
repo, err := models.CreateRepository(ctxUser, models.CreateRepoOptions{
|
repo, err := models.CreateRepository(ctx.User, ctxUser, models.CreateRepoOptions{
|
||||||
Name: form.RepoName,
|
Name: form.RepoName,
|
||||||
Description: form.Description,
|
Description: form.Description,
|
||||||
Gitignores: form.Gitignores,
|
Gitignores: form.Gitignores,
|
||||||
|
@ -143,7 +143,7 @@ func CreatePost(ctx *context.Context, form auth.CreateRepoForm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if repo != nil {
|
if repo != nil {
|
||||||
if errDelete := models.DeleteRepository(ctxUser.ID, repo.ID); errDelete != nil {
|
if errDelete := models.DeleteRepository(ctx.User, ctxUser.ID, repo.ID); errDelete != nil {
|
||||||
log.Error(4, "DeleteRepository: %v", errDelete)
|
log.Error(4, "DeleteRepository: %v", errDelete)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -204,7 +204,7 @@ func MigratePost(ctx *context.Context, form auth.MigrateRepoForm) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
repo, err := models.MigrateRepository(ctxUser, models.MigrateRepoOptions{
|
repo, err := models.MigrateRepository(ctx.User, ctxUser, models.MigrateRepoOptions{
|
||||||
Name: form.RepoName,
|
Name: form.RepoName,
|
||||||
Description: form.Description,
|
Description: form.Description,
|
||||||
IsPrivate: form.Private || setting.Repository.ForcePrivate,
|
IsPrivate: form.Private || setting.Repository.ForcePrivate,
|
||||||
|
@ -218,7 +218,7 @@ func MigratePost(ctx *context.Context, form auth.MigrateRepoForm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if repo != nil {
|
if repo != nil {
|
||||||
if errDelete := models.DeleteRepository(ctxUser.ID, repo.ID); errDelete != nil {
|
if errDelete := models.DeleteRepository(ctx.User, ctxUser.ID, repo.ID); errDelete != nil {
|
||||||
log.Error(4, "DeleteRepository: %v", errDelete)
|
log.Error(4, "DeleteRepository: %v", errDelete)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -314,7 +314,7 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := models.DeleteRepository(ctx.Repo.Owner.ID, repo.ID); err != nil {
|
if err := models.DeleteRepository(ctx.User, ctx.Repo.Owner.ID, repo.ID); err != nil {
|
||||||
ctx.Handle(500, "DeleteRepository", err)
|
ctx.Handle(500, "DeleteRepository", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,6 +121,7 @@ func ParseHookEvent(form auth.WebhookForm) *models.HookEvent {
|
||||||
Create: form.Create,
|
Create: form.Create,
|
||||||
Push: form.Push,
|
Push: form.Push,
|
||||||
PullRequest: form.PullRequest,
|
PullRequest: form.PullRequest,
|
||||||
|
Repository: form.Repository,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,16 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- Repository -->
|
||||||
|
<div class="seven wide column">
|
||||||
|
<div class="field">
|
||||||
|
<div class="ui checkbox">
|
||||||
|
<input class="hidden" name="repository" type="checkbox" tabindex="0" {{if .Webhook.Repository}}checked{{end}}>
|
||||||
|
<label>{{.i18n.Tr "repo.settings.event_repository"}}</label>
|
||||||
|
<span class="help">{{.i18n.Tr "repo.settings.event_repository_desc"}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue