Browse Source

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>
David Schneiderbauer 2 years ago
parent
commit
1eedd983ea

+ 1 - 0
integrations/gitea-repositories-meta/user2/repo1.git/refs/tags/v1.1

@@ -0,0 +1 @@
1
+65f1bf27bc3bf70f64657658635e66094edbcb4d

+ 41 - 16
models/action.go

@@ -46,6 +46,8 @@ const (
46 46
 	ActionReopenIssue                             // 13
47 47
 	ActionClosePullRequest                        // 14
48 48
 	ActionReopenPullRequest                       // 15
49
+	ActionDeleteTag                               // 16
50
+	ActionDeleteBranch                            // 17
49 51
 )
50 52
 
51 53
 var (
@@ -554,6 +556,12 @@ func CommitRepoAction(opts CommitRepoActionOptions) error {
554 556
 	// Check it's tag push or branch.
555 557
 	if strings.HasPrefix(opts.RefFullName, git.TagPrefix) {
556 558
 		opType = ActionPushTag
559
+		if opts.NewCommitID == git.EmptySHA {
560
+			opType = ActionDeleteTag
561
+		}
562
+		opts.Commits = &PushCommits{}
563
+	} else if opts.NewCommitID == git.EmptySHA {
564
+		opType = ActionDeleteBranch
557 565
 		opts.Commits = &PushCommits{}
558 566
 	} else {
559 567
 		// if not the first commit, set the compare URL.
@@ -599,40 +607,38 @@ func CommitRepoAction(opts CommitRepoActionOptions) error {
599 607
 	apiRepo := repo.APIFormat(AccessModeNone)
600 608
 
601 609
 	var shaSum string
610
+	var isHookEventPush = false
602 611
 	switch opType {
603 612
 	case ActionCommitRepo: // Push
604
-		if err = PrepareWebhooks(repo, HookEventPush, &api.PushPayload{
605
-			Ref:        opts.RefFullName,
606
-			Before:     opts.OldCommitID,
607
-			After:      opts.NewCommitID,
608
-			CompareURL: setting.AppURL + opts.Commits.CompareURL,
609
-			Commits:    opts.Commits.ToAPIPayloadCommits(repo.HTMLURL()),
610
-			Repo:       apiRepo,
611
-			Pusher:     apiPusher,
612
-			Sender:     apiPusher,
613
-		}); err != nil {
614
-			return fmt.Errorf("PrepareWebhooks: %v", err)
615
-		}
613
+		isHookEventPush = true
616 614
 
617 615
 		if isNewBranch {
618 616
 			gitRepo, err := git.OpenRepository(repo.RepoPath())
619 617
 			if err != nil {
620 618
 				log.Error(4, "OpenRepository[%s]: %v", repo.RepoPath(), err)
621 619
 			}
620
+
622 621
 			shaSum, err = gitRepo.GetBranchCommitID(refName)
623 622
 			if err != nil {
624 623
 				log.Error(4, "GetBranchCommitID[%s]: %v", opts.RefFullName, err)
625 624
 			}
626
-			return PrepareWebhooks(repo, HookEventCreate, &api.CreatePayload{
625
+			if err = PrepareWebhooks(repo, HookEventCreate, &api.CreatePayload{
627 626
 				Ref:     refName,
628 627
 				Sha:     shaSum,
629 628
 				RefType: "branch",
630 629
 				Repo:    apiRepo,
631 630
 				Sender:  apiPusher,
632
-			})
631
+			}); err != nil {
632
+				return fmt.Errorf("PrepareWebhooks: %v", err)
633
+			}
633 634
 		}
634 635
 
636
+	case ActionDeleteBranch: // Delete Branch
637
+		isHookEventPush = true
638
+
635 639
 	case ActionPushTag: // Create
640
+		isHookEventPush = true
641
+
636 642
 		gitRepo, err := git.OpenRepository(repo.RepoPath())
637 643
 		if err != nil {
638 644
 			log.Error(4, "OpenRepository[%s]: %v", repo.RepoPath(), err)
@@ -641,13 +647,32 @@ func CommitRepoAction(opts CommitRepoActionOptions) error {
641 647
 		if err != nil {
642 648
 			log.Error(4, "GetTagCommitID[%s]: %v", opts.RefFullName, err)
643 649
 		}
644
-		return PrepareWebhooks(repo, HookEventCreate, &api.CreatePayload{
650
+		if err = PrepareWebhooks(repo, HookEventCreate, &api.CreatePayload{
645 651
 			Ref:     refName,
646 652
 			Sha:     shaSum,
647 653
 			RefType: "tag",
648 654
 			Repo:    apiRepo,
649 655
 			Sender:  apiPusher,
650
-		})
656
+		}); err != nil {
657
+			return fmt.Errorf("PrepareWebhooks: %v", err)
658
+		}
659
+	case ActionDeleteTag: // Delete Tag
660
+		isHookEventPush = true
661
+	}
662
+
663
+	if isHookEventPush {
664
+		if err = PrepareWebhooks(repo, HookEventPush, &api.PushPayload{
665
+			Ref:        opts.RefFullName,
666
+			Before:     opts.OldCommitID,
667
+			After:      opts.NewCommitID,
668
+			CompareURL: setting.AppURL + opts.Commits.CompareURL,
669
+			Commits:    opts.Commits.ToAPIPayloadCommits(repo.HTMLURL()),
670
+			Repo:       apiRepo,
671
+			Pusher:     apiPusher,
672
+			Sender:     apiPusher,
673
+		}); err != nil {
674
+			return fmt.Errorf("PrepareWebhooks: %v", err)
675
+		}
651 676
 	}
652 677
 
653 678
 	return nil

+ 103 - 41
models/action_test.go

@@ -5,6 +5,7 @@ import (
5 5
 	"strings"
6 6
 	"testing"
7 7
 
8
+	"code.gitea.io/git"
8 9
 	"code.gitea.io/gitea/modules/setting"
9 10
 
10 11
 	"github.com/stretchr/testify/assert"
@@ -202,55 +203,116 @@ func TestUpdateIssuesCommit(t *testing.T) {
202 203
 	CheckConsistencyFor(t, &Action{})
203 204
 }
204 205
 
205
-func TestCommitRepoAction(t *testing.T) {
206
-	assert.NoError(t, PrepareTestDatabase())
207
-
208
-	user := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
209
-	repo := AssertExistsAndLoadBean(t, &Repository{ID: 2, OwnerID: user.ID}).(*Repository)
210
-	repo.Owner = user
206
+func testCorrectRepoAction(t *testing.T, opts CommitRepoActionOptions, actionBean *Action) {
207
+	AssertNotExistsBean(t, actionBean)
208
+	assert.NoError(t, CommitRepoAction(opts))
209
+	AssertExistsAndLoadBean(t, actionBean)
210
+	CheckConsistencyFor(t, &Action{})
211
+}
211 212
 
212
-	pushCommits := NewPushCommits()
213
-	pushCommits.Commits = []*PushCommit{
213
+func TestCommitRepoAction(t *testing.T) {
214
+	samples := []struct {
215
+		userID                  int64
216
+		repositoryID            int64
217
+		commitRepoActionOptions CommitRepoActionOptions
218
+		action                  Action
219
+	}{
214 220
 		{
215
-			Sha1:           "abcdef1",
216
-			CommitterEmail: "user2@example.com",
217
-			CommitterName:  "User Two",
218
-			AuthorEmail:    "user4@example.com",
219
-			AuthorName:     "User Four",
220
-			Message:        "message1",
221
+			userID:       2,
222
+			repositoryID: 2,
223
+			commitRepoActionOptions: CommitRepoActionOptions{
224
+				RefFullName: "refName",
225
+				OldCommitID: "oldCommitID",
226
+				NewCommitID: "newCommitID",
227
+				Commits: &PushCommits{
228
+					avatars: make(map[string]string),
229
+					Commits: []*PushCommit{
230
+						{
231
+							Sha1:           "abcdef1",
232
+							CommitterEmail: "user2@example.com",
233
+							CommitterName:  "User Two",
234
+							AuthorEmail:    "user4@example.com",
235
+							AuthorName:     "User Four",
236
+							Message:        "message1",
237
+						},
238
+						{
239
+							Sha1:           "abcdef2",
240
+							CommitterEmail: "user2@example.com",
241
+							CommitterName:  "User Two",
242
+							AuthorEmail:    "user2@example.com",
243
+							AuthorName:     "User Two",
244
+							Message:        "message2",
245
+						},
246
+					},
247
+					Len: 2,
248
+				},
249
+			},
250
+			action: Action{
251
+				OpType:  ActionCommitRepo,
252
+				RefName: "refName",
253
+			},
221 254
 		},
222 255
 		{
223
-			Sha1:           "abcdef2",
224
-			CommitterEmail: "user2@example.com",
225
-			CommitterName:  "User Two",
226
-			AuthorEmail:    "user2@example.com",
227
-			AuthorName:     "User Two",
228
-			Message:        "message2",
256
+			userID:       2,
257
+			repositoryID: 1,
258
+			commitRepoActionOptions: CommitRepoActionOptions{
259
+				RefFullName: git.TagPrefix + "v1.1",
260
+				OldCommitID: git.EmptySHA,
261
+				NewCommitID: "newCommitID",
262
+				Commits:     &PushCommits{},
263
+			},
264
+			action: Action{
265
+				OpType:  ActionPushTag,
266
+				RefName: "v1.1",
267
+			},
268
+		},
269
+		{
270
+			userID:       2,
271
+			repositoryID: 1,
272
+			commitRepoActionOptions: CommitRepoActionOptions{
273
+				RefFullName: git.TagPrefix + "v1.1",
274
+				OldCommitID: "oldCommitID",
275
+				NewCommitID: git.EmptySHA,
276
+				Commits:     &PushCommits{},
277
+			},
278
+			action: Action{
279
+				OpType:  ActionDeleteTag,
280
+				RefName: "v1.1",
281
+			},
282
+		},
283
+		{
284
+			userID:       2,
285
+			repositoryID: 1,
286
+			commitRepoActionOptions: CommitRepoActionOptions{
287
+				RefFullName: git.BranchPrefix + "feature/1",
288
+				OldCommitID: "oldCommitID",
289
+				NewCommitID: git.EmptySHA,
290
+				Commits:     &PushCommits{},
291
+			},
292
+			action: Action{
293
+				OpType:  ActionDeleteBranch,
294
+				RefName: "feature/1",
295
+			},
229 296
 		},
230 297
 	}
231
-	pushCommits.Len = len(pushCommits.Commits)
232 298
 
233
-	actionBean := &Action{
234
-		OpType:    ActionCommitRepo,
235
-		ActUserID: user.ID,
236
-		ActUser:   user,
237
-		RepoID:    repo.ID,
238
-		Repo:      repo,
239
-		RefName:   "refName",
240
-		IsPrivate: repo.IsPrivate,
299
+	for _, s := range samples {
300
+		prepareTestEnv(t)
301
+
302
+		user := AssertExistsAndLoadBean(t, &User{ID: s.userID}).(*User)
303
+		repo := AssertExistsAndLoadBean(t, &Repository{ID: s.repositoryID, OwnerID: user.ID}).(*Repository)
304
+		repo.Owner = user
305
+
306
+		s.commitRepoActionOptions.PusherName = user.Name
307
+		s.commitRepoActionOptions.RepoOwnerID = user.ID
308
+		s.commitRepoActionOptions.RepoName = repo.Name
309
+
310
+		s.action.ActUserID = user.ID
311
+		s.action.RepoID = repo.ID
312
+		s.action.IsPrivate = repo.IsPrivate
313
+
314
+		testCorrectRepoAction(t, s.commitRepoActionOptions, &s.action)
241 315
 	}
242
-	AssertNotExistsBean(t, actionBean)
243
-	assert.NoError(t, CommitRepoAction(CommitRepoActionOptions{
244
-		PusherName:  user.Name,
245
-		RepoOwnerID: user.ID,
246
-		RepoName:    repo.Name,
247
-		RefFullName: "refName",
248
-		OldCommitID: "oldCommitID",
249
-		NewCommitID: "newCommitID",
250
-		Commits:     pushCommits,
251
-	}))
252
-	AssertExistsAndLoadBean(t, actionBean)
253
-	CheckConsistencyFor(t, &Action{})
254 316
 }
255 317
 
256 318
 func TestTransferRepoAction(t *testing.T) {

+ 10 - 0
models/unit_tests.go

@@ -5,8 +5,12 @@
5 5
 package models
6 6
 
7 7
 import (
8
+	"os"
8 9
 	"testing"
9 10
 
11
+	"code.gitea.io/gitea/modules/setting"
12
+
13
+	"github.com/Unknwon/com"
10 14
 	"github.com/go-xorm/core"
11 15
 	"github.com/go-xorm/xorm"
12 16
 	"github.com/stretchr/testify/assert"
@@ -38,6 +42,12 @@ func PrepareTestDatabase() error {
38 42
 	return LoadFixtures()
39 43
 }
40 44
 
45
+func prepareTestEnv(t testing.TB) {
46
+	assert.NoError(t, PrepareTestDatabase())
47
+	assert.NoError(t, os.RemoveAll(setting.RepoRootPath))
48
+	assert.NoError(t, com.CopyDir("../integrations/gitea-repositories-meta", setting.RepoRootPath))
49
+}
50
+
41 51
 type testCond struct {
42 52
 	query interface{}
43 53
 	args  []interface{}

+ 33 - 44
models/update.go

@@ -198,57 +198,46 @@ func pushUpdate(opts PushUpdateOptions) (repo *Repository, err error) {
198 198
 		return nil, fmt.Errorf("OpenRepository: %v", err)
199 199
 	}
200 200
 
201
-	if isDelRef {
202
-		// Tag has been deleted
203
-		if strings.HasPrefix(opts.RefFullName, git.TagPrefix) {
204
-			err = pushUpdateDeleteTag(repo, gitRepo, opts.RefFullName[len(git.TagPrefix):])
205
-			if err != nil {
206
-				return nil, fmt.Errorf("pushUpdateDeleteTag: %v", err)
207
-			}
208
-		}
209
-		log.GitLogger.Info("Reference '%s' has been deleted from '%s/%s' by %s",
210
-			opts.RefFullName, opts.RepoUserName, opts.RepoName, opts.PusherName)
211
-		return repo, nil
212
-	}
213
-
214 201
 	if err = repo.UpdateSize(); err != nil {
215 202
 		log.Error(4, "Failed to update size for repository: %v", err)
216 203
 	}
217 204
 
218
-	// Push tags.
205
+	var commits = &PushCommits{}
219 206
 	if strings.HasPrefix(opts.RefFullName, git.TagPrefix) {
220
-		pushUpdateAddTag(repo, gitRepo, opts.RefFullName[len(git.TagPrefix):])
221
-		if err := CommitRepoAction(CommitRepoActionOptions{
222
-			PusherName:  opts.PusherName,
223
-			RepoOwnerID: owner.ID,
224
-			RepoName:    repo.Name,
225
-			RefFullName: opts.RefFullName,
226
-			OldCommitID: opts.OldCommitID,
227
-			NewCommitID: opts.NewCommitID,
228
-			Commits:     &PushCommits{},
229
-		}); err != nil {
230
-			return nil, fmt.Errorf("CommitRepoAction (tag): %v", err)
207
+		// If is tag reference
208
+		if isDelRef {
209
+			err = pushUpdateDeleteTag(repo, gitRepo, opts.RefFullName[len(git.TagPrefix):])
210
+			if err != nil {
211
+				return nil, fmt.Errorf("pushUpdateDeleteTag: %v", err)
212
+			}
213
+		} else {
214
+			err = pushUpdateAddTag(repo, gitRepo, opts.RefFullName[len(git.TagPrefix):])
215
+			if err != nil {
216
+				return nil, fmt.Errorf("pushUpdateAddTag: %v", err)
217
+			}
231 218
 		}
232
-		return repo, nil
233
-	}
234
-
235
-	newCommit, err := gitRepo.GetCommit(opts.NewCommitID)
236
-	if err != nil {
237
-		return nil, fmt.Errorf("gitRepo.GetCommit: %v", err)
238
-	}
239
-
240
-	// Push new branch.
241
-	var l *list.List
242
-	if isNewRef {
243
-		l, err = newCommit.CommitsBeforeLimit(10)
219
+	} else if !isDelRef {
220
+		// If is branch reference
221
+		newCommit, err := gitRepo.GetCommit(opts.NewCommitID)
244 222
 		if err != nil {
245
-			return nil, fmt.Errorf("newCommit.CommitsBeforeLimit: %v", err)
223
+			return nil, fmt.Errorf("gitRepo.GetCommit: %v", err)
246 224
 		}
247
-	} else {
248
-		l, err = newCommit.CommitsBeforeUntil(opts.OldCommitID)
249
-		if err != nil {
250
-			return nil, fmt.Errorf("newCommit.CommitsBeforeUntil: %v", err)
225
+
226
+		// Push new branch.
227
+		var l *list.List
228
+		if isNewRef {
229
+			l, err = newCommit.CommitsBeforeLimit(10)
230
+			if err != nil {
231
+				return nil, fmt.Errorf("newCommit.CommitsBeforeLimit: %v", err)
232
+			}
233
+		} else {
234
+			l, err = newCommit.CommitsBeforeUntil(opts.OldCommitID)
235
+			if err != nil {
236
+				return nil, fmt.Errorf("newCommit.CommitsBeforeUntil: %v", err)
237
+			}
251 238
 		}
239
+
240
+		commits = ListToPushCommits(l)
252 241
 	}
253 242
 
254 243
 	if err := CommitRepoAction(CommitRepoActionOptions{
@@ -258,9 +247,9 @@ func pushUpdate(opts PushUpdateOptions) (repo *Repository, err error) {
258 247
 		RefFullName: opts.RefFullName,
259 248
 		OldCommitID: opts.OldCommitID,
260 249
 		NewCommitID: opts.NewCommitID,
261
-		Commits:     ListToPushCommits(l),
250
+		Commits:     commits,
262 251
 	}); err != nil {
263
-		return nil, fmt.Errorf("CommitRepoAction (branch): %v", err)
252
+		return nil, fmt.Errorf("CommitRepoAction: %v", err)
264 253
 	}
265 254
 	return repo, nil
266 255
 }

+ 1 - 1
modules/templates/helper.go

@@ -294,7 +294,7 @@ func ActionIcon(opType models.ActionType) string {
294 294
 	switch opType {
295 295
 	case models.ActionCreateRepo, models.ActionTransferRepo:
296 296
 		return "repo"
297
-	case models.ActionCommitRepo, models.ActionPushTag:
297
+	case models.ActionCommitRepo, models.ActionPushTag, models.ActionDeleteTag, models.ActionDeleteBranch:
298 298
 		return "git-commit"
299 299
 	case models.ActionCreateIssue:
300 300
 		return "issue-opened"

+ 2 - 0
options/locale/locale_en-US.ini

@@ -1436,6 +1436,8 @@ comment_issue = `commented on issue <a href="%s/issues/%s">%s#%[2]s</a>`
1436 1436
 merge_pull_request = `merged pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
1437 1437
 transfer_repo = transferred repository <code>%s</code> to <a href="%s">%s</a>
1438 1438
 push_tag = pushed tag <a href="%s/src/%s">%[2]s</a> to <a href="%[1]s">%[3]s</a>
1439
+delete_tag = deleted tag %[2]s from <a href="%[1]s">%[3]s</a>
1440
+delete_branch = deleted branch %[2]s from <a href="%[1]s">%[3]s</a>
1439 1441
 compare_commits = Compare %d commits
1440 1442
 
1441 1443
 [tool]

+ 6 - 0
templates/user/dashboard/feeds.tmpl

@@ -43,6 +43,12 @@
43 43
 						{{else if eq .GetOpType 15}}
44 44
 							{{ $index := index .GetIssueInfos 0}}
45 45
 							{{$.i18n.Tr "action.reopen_pull_request" .GetRepoLink $index .ShortRepoPath | Str2html}}
46
+						{{else if eq .GetOpType 16}}
47
+							{{ $index := index .GetIssueInfos 0}}
48
+							{{$.i18n.Tr "action.delete_tag" .GetRepoLink .GetBranch .ShortRepoPath | Str2html}}
49
+						{{else if eq .GetOpType 17}}
50
+							{{ $index := index .GetIssueInfos 0}}
51
+							{{$.i18n.Tr "action.delete_branch" .GetRepoLink .GetBranch .ShortRepoPath | Str2html}}
46 52
 						{{end}}
47 53
 					</p>
48 54
 					{{if eq .GetOpType 5}}