mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-11-25 14:35:40 +00:00
Complete push webhooks (#2530)
* implemented missing 'delete' push webhooks moreover created ActionDeleteBranch and ActionDeleteTag * add CommitRepoAction tests for tag/branch creation/deletion * fixed error where push webhook not called if is new branch or tag removed unnecessary code * moved prepare unit test environment into separate method to be used across unit tests * add missing if clause in pushUpdate Signed-off-by: David Schneiderbauer <dschneiderbauer@gmail.com>
This commit is contained in:
parent
0d80af649a
commit
1eedd983ea
|
@ -0,0 +1 @@
|
|||
65f1bf27bc3bf70f64657658635e66094edbcb4d
|
|
@ -46,6 +46,8 @@ const (
|
|||
ActionReopenIssue // 13
|
||||
ActionClosePullRequest // 14
|
||||
ActionReopenPullRequest // 15
|
||||
ActionDeleteTag // 16
|
||||
ActionDeleteBranch // 17
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -554,6 +556,12 @@ func CommitRepoAction(opts CommitRepoActionOptions) error {
|
|||
// Check it's tag push or branch.
|
||||
if strings.HasPrefix(opts.RefFullName, git.TagPrefix) {
|
||||
opType = ActionPushTag
|
||||
if opts.NewCommitID == git.EmptySHA {
|
||||
opType = ActionDeleteTag
|
||||
}
|
||||
opts.Commits = &PushCommits{}
|
||||
} else if opts.NewCommitID == git.EmptySHA {
|
||||
opType = ActionDeleteBranch
|
||||
opts.Commits = &PushCommits{}
|
||||
} else {
|
||||
// if not the first commit, set the compare URL.
|
||||
|
@ -599,8 +607,60 @@ func CommitRepoAction(opts CommitRepoActionOptions) error {
|
|||
apiRepo := repo.APIFormat(AccessModeNone)
|
||||
|
||||
var shaSum string
|
||||
var isHookEventPush = false
|
||||
switch opType {
|
||||
case ActionCommitRepo: // Push
|
||||
isHookEventPush = true
|
||||
|
||||
if isNewBranch {
|
||||
gitRepo, err := git.OpenRepository(repo.RepoPath())
|
||||
if err != nil {
|
||||
log.Error(4, "OpenRepository[%s]: %v", repo.RepoPath(), err)
|
||||
}
|
||||
|
||||
shaSum, err = gitRepo.GetBranchCommitID(refName)
|
||||
if err != nil {
|
||||
log.Error(4, "GetBranchCommitID[%s]: %v", opts.RefFullName, err)
|
||||
}
|
||||
if err = PrepareWebhooks(repo, HookEventCreate, &api.CreatePayload{
|
||||
Ref: refName,
|
||||
Sha: shaSum,
|
||||
RefType: "branch",
|
||||
Repo: apiRepo,
|
||||
Sender: apiPusher,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("PrepareWebhooks: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
case ActionDeleteBranch: // Delete Branch
|
||||
isHookEventPush = true
|
||||
|
||||
case ActionPushTag: // Create
|
||||
isHookEventPush = true
|
||||
|
||||
gitRepo, err := git.OpenRepository(repo.RepoPath())
|
||||
if err != nil {
|
||||
log.Error(4, "OpenRepository[%s]: %v", repo.RepoPath(), err)
|
||||
}
|
||||
shaSum, err = gitRepo.GetTagCommitID(refName)
|
||||
if err != nil {
|
||||
log.Error(4, "GetTagCommitID[%s]: %v", opts.RefFullName, err)
|
||||
}
|
||||
if err = PrepareWebhooks(repo, HookEventCreate, &api.CreatePayload{
|
||||
Ref: refName,
|
||||
Sha: shaSum,
|
||||
RefType: "tag",
|
||||
Repo: apiRepo,
|
||||
Sender: apiPusher,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("PrepareWebhooks: %v", err)
|
||||
}
|
||||
case ActionDeleteTag: // Delete Tag
|
||||
isHookEventPush = true
|
||||
}
|
||||
|
||||
if isHookEventPush {
|
||||
if err = PrepareWebhooks(repo, HookEventPush, &api.PushPayload{
|
||||
Ref: opts.RefFullName,
|
||||
Before: opts.OldCommitID,
|
||||
|
@ -613,41 +673,6 @@ func CommitRepoAction(opts CommitRepoActionOptions) error {
|
|||
}); err != nil {
|
||||
return fmt.Errorf("PrepareWebhooks: %v", err)
|
||||
}
|
||||
|
||||
if isNewBranch {
|
||||
gitRepo, err := git.OpenRepository(repo.RepoPath())
|
||||
if err != nil {
|
||||
log.Error(4, "OpenRepository[%s]: %v", repo.RepoPath(), err)
|
||||
}
|
||||
shaSum, err = gitRepo.GetBranchCommitID(refName)
|
||||
if err != nil {
|
||||
log.Error(4, "GetBranchCommitID[%s]: %v", opts.RefFullName, err)
|
||||
}
|
||||
return PrepareWebhooks(repo, HookEventCreate, &api.CreatePayload{
|
||||
Ref: refName,
|
||||
Sha: shaSum,
|
||||
RefType: "branch",
|
||||
Repo: apiRepo,
|
||||
Sender: apiPusher,
|
||||
})
|
||||
}
|
||||
|
||||
case ActionPushTag: // Create
|
||||
gitRepo, err := git.OpenRepository(repo.RepoPath())
|
||||
if err != nil {
|
||||
log.Error(4, "OpenRepository[%s]: %v", repo.RepoPath(), err)
|
||||
}
|
||||
shaSum, err = gitRepo.GetTagCommitID(refName)
|
||||
if err != nil {
|
||||
log.Error(4, "GetTagCommitID[%s]: %v", opts.RefFullName, err)
|
||||
}
|
||||
return PrepareWebhooks(repo, HookEventCreate, &api.CreatePayload{
|
||||
Ref: refName,
|
||||
Sha: shaSum,
|
||||
RefType: "tag",
|
||||
Repo: apiRepo,
|
||||
Sender: apiPusher,
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/git"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -202,57 +203,118 @@ func TestUpdateIssuesCommit(t *testing.T) {
|
|||
CheckConsistencyFor(t, &Action{})
|
||||
}
|
||||
|
||||
func TestCommitRepoAction(t *testing.T) {
|
||||
assert.NoError(t, PrepareTestDatabase())
|
||||
|
||||
user := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
|
||||
repo := AssertExistsAndLoadBean(t, &Repository{ID: 2, OwnerID: user.ID}).(*Repository)
|
||||
repo.Owner = user
|
||||
|
||||
pushCommits := NewPushCommits()
|
||||
pushCommits.Commits = []*PushCommit{
|
||||
{
|
||||
Sha1: "abcdef1",
|
||||
CommitterEmail: "user2@example.com",
|
||||
CommitterName: "User Two",
|
||||
AuthorEmail: "user4@example.com",
|
||||
AuthorName: "User Four",
|
||||
Message: "message1",
|
||||
},
|
||||
{
|
||||
Sha1: "abcdef2",
|
||||
CommitterEmail: "user2@example.com",
|
||||
CommitterName: "User Two",
|
||||
AuthorEmail: "user2@example.com",
|
||||
AuthorName: "User Two",
|
||||
Message: "message2",
|
||||
},
|
||||
}
|
||||
pushCommits.Len = len(pushCommits.Commits)
|
||||
|
||||
actionBean := &Action{
|
||||
OpType: ActionCommitRepo,
|
||||
ActUserID: user.ID,
|
||||
ActUser: user,
|
||||
RepoID: repo.ID,
|
||||
Repo: repo,
|
||||
RefName: "refName",
|
||||
IsPrivate: repo.IsPrivate,
|
||||
}
|
||||
func testCorrectRepoAction(t *testing.T, opts CommitRepoActionOptions, actionBean *Action) {
|
||||
AssertNotExistsBean(t, actionBean)
|
||||
assert.NoError(t, CommitRepoAction(CommitRepoActionOptions{
|
||||
PusherName: user.Name,
|
||||
RepoOwnerID: user.ID,
|
||||
RepoName: repo.Name,
|
||||
RefFullName: "refName",
|
||||
OldCommitID: "oldCommitID",
|
||||
NewCommitID: "newCommitID",
|
||||
Commits: pushCommits,
|
||||
}))
|
||||
assert.NoError(t, CommitRepoAction(opts))
|
||||
AssertExistsAndLoadBean(t, actionBean)
|
||||
CheckConsistencyFor(t, &Action{})
|
||||
}
|
||||
|
||||
func TestCommitRepoAction(t *testing.T) {
|
||||
samples := []struct {
|
||||
userID int64
|
||||
repositoryID int64
|
||||
commitRepoActionOptions CommitRepoActionOptions
|
||||
action Action
|
||||
}{
|
||||
{
|
||||
userID: 2,
|
||||
repositoryID: 2,
|
||||
commitRepoActionOptions: CommitRepoActionOptions{
|
||||
RefFullName: "refName",
|
||||
OldCommitID: "oldCommitID",
|
||||
NewCommitID: "newCommitID",
|
||||
Commits: &PushCommits{
|
||||
avatars: make(map[string]string),
|
||||
Commits: []*PushCommit{
|
||||
{
|
||||
Sha1: "abcdef1",
|
||||
CommitterEmail: "user2@example.com",
|
||||
CommitterName: "User Two",
|
||||
AuthorEmail: "user4@example.com",
|
||||
AuthorName: "User Four",
|
||||
Message: "message1",
|
||||
},
|
||||
{
|
||||
Sha1: "abcdef2",
|
||||
CommitterEmail: "user2@example.com",
|
||||
CommitterName: "User Two",
|
||||
AuthorEmail: "user2@example.com",
|
||||
AuthorName: "User Two",
|
||||
Message: "message2",
|
||||
},
|
||||
},
|
||||
Len: 2,
|
||||
},
|
||||
},
|
||||
action: Action{
|
||||
OpType: ActionCommitRepo,
|
||||
RefName: "refName",
|
||||
},
|
||||
},
|
||||
{
|
||||
userID: 2,
|
||||
repositoryID: 1,
|
||||
commitRepoActionOptions: CommitRepoActionOptions{
|
||||
RefFullName: git.TagPrefix + "v1.1",
|
||||
OldCommitID: git.EmptySHA,
|
||||
NewCommitID: "newCommitID",
|
||||
Commits: &PushCommits{},
|
||||
},
|
||||
action: Action{
|
||||
OpType: ActionPushTag,
|
||||
RefName: "v1.1",
|
||||
},
|
||||
},
|
||||
{
|
||||
userID: 2,
|
||||
repositoryID: 1,
|
||||
commitRepoActionOptions: CommitRepoActionOptions{
|
||||
RefFullName: git.TagPrefix + "v1.1",
|
||||
OldCommitID: "oldCommitID",
|
||||
NewCommitID: git.EmptySHA,
|
||||
Commits: &PushCommits{},
|
||||
},
|
||||
action: Action{
|
||||
OpType: ActionDeleteTag,
|
||||
RefName: "v1.1",
|
||||
},
|
||||
},
|
||||
{
|
||||
userID: 2,
|
||||
repositoryID: 1,
|
||||
commitRepoActionOptions: CommitRepoActionOptions{
|
||||
RefFullName: git.BranchPrefix + "feature/1",
|
||||
OldCommitID: "oldCommitID",
|
||||
NewCommitID: git.EmptySHA,
|
||||
Commits: &PushCommits{},
|
||||
},
|
||||
action: Action{
|
||||
OpType: ActionDeleteBranch,
|
||||
RefName: "feature/1",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, s := range samples {
|
||||
prepareTestEnv(t)
|
||||
|
||||
user := AssertExistsAndLoadBean(t, &User{ID: s.userID}).(*User)
|
||||
repo := AssertExistsAndLoadBean(t, &Repository{ID: s.repositoryID, OwnerID: user.ID}).(*Repository)
|
||||
repo.Owner = user
|
||||
|
||||
s.commitRepoActionOptions.PusherName = user.Name
|
||||
s.commitRepoActionOptions.RepoOwnerID = user.ID
|
||||
s.commitRepoActionOptions.RepoName = repo.Name
|
||||
|
||||
s.action.ActUserID = user.ID
|
||||
s.action.RepoID = repo.ID
|
||||
s.action.IsPrivate = repo.IsPrivate
|
||||
|
||||
testCorrectRepoAction(t, s.commitRepoActionOptions, &s.action)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTransferRepoAction(t *testing.T) {
|
||||
assert.NoError(t, PrepareTestDatabase())
|
||||
|
||||
|
|
|
@ -5,8 +5,12 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/go-xorm/core"
|
||||
"github.com/go-xorm/xorm"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -38,6 +42,12 @@ func PrepareTestDatabase() error {
|
|||
return LoadFixtures()
|
||||
}
|
||||
|
||||
func prepareTestEnv(t testing.TB) {
|
||||
assert.NoError(t, PrepareTestDatabase())
|
||||
assert.NoError(t, os.RemoveAll(setting.RepoRootPath))
|
||||
assert.NoError(t, com.CopyDir("../integrations/gitea-repositories-meta", setting.RepoRootPath))
|
||||
}
|
||||
|
||||
type testCond struct {
|
||||
query interface{}
|
||||
args []interface{}
|
||||
|
|
|
@ -198,57 +198,46 @@ func pushUpdate(opts PushUpdateOptions) (repo *Repository, err error) {
|
|||
return nil, fmt.Errorf("OpenRepository: %v", err)
|
||||
}
|
||||
|
||||
if isDelRef {
|
||||
// Tag has been deleted
|
||||
if strings.HasPrefix(opts.RefFullName, git.TagPrefix) {
|
||||
err = pushUpdateDeleteTag(repo, gitRepo, opts.RefFullName[len(git.TagPrefix):])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("pushUpdateDeleteTag: %v", err)
|
||||
}
|
||||
}
|
||||
log.GitLogger.Info("Reference '%s' has been deleted from '%s/%s' by %s",
|
||||
opts.RefFullName, opts.RepoUserName, opts.RepoName, opts.PusherName)
|
||||
return repo, nil
|
||||
}
|
||||
|
||||
if err = repo.UpdateSize(); err != nil {
|
||||
log.Error(4, "Failed to update size for repository: %v", err)
|
||||
}
|
||||
|
||||
// Push tags.
|
||||
var commits = &PushCommits{}
|
||||
if strings.HasPrefix(opts.RefFullName, git.TagPrefix) {
|
||||
pushUpdateAddTag(repo, gitRepo, opts.RefFullName[len(git.TagPrefix):])
|
||||
if err := CommitRepoAction(CommitRepoActionOptions{
|
||||
PusherName: opts.PusherName,
|
||||
RepoOwnerID: owner.ID,
|
||||
RepoName: repo.Name,
|
||||
RefFullName: opts.RefFullName,
|
||||
OldCommitID: opts.OldCommitID,
|
||||
NewCommitID: opts.NewCommitID,
|
||||
Commits: &PushCommits{},
|
||||
}); err != nil {
|
||||
return nil, fmt.Errorf("CommitRepoAction (tag): %v", err)
|
||||
// If is tag reference
|
||||
if isDelRef {
|
||||
err = pushUpdateDeleteTag(repo, gitRepo, opts.RefFullName[len(git.TagPrefix):])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("pushUpdateDeleteTag: %v", err)
|
||||
}
|
||||
} else {
|
||||
err = pushUpdateAddTag(repo, gitRepo, opts.RefFullName[len(git.TagPrefix):])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("pushUpdateAddTag: %v", err)
|
||||
}
|
||||
}
|
||||
return repo, nil
|
||||
}
|
||||
|
||||
newCommit, err := gitRepo.GetCommit(opts.NewCommitID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("gitRepo.GetCommit: %v", err)
|
||||
}
|
||||
|
||||
// Push new branch.
|
||||
var l *list.List
|
||||
if isNewRef {
|
||||
l, err = newCommit.CommitsBeforeLimit(10)
|
||||
} else if !isDelRef {
|
||||
// If is branch reference
|
||||
newCommit, err := gitRepo.GetCommit(opts.NewCommitID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("newCommit.CommitsBeforeLimit: %v", err)
|
||||
return nil, fmt.Errorf("gitRepo.GetCommit: %v", err)
|
||||
}
|
||||
} else {
|
||||
l, err = newCommit.CommitsBeforeUntil(opts.OldCommitID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("newCommit.CommitsBeforeUntil: %v", err)
|
||||
|
||||
// Push new branch.
|
||||
var l *list.List
|
||||
if isNewRef {
|
||||
l, err = newCommit.CommitsBeforeLimit(10)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("newCommit.CommitsBeforeLimit: %v", err)
|
||||
}
|
||||
} else {
|
||||
l, err = newCommit.CommitsBeforeUntil(opts.OldCommitID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("newCommit.CommitsBeforeUntil: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
commits = ListToPushCommits(l)
|
||||
}
|
||||
|
||||
if err := CommitRepoAction(CommitRepoActionOptions{
|
||||
|
@ -258,9 +247,9 @@ func pushUpdate(opts PushUpdateOptions) (repo *Repository, err error) {
|
|||
RefFullName: opts.RefFullName,
|
||||
OldCommitID: opts.OldCommitID,
|
||||
NewCommitID: opts.NewCommitID,
|
||||
Commits: ListToPushCommits(l),
|
||||
Commits: commits,
|
||||
}); err != nil {
|
||||
return nil, fmt.Errorf("CommitRepoAction (branch): %v", err)
|
||||
return nil, fmt.Errorf("CommitRepoAction: %v", err)
|
||||
}
|
||||
return repo, nil
|
||||
}
|
||||
|
|
|
@ -294,7 +294,7 @@ func ActionIcon(opType models.ActionType) string {
|
|||
switch opType {
|
||||
case models.ActionCreateRepo, models.ActionTransferRepo:
|
||||
return "repo"
|
||||
case models.ActionCommitRepo, models.ActionPushTag:
|
||||
case models.ActionCommitRepo, models.ActionPushTag, models.ActionDeleteTag, models.ActionDeleteBranch:
|
||||
return "git-commit"
|
||||
case models.ActionCreateIssue:
|
||||
return "issue-opened"
|
||||
|
|
|
@ -1436,6 +1436,8 @@ comment_issue = `commented on issue <a href="%s/issues/%s">%s#%[2]s</a>`
|
|||
merge_pull_request = `merged pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
|
||||
transfer_repo = transferred repository <code>%s</code> to <a href="%s">%s</a>
|
||||
push_tag = pushed tag <a href="%s/src/%s">%[2]s</a> to <a href="%[1]s">%[3]s</a>
|
||||
delete_tag = deleted tag %[2]s from <a href="%[1]s">%[3]s</a>
|
||||
delete_branch = deleted branch %[2]s from <a href="%[1]s">%[3]s</a>
|
||||
compare_commits = Compare %d commits
|
||||
|
||||
[tool]
|
||||
|
|
|
@ -43,6 +43,12 @@
|
|||
{{else if eq .GetOpType 15}}
|
||||
{{ $index := index .GetIssueInfos 0}}
|
||||
{{$.i18n.Tr "action.reopen_pull_request" .GetRepoLink $index .ShortRepoPath | Str2html}}
|
||||
{{else if eq .GetOpType 16}}
|
||||
{{ $index := index .GetIssueInfos 0}}
|
||||
{{$.i18n.Tr "action.delete_tag" .GetRepoLink .GetBranch .ShortRepoPath | Str2html}}
|
||||
{{else if eq .GetOpType 17}}
|
||||
{{ $index := index .GetIssueInfos 0}}
|
||||
{{$.i18n.Tr "action.delete_branch" .GetRepoLink .GetBranch .ShortRepoPath | Str2html}}
|
||||
{{end}}
|
||||
</p>
|
||||
{{if eq .GetOpType 5}}
|
||||
|
|
Loading…
Reference in a new issue