Skip to content

Commit 7ea4bfc

Browse files
ethantkoeniglunny
authored andcommitted
API endpoint for testing webhook (#3550)
* API endpoint for testing webhook * Empty commit to rerun CI
1 parent 5a62eb3 commit 7ea4bfc

File tree

7 files changed

+165
-5
lines changed

7 files changed

+165
-5
lines changed

models/fixtures/hook_task.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
repo_id: 1
44
hook_id: 1
55
uuid: uuid1
6+
is_delivered: true

modules/test/context_tests.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@ import (
1313
"code.gitea.io/gitea/models"
1414
"code.gitea.io/gitea/modules/context"
1515

16+
"net/http/httptest"
17+
1618
"github.com/go-macaron/session"
1719
"github.com/stretchr/testify/assert"
1820
"gopkg.in/macaron.v1"
19-
"net/http/httptest"
2021
)
2122

2223
// MockContext mock context for unit tests
@@ -48,6 +49,16 @@ func LoadRepo(t *testing.T, ctx *context.Context, repoID int64) {
4849
ctx.Repo.RepoLink = ctx.Repo.Repository.Link()
4950
}
5051

52+
// LoadRepoCommit loads a repo's commit into a test context.
53+
func LoadRepoCommit(t *testing.T, ctx *context.Context) {
54+
gitRepo, err := git.OpenRepository(ctx.Repo.Repository.RepoPath())
55+
assert.NoError(t, err)
56+
branch, err := gitRepo.GetHEADBranch()
57+
assert.NoError(t, err)
58+
ctx.Repo.Commit, err = gitRepo.GetBranchCommit(branch.Name)
59+
assert.NoError(t, err)
60+
}
61+
5162
// LoadUser load a user into a test context.
5263
func LoadUser(t *testing.T, ctx *context.Context, userID int64) {
5364
ctx.User = models.AssertExistsAndLoadBean(t, &models.User{ID: userID}).(*models.User)

public/swagger.v1.json

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1565,6 +1565,46 @@
15651565
}
15661566
}
15671567
},
1568+
"/repos/{owner}/{repo}/hooks/{id}/tests": {
1569+
"post": {
1570+
"produces": [
1571+
"application/json"
1572+
],
1573+
"tags": [
1574+
"repository"
1575+
],
1576+
"summary": "Test a push webhook",
1577+
"operationId": "repoTestHook",
1578+
"parameters": [
1579+
{
1580+
"type": "string",
1581+
"description": "owner of the repo",
1582+
"name": "owner",
1583+
"in": "path",
1584+
"required": true
1585+
},
1586+
{
1587+
"type": "string",
1588+
"description": "name of the repo",
1589+
"name": "repo",
1590+
"in": "path",
1591+
"required": true
1592+
},
1593+
{
1594+
"type": "integer",
1595+
"description": "id of the hook to test",
1596+
"name": "id",
1597+
"in": "path",
1598+
"required": true
1599+
}
1600+
],
1601+
"responses": {
1602+
"204": {
1603+
"$ref": "#/responses/empty"
1604+
}
1605+
}
1606+
}
1607+
},
15681608
"/repos/{owner}/{repo}/issue/{index}/comments": {
15691609
"get": {
15701610
"produces": [

routers/api/v1/api.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -382,9 +382,12 @@ func RegisterRoutes(m *macaron.Macaron) {
382382
m.Group("/hooks", func() {
383383
m.Combo("").Get(repo.ListHooks).
384384
Post(bind(api.CreateHookOption{}), repo.CreateHook)
385-
m.Combo("/:id").Get(repo.GetHook).
386-
Patch(bind(api.EditHookOption{}), repo.EditHook).
387-
Delete(repo.DeleteHook)
385+
m.Group("/:id", func() {
386+
m.Combo("").Get(repo.GetHook).
387+
Patch(bind(api.EditHookOption{}), repo.EditHook).
388+
Delete(repo.DeleteHook)
389+
m.Post("/tests", context.RepoRef(), repo.TestHook)
390+
})
388391
}, reqToken(), reqRepoWriter())
389392
m.Group("/collaborators", func() {
390393
m.Get("", repo.ListCollaborators)

routers/api/v1/repo/hook.go

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
package repo
66

77
import (
8+
"code.gitea.io/git"
89
"code.gitea.io/gitea/models"
910
"code.gitea.io/gitea/modules/context"
1011
"code.gitea.io/gitea/routers/api/v1/convert"
1112
"code.gitea.io/gitea/routers/api/v1/utils"
12-
1313
api "code.gitea.io/sdk/gitea"
1414
)
1515

@@ -82,6 +82,62 @@ func GetHook(ctx *context.APIContext) {
8282
ctx.JSON(200, convert.ToHook(repo.RepoLink, hook))
8383
}
8484

85+
// TestHook tests a hook
86+
func TestHook(ctx *context.APIContext) {
87+
// swagger:operation POST /repos/{owner}/{repo}/hooks/{id}/tests repository repoTestHook
88+
// ---
89+
// summary: Test a push webhook
90+
// produces:
91+
// - application/json
92+
// parameters:
93+
// - name: owner
94+
// in: path
95+
// description: owner of the repo
96+
// type: string
97+
// required: true
98+
// - name: repo
99+
// in: path
100+
// description: name of the repo
101+
// type: string
102+
// required: true
103+
// - name: id
104+
// in: path
105+
// description: id of the hook to test
106+
// type: integer
107+
// required: true
108+
// responses:
109+
// "204":
110+
// "$ref": "#/responses/empty"
111+
if ctx.Repo.Commit == nil {
112+
// if repo does not have any commits, then don't send a webhook
113+
ctx.Status(204)
114+
return
115+
}
116+
117+
hookID := ctx.ParamsInt64(":id")
118+
hook, err := utils.GetRepoHook(ctx, ctx.Repo.Repository.ID, hookID)
119+
if err != nil {
120+
return
121+
}
122+
123+
if err := models.PrepareWebhook(hook, ctx.Repo.Repository, models.HookEventPush, &api.PushPayload{
124+
Ref: git.BranchPrefix + ctx.Repo.Repository.DefaultBranch,
125+
Before: ctx.Repo.Commit.ID.String(),
126+
After: ctx.Repo.Commit.ID.String(),
127+
Commits: []*api.PayloadCommit{
128+
convert.ToCommit(ctx.Repo.Repository, ctx.Repo.Commit),
129+
},
130+
Repo: ctx.Repo.Repository.APIFormat(models.AccessModeNone),
131+
Pusher: ctx.User.APIFormat(),
132+
Sender: ctx.User.APIFormat(),
133+
}); err != nil {
134+
ctx.Error(500, "PrepareWebhook: ", err)
135+
return
136+
}
137+
go models.HookQueue.Add(ctx.Repo.Repository.ID)
138+
ctx.Status(204)
139+
}
140+
85141
// CreateHook create a hook for a repository
86142
func CreateHook(ctx *context.APIContext, form api.CreateHookOption) {
87143
// swagger:operation POST /repos/{owner}/{repo}/hooks repository repoCreateHook

routers/api/v1/repo/hook_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2018 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package repo
6+
7+
import (
8+
"net/http"
9+
"testing"
10+
11+
"code.gitea.io/gitea/models"
12+
"code.gitea.io/gitea/modules/context"
13+
"code.gitea.io/gitea/modules/test"
14+
15+
"github.com/stretchr/testify/assert"
16+
)
17+
18+
func TestTestHook(t *testing.T) {
19+
models.PrepareTestEnv(t)
20+
21+
ctx := test.MockContext(t, "user2/repo1/wiki/_pages")
22+
ctx.SetParams(":id", "1")
23+
test.LoadRepo(t, ctx, 1)
24+
test.LoadRepoCommit(t, ctx)
25+
test.LoadUser(t, ctx, 2)
26+
TestHook(&context.APIContext{Context: ctx, Org: nil})
27+
assert.EqualValues(t, http.StatusNoContent, ctx.Resp.Status())
28+
29+
models.AssertExistsAndLoadBean(t, &models.HookTask{
30+
RepoID: 1,
31+
HookID: 1,
32+
}, models.Cond("is_delivered=?", false))
33+
}

routers/api/v1/repo/main_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2018 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package repo
6+
7+
import (
8+
"path/filepath"
9+
"testing"
10+
11+
"code.gitea.io/gitea/models"
12+
)
13+
14+
func TestMain(m *testing.M) {
15+
models.MainTest(m, filepath.Join("..", "..", "..", ".."))
16+
}

0 commit comments

Comments
 (0)