add:hooktasks
This commit is contained in:
parent
b3399ea04d
commit
27b4478da0
|
@ -77,6 +77,13 @@ func IsValidHookContentType(name string) bool {
|
|||
return ok
|
||||
}
|
||||
|
||||
func IsValidHookHttpMethod(name string) bool {
|
||||
if name == "POST" || name == "GET" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// HookEvents is a set of web hook events
|
||||
type HookEvents struct {
|
||||
Create bool `json:"create"`
|
||||
|
@ -151,6 +158,7 @@ type Webhook struct {
|
|||
Type HookType `xorm:"VARCHAR(16) 'type'"`
|
||||
Meta string `xorm:"TEXT"` // store hook-specific attributes
|
||||
LastStatus HookStatus // Last delivery status
|
||||
BranchFilter string `xorm:"TEXT"`
|
||||
|
||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
|
||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
|
||||
|
@ -647,16 +655,23 @@ type HookResponse struct {
|
|||
|
||||
// HookTask represents a hook task.
|
||||
type HookTask struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
RepoID int64 `xorm:"INDEX"`
|
||||
HookID int64
|
||||
UUID string
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
RepoID int64 `xorm:"INDEX"`
|
||||
HookID int64
|
||||
UUID string
|
||||
|
||||
Type HookType
|
||||
URL string `xorm:"TEXT"`
|
||||
Signature string `xorm:"TEXT"`
|
||||
HTTPMethod string `xorm:"http_method"`
|
||||
ContentType HookContentType
|
||||
api.Payloader `xorm:"-"`
|
||||
PayloadContent string `xorm:"TEXT"`
|
||||
EventType HookEventType
|
||||
IsDelivered bool
|
||||
Delivered int64
|
||||
DeliveredString string `xorm:"-"`
|
||||
IsSSL bool
|
||||
|
||||
// History info.
|
||||
IsSucceed bool
|
||||
|
@ -708,6 +723,18 @@ func (t *HookTask) simpleMarshalJSON(v interface{}) string {
|
|||
return string(p)
|
||||
}
|
||||
|
||||
func GetHookTasksByRepoIDAndHookID(repoID int64, hookID int64, listOptions ListOptions) ([]*HookTask, error) {
|
||||
if listOptions.Page == 0 {
|
||||
hookTasks := make([]*HookTask, 0, 5)
|
||||
return hookTasks, x.Find(&hookTasks, &HookTask{RepoID: repoID, HookID: hookID})
|
||||
}
|
||||
|
||||
sess := listOptions.getPaginatedSession()
|
||||
hookTasks := make([]*HookTask, 0, listOptions.PageSize)
|
||||
|
||||
return hookTasks, sess.Find(&hookTasks, &HookTask{RepoID: repoID, HookID: hookID})
|
||||
}
|
||||
|
||||
// HookTasks returns a list of hook tasks by given conditions.
|
||||
func HookTasks(hookID int64, page int) ([]*HookTask, error) {
|
||||
tasks := make([]*HookTask, 0, setting.Webhook.PagingNum)
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
package convert
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -273,6 +274,7 @@ func ToHook(repoLink string, w *models.Webhook) *api.Hook {
|
|||
config := map[string]string{
|
||||
"url": w.URL,
|
||||
"content_type": w.ContentType.Name(),
|
||||
"http_method": w.HTTPMethod,
|
||||
}
|
||||
if w.Type == models.SLACK {
|
||||
s := webhook.GetSlackHook(w)
|
||||
|
@ -283,14 +285,45 @@ func ToHook(repoLink string, w *models.Webhook) *api.Hook {
|
|||
}
|
||||
|
||||
return &api.Hook{
|
||||
ID: w.ID,
|
||||
Type: string(w.Type),
|
||||
URL: fmt.Sprintf("%s/settings/hooks/%d", repoLink, w.ID),
|
||||
Active: w.IsActive,
|
||||
Config: config,
|
||||
Events: w.EventsArray(),
|
||||
Updated: w.UpdatedUnix.AsTime(),
|
||||
Created: w.CreatedUnix.AsTime(),
|
||||
ID: w.ID,
|
||||
Type: string(w.Type),
|
||||
URL: fmt.Sprintf("%s/settings/hooks/%d", repoLink, w.ID),
|
||||
Active: w.IsActive,
|
||||
Config: config,
|
||||
Events: w.EventsArray(),
|
||||
Updated: w.UpdatedUnix.AsTime(),
|
||||
Created: w.CreatedUnix.AsTime(),
|
||||
BranchFilter: w.HookEvent.BranchFilter,
|
||||
}
|
||||
}
|
||||
|
||||
func ToHookTask(t *models.HookTask) *api.HookTask {
|
||||
config := map[string]string{
|
||||
"url": t.URL,
|
||||
"content_type": t.ContentType.Name(),
|
||||
"http_method": t.HTTPMethod,
|
||||
}
|
||||
|
||||
payloadContent := make(map[string]interface{})
|
||||
requestContent := make(map[string]interface{})
|
||||
responseContent := make(map[string]interface{})
|
||||
_ = json.Unmarshal([]byte(t.PayloadContent), &payloadContent)
|
||||
_ = json.Unmarshal([]byte(t.RequestContent), &requestContent)
|
||||
_ = json.Unmarshal([]byte(t.ResponseContent), &responseContent)
|
||||
|
||||
return &api.HookTask{
|
||||
ID: t.ID,
|
||||
UUID: t.UUID,
|
||||
Type: string(t.Type),
|
||||
Config: config,
|
||||
PayloadContent: payloadContent,
|
||||
EventType: string(t.EventType),
|
||||
IsSSL: t.IsSSL,
|
||||
IsDelivered: t.IsDelivered,
|
||||
Delivered: t.Delivered,
|
||||
IsSucceed: t.IsSucceed,
|
||||
RequestContent: requestContent,
|
||||
ResponseContent: responseContent,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,18 +20,34 @@ var (
|
|||
|
||||
// Hook a hook is a web hook when one repository changed
|
||||
type Hook struct {
|
||||
ID int64 `json:"id"`
|
||||
Type string `json:"type"`
|
||||
URL string `json:"-"`
|
||||
Config map[string]string `json:"config"`
|
||||
Events []string `json:"events"`
|
||||
Active bool `json:"active"`
|
||||
ID int64 `json:"id"`
|
||||
Type string `json:"type"`
|
||||
URL string `json:"-"`
|
||||
Config map[string]string `json:"config"`
|
||||
Events []string `json:"events"`
|
||||
Active bool `json:"active"`
|
||||
BranchFilter string `json:"branch_filter"`
|
||||
// swagger:strfmt date-time
|
||||
Updated time.Time `json:"updated_at"`
|
||||
// swagger:strfmt date-time
|
||||
Created time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
type HookTask struct {
|
||||
ID int64 `json:"id"`
|
||||
UUID string `json:"uuid"`
|
||||
Type string `json:"type"`
|
||||
Config map[string]string `json:"config"`
|
||||
PayloadContent map[string]interface{} `json:"payload_content"`
|
||||
EventType string `json:"event_type"`
|
||||
IsSSL bool `json:"is_ssl"`
|
||||
IsDelivered bool `json:"is_delivered"`
|
||||
Delivered int64 `json:"delivered"`
|
||||
IsSucceed bool `json:"is_succeed"`
|
||||
RequestContent map[string]interface{} `json:"request_info"`
|
||||
ResponseContent map[string]interface{} `json:"response_content"`
|
||||
}
|
||||
|
||||
// HookList represents a list of API hook.
|
||||
type HookList []*Hook
|
||||
|
||||
|
|
|
@ -747,6 +747,7 @@ func Routes() *web.Route {
|
|||
Patch(bind(api.EditHookOption{}), repo.EditHook).
|
||||
Delete(repo.DeleteHook)
|
||||
m.Post("/tests", context.RepoRefForAPI, repo.TestHook)
|
||||
m.Get("/hooktasks", repo.ListHookTask)
|
||||
})
|
||||
}, reqToken(), reqAdmin(), reqWebhooksEnabled())
|
||||
m.Group("/collaborators", func() {
|
||||
|
|
|
@ -16,6 +16,7 @@ import (
|
|||
"code.gitea.io/gitea/modules/web"
|
||||
"code.gitea.io/gitea/routers/api/v1/utils"
|
||||
"code.gitea.io/gitea/services/webhook"
|
||||
// "code.gitea.io/gitea/"
|
||||
)
|
||||
|
||||
// ListHooks list all hooks of a repository
|
||||
|
@ -269,3 +270,57 @@ func DeleteHook(ctx *context.APIContext) {
|
|||
}
|
||||
ctx.Status(http.StatusNoContent)
|
||||
}
|
||||
|
||||
func ListHookTask(ctx *context.APIContext) {
|
||||
// swagger:operation GET /repos/{owner}/{repo}/hooks/{id}/hooktasks repository repoGetHookTasks
|
||||
// ---
|
||||
// summary: Get a hooktasks ***
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: owner
|
||||
// in: path
|
||||
// description: owner of the repo
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: repo
|
||||
// in: path
|
||||
// description: name of the repo
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: id
|
||||
// in: path
|
||||
// description: id of the hook
|
||||
// type: integer
|
||||
// format: int64
|
||||
// required: true
|
||||
// - name: page
|
||||
// in: query
|
||||
// description: page number of results to return (1-based)
|
||||
// type: integer
|
||||
// - name: limit
|
||||
// in: query
|
||||
// description: page size of results
|
||||
// type: integer
|
||||
// responses:
|
||||
// "200":
|
||||
// "$ref": "#/responses/HookTaskList"
|
||||
|
||||
hook, err := utils.GetRepoHook(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":id"))
|
||||
if err != nil {
|
||||
ctx.NotFound()
|
||||
return
|
||||
}
|
||||
hookTasks, err := models.GetHookTasksByRepoIDAndHookID(ctx.Repo.Repository.ID, hook.ID, utils.GetListOptions(ctx))
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "GetHookTasksByRepoIDAndHookID", err)
|
||||
return
|
||||
}
|
||||
|
||||
apiHookTasks := make([]*api.HookTask, len(hookTasks))
|
||||
for i := range hookTasks {
|
||||
apiHookTasks[i] = convert.ToHookTask(hookTasks[i])
|
||||
}
|
||||
|
||||
ctx.JSON(http.StatusOK, &apiHookTasks)
|
||||
}
|
||||
|
|
|
@ -119,6 +119,13 @@ type swaggerResponseHookList struct {
|
|||
Body []api.Hook `json:"body"`
|
||||
}
|
||||
|
||||
// HookTaskList
|
||||
// swagger:response HookTaskList
|
||||
type swaggerResponseHookTaskList struct {
|
||||
// in:body
|
||||
Body []api.HookTask `json:"body"`
|
||||
}
|
||||
|
||||
// GitHook
|
||||
// swagger:response GitHook
|
||||
type swaggerResponseGitHook struct {
|
||||
|
|
|
@ -66,6 +66,10 @@ func CheckCreateHookOption(ctx *context.APIContext, form *api.CreateHookOption)
|
|||
ctx.Error(http.StatusUnprocessableEntity, "", "Invalid content type")
|
||||
return false
|
||||
}
|
||||
if !models.IsValidHookHttpMethod(form.Config["http_method"]) {
|
||||
ctx.Error(http.StatusUnprocessableEntity, "", "Invalid http method")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -212,6 +216,10 @@ func editHook(ctx *context.APIContext, form *api.EditHookOption, w *models.Webho
|
|||
if url, ok := form.Config["url"]; ok {
|
||||
w.URL = url
|
||||
}
|
||||
if secret, ok := form.Config["secret"]; ok {
|
||||
w.Secret = secret
|
||||
}
|
||||
|
||||
if ct, ok := form.Config["content_type"]; ok {
|
||||
if !models.IsValidHookContentType(ct) {
|
||||
ctx.Error(http.StatusUnprocessableEntity, "", "Invalid content type")
|
||||
|
@ -220,6 +228,14 @@ func editHook(ctx *context.APIContext, form *api.EditHookOption, w *models.Webho
|
|||
w.ContentType = models.ToHookContentType(ct)
|
||||
}
|
||||
|
||||
if hw, ok := form.Config["http_method"]; ok {
|
||||
if !models.IsValidHookHttpMethod(hw) {
|
||||
ctx.Error(http.StatusUnprocessableEntity, "", "Invalid http method")
|
||||
return false
|
||||
}
|
||||
w.HTTPMethod = hw
|
||||
}
|
||||
|
||||
if w.Type == models.SLACK {
|
||||
if channel, ok := form.Config["channel"]; ok {
|
||||
json := jsoniter.ConfigCompatibleWithStandardLibrary
|
||||
|
@ -248,16 +264,29 @@ func editHook(ctx *context.APIContext, form *api.EditHookOption, w *models.Webho
|
|||
w.Create = util.IsStringInSlice(string(models.HookEventCreate), form.Events, true)
|
||||
w.Push = util.IsStringInSlice(string(models.HookEventPush), form.Events, true)
|
||||
w.PullRequest = util.IsStringInSlice(string(models.HookEventPullRequest), form.Events, true)
|
||||
w.Create = util.IsStringInSlice(string(models.HookEventCreate), form.Events, true)
|
||||
// w.Create = util.IsStringInSlice(string(models.HookEventCreate), form.Events, true)
|
||||
w.Delete = util.IsStringInSlice(string(models.HookEventDelete), form.Events, true)
|
||||
w.Fork = util.IsStringInSlice(string(models.HookEventFork), form.Events, true)
|
||||
w.Issues = util.IsStringInSlice(string(models.HookEventIssues), form.Events, true)
|
||||
w.IssueComment = util.IsStringInSlice(string(models.HookEventIssueComment), form.Events, true)
|
||||
w.Issues = issuesHook(form.Events, "issues_only")
|
||||
w.IssueAssign = issuesHook(form.Events, string(models.HookEventIssueAssign))
|
||||
w.IssueLabel = issuesHook(form.Events, string(models.HookEventIssueLabel))
|
||||
w.IssueMilestone = issuesHook(form.Events, string(models.HookEventIssueMilestone))
|
||||
w.IssueComment = issuesHook(form.Events, string(models.HookEventIssueComment))
|
||||
// w.IssueComment = util.IsStringInSlice(string(models.HookEventIssueComment), form.Events, true)
|
||||
w.Push = util.IsStringInSlice(string(models.HookEventPush), form.Events, true)
|
||||
w.PullRequest = util.IsStringInSlice(string(models.HookEventPullRequest), form.Events, true)
|
||||
// w.PullRequest = util.IsStringInSlice(string(models.HookEventPullRequest), form.Events, true)
|
||||
w.PullRequest = pullHook(form.Events, "pull_request_only")
|
||||
w.PullRequestAssign = pullHook(form.Events, string(models.HookEventPullRequestAssign))
|
||||
w.PullRequestLabel = pullHook(form.Events, string(models.HookEventPullRequestLabel))
|
||||
w.PullRequestMilestone = pullHook(form.Events, string(models.HookEventPullRequestMilestone))
|
||||
w.PullRequestComment = pullHook(form.Events, string(models.HookEventPullRequestComment))
|
||||
w.PullRequestReview = pullHook(form.Events, "pull_request_review")
|
||||
w.PullRequestSync = pullHook(form.Events, string(models.HookEventPullRequestSync))
|
||||
w.Repository = util.IsStringInSlice(string(models.HookEventRepository), form.Events, true)
|
||||
w.Release = util.IsStringInSlice(string(models.HookEventRelease), form.Events, true)
|
||||
w.BranchFilter = form.BranchFilter
|
||||
w.HookEvent.BranchFilter = form.BranchFilter
|
||||
|
||||
if err := w.UpdateEvent(); err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "UpdateEvent", err)
|
||||
|
|
|
@ -4258,6 +4258,59 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{repo}/hooks/{id}/hooktasks": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"repository"
|
||||
],
|
||||
"summary": "Get a hooktasks",
|
||||
"operationId": "repoGetHookTasks",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "owner of the repo",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "name of the repo",
|
||||
"name": "repo",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"description": "id of the hook",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "page number of results to return (1-based)",
|
||||
"name": "page",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "page size of results",
|
||||
"name": "limit",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/responses/HookTaskList"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{repo}/hooks/{id}/tests": {
|
||||
"post": {
|
||||
"produces": [
|
||||
|
@ -15324,6 +15377,10 @@
|
|||
"type": "boolean",
|
||||
"x-go-name": "Active"
|
||||
},
|
||||
"branch_filter": {
|
||||
"type": "string",
|
||||
"x-go-name": "BranchFilter"
|
||||
},
|
||||
"config": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
|
@ -15360,6 +15417,74 @@
|
|||
},
|
||||
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
||||
},
|
||||
"HookTask": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"config": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
},
|
||||
"x-go-name": "Config"
|
||||
},
|
||||
"delivered": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"x-go-name": "Delivered"
|
||||
},
|
||||
"event_type": {
|
||||
"type": "string",
|
||||
"x-go-name": "EventType"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"x-go-name": "ID"
|
||||
},
|
||||
"is_delivered": {
|
||||
"type": "boolean",
|
||||
"x-go-name": "IsDelivered"
|
||||
},
|
||||
"is_ssl": {
|
||||
"type": "boolean",
|
||||
"x-go-name": "IsSSL"
|
||||
},
|
||||
"is_succeed": {
|
||||
"type": "boolean",
|
||||
"x-go-name": "IsSucceed"
|
||||
},
|
||||
"payload_content": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "object"
|
||||
},
|
||||
"x-go-name": "PayloadContent"
|
||||
},
|
||||
"request_info": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "object"
|
||||
},
|
||||
"x-go-name": "RequestContent"
|
||||
},
|
||||
"response_content": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "object"
|
||||
},
|
||||
"x-go-name": "ResponseContent"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"x-go-name": "Type"
|
||||
},
|
||||
"uuid": {
|
||||
"type": "string",
|
||||
"x-go-name": "UUID"
|
||||
}
|
||||
},
|
||||
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
||||
},
|
||||
"Identity": {
|
||||
"description": "Identity for a person's identity like an author or committer",
|
||||
"type": "object",
|
||||
|
@ -17938,6 +18063,15 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"HookTaskList": {
|
||||
"description": "HookTaskList",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/HookTask"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Issue": {
|
||||
"description": "Issue",
|
||||
"schema": {
|
||||
|
|
Loading…
Reference in New Issue