From e0c6ab2d44d17b72a7ea6f8b4c829c42baeaae3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Boulanouar?= Date: Mon, 29 May 2017 09:17:15 +0200 Subject: [PATCH] Add Gitea Webhook (#1755) * Replace Gogs by Gitea * Fix missing changes * Create Gitea webhook and put Gogs webhook apart. --- models/webhook.go | 9 ++- models/webhook_test.go | 5 +- modules/auth/repo_form.go | 14 ++++ modules/setting/setting.go | 3 +- public/img/gogs.ico | Bin 0 -> 29157 bytes routers/repo/webhook.go | 93 +++++++++++++++++++++++- routers/routes/routes.go | 12 ++- templates/org/settings/hook_new.tmpl | 5 +- templates/repo/settings/hook_gitea.tmpl | 28 +++++++ templates/repo/settings/hook_list.tmpl | 5 +- templates/repo/settings/hook_new.tmpl | 5 +- 11 files changed, 167 insertions(+), 12 deletions(-) create mode 100644 public/img/gogs.ico create mode 100644 templates/repo/settings/hook_gitea.tmpl diff --git a/models/webhook.go b/models/webhook.go index 3fb1e57e78..5cb2e13a6d 100644 --- a/models/webhook.go +++ b/models/webhook.go @@ -1,4 +1,5 @@ // Copyright 2014 The Gogs Authors. All rights reserved. +// Copyright 2017 The Gitea Authors. All rights reserved. // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. @@ -312,9 +313,11 @@ type HookTaskType int const ( GOGS HookTaskType = iota + 1 SLACK + GITEA ) var hookTaskTypes = map[string]HookTaskType{ + "gitea": GITEA, "gogs": GOGS, "slack": SLACK, } @@ -327,6 +330,8 @@ func ToHookTaskType(name string) HookTaskType { // Name returns the name of an hook task type func (t HookTaskType) Name() string { switch t { + case GITEA: + return "gitea" case GOGS: return "gogs" case SLACK: @@ -503,7 +508,7 @@ func PrepareWebhooks(repo *Repository, event HookEventType, p api.Payloader) err } } - // Use separate objects so modifications won't be made on payload on non-Gogs type hooks. + // Use separate objects so modifications won't be made on payload on non-Gogs/Gitea type hooks. switch w.HookTaskType { case SLACK: payloader, err = GetSlackPayload(p, event, w.Meta) @@ -536,6 +541,8 @@ func (t *HookTask) deliver() { timeout := time.Duration(setting.Webhook.DeliverTimeout) * time.Second req := httplib.Post(t.URL).SetTimeout(timeout, timeout). + Header("X-Gitea-Delivery", t.UUID). + Header("X-Gitea-Event", string(t.EventType)). Header("X-Gogs-Delivery", t.UUID). Header("X-Gogs-Event", string(t.EventType)). Header("X-GitHub-Delivery", t.UUID). diff --git a/models/webhook_test.go b/models/webhook_test.go index 3f377eae7a..a637a16999 100644 --- a/models/webhook_test.go +++ b/models/webhook_test.go @@ -191,16 +191,19 @@ func TestDeleteWebhookByOrgID(t *testing.T) { func TestToHookTaskType(t *testing.T) { assert.Equal(t, GOGS, ToHookTaskType("gogs")) assert.Equal(t, SLACK, ToHookTaskType("slack")) + assert.Equal(t, GITEA, ToHookTaskType("gitea")) } func TestHookTaskType_Name(t *testing.T) { assert.Equal(t, "gogs", GOGS.Name()) assert.Equal(t, "slack", SLACK.Name()) + assert.Equal(t, "gitea", GITEA.Name()) } func TestIsValidHookTaskType(t *testing.T) { assert.True(t, IsValidHookTaskType("gogs")) assert.True(t, IsValidHookTaskType("slack")) + assert.True(t, IsValidHookTaskType("gitea")) assert.False(t, IsValidHookTaskType("invalid")) } @@ -221,7 +224,7 @@ func TestCreateHookTask(t *testing.T) { hookTask := &HookTask{ RepoID: 3, HookID: 3, - Type: GOGS, + Type: GITEA, URL: "http://www.example.com/unit_test", Payloader: &api.PushPayload{}, } diff --git a/modules/auth/repo_form.go b/modules/auth/repo_form.go index c56e76c871..58dcf468ef 100644 --- a/modules/auth/repo_form.go +++ b/modules/auth/repo_form.go @@ -1,4 +1,5 @@ // Copyright 2014 The Gogs Authors. All rights reserved. +// Copyright 2017 The Gitea Authors. All rights reserved. // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. @@ -154,6 +155,19 @@ func (f *NewWebhookForm) Validate(ctx *macaron.Context, errs binding.Errors) bin return validate(errs, ctx.Data, f, ctx.Locale) } +// NewGogshookForm form for creating gogs hook +type NewGogshookForm struct { + PayloadURL string `binding:"Required;ValidUrl"` + ContentType int `binding:"Required"` + Secret string + WebhookForm +} + +// Validate validates the fields +func (f *NewGogshookForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors { + return validate(errs, ctx.Data, f, ctx.Locale) +} + // NewSlackHookForm form for creating slack hook type NewSlackHookForm struct { PayloadURL string `binding:"Required;ValidUrl"` diff --git a/modules/setting/setting.go b/modules/setting/setting.go index c3a829715b..a948527a2c 100644 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -1,4 +1,5 @@ // Copyright 2014 The Gogs Authors. All rights reserved. +// Copyright 2017 The Gitea Authors. All rights reserved. // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. @@ -1325,7 +1326,7 @@ func newWebhookService() { Webhook.QueueLength = sec.Key("QUEUE_LENGTH").MustInt(1000) Webhook.DeliverTimeout = sec.Key("DELIVER_TIMEOUT").MustInt(5) Webhook.SkipTLSVerify = sec.Key("SKIP_TLS_VERIFY").MustBool() - Webhook.Types = []string{"gogs", "slack"} + Webhook.Types = []string{"gitea", "gogs", "slack"} Webhook.PagingNum = sec.Key("PAGING_NUM").MustInt(10) } diff --git a/public/img/gogs.ico b/public/img/gogs.ico new file mode 100644 index 0000000000000000000000000000000000000000..34385535534c7520f4b1194e9a5def4094874374 GIT binary patch literal 29157 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 Z9+&4SM@nbE!bUOzl;qXrYGlmA{tx4U{&@fZ literal 0 HcmV?d00001 diff --git a/routers/repo/webhook.go b/routers/repo/webhook.go index 754cf169b8..5489d71857 100644 --- a/routers/repo/webhook.go +++ b/routers/repo/webhook.go @@ -1,4 +1,5 @@ // Copyright 2015 The Gogs Authors. All rights reserved. +// Copyright 2017 The Gitea Authors. All rights reserved. // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. @@ -120,6 +121,53 @@ func ParseHookEvent(form auth.WebhookForm) *models.HookEvent { // WebHooksNewPost response for creating webhook func WebHooksNewPost(ctx *context.Context, form auth.NewWebhookForm) { + ctx.Data["Title"] = ctx.Tr("repo.settings.add_webhook") + ctx.Data["PageIsSettingsHooks"] = true + ctx.Data["PageIsSettingsHooksNew"] = true + ctx.Data["Webhook"] = models.Webhook{HookEvent: &models.HookEvent{}} + ctx.Data["HookType"] = "gitea" + + orCtx, err := getOrgRepoCtx(ctx) + if err != nil { + ctx.Handle(500, "getOrgRepoCtx", err) + return + } + ctx.Data["BaseLink"] = orCtx.Link + + if ctx.HasError() { + ctx.HTML(200, orCtx.NewTemplate) + return + } + + contentType := models.ContentTypeJSON + if models.HookContentType(form.ContentType) == models.ContentTypeForm { + contentType = models.ContentTypeForm + } + + w := &models.Webhook{ + RepoID: orCtx.RepoID, + URL: form.PayloadURL, + ContentType: contentType, + Secret: form.Secret, + HookEvent: ParseHookEvent(form.WebhookForm), + IsActive: form.Active, + HookTaskType: models.GITEA, + OrgID: orCtx.OrgID, + } + if err := w.UpdateEvent(); err != nil { + ctx.Handle(500, "UpdateEvent", err) + return + } else if err := models.CreateWebhook(w); err != nil { + ctx.Handle(500, "CreateWebhook", err) + return + } + + ctx.Flash.Success(ctx.Tr("repo.settings.add_hook_success")) + ctx.Redirect(orCtx.Link + "/settings/hooks") +} + +// GogsHooksNewPost response for creating webhook +func GogsHooksNewPost(ctx *context.Context, form auth.NewWebhookForm) { ctx.Data["Title"] = ctx.Tr("repo.settings.add_webhook") ctx.Data["PageIsSettingsHooks"] = true ctx.Data["PageIsSettingsHooksNew"] = true @@ -150,7 +198,7 @@ func WebHooksNewPost(ctx *context.Context, form auth.NewWebhookForm) { Secret: form.Secret, HookEvent: ParseHookEvent(form.WebhookForm), IsActive: form.Active, - HookTaskType: models.GOGS, + HookTaskType: models.GITEA, OrgID: orCtx.OrgID, } if err := w.UpdateEvent(); err != nil { @@ -245,8 +293,10 @@ func checkWebhook(ctx *context.Context) (*orgRepoCtx, *models.Webhook) { case models.SLACK: ctx.Data["SlackHook"] = w.GetSlackHook() ctx.Data["HookType"] = "slack" - default: + case models.GOGS: ctx.Data["HookType"] = "gogs" + default: + ctx.Data["HookType"] = "gitea" } ctx.Data["History"], err = w.History(1) @@ -310,6 +360,45 @@ func WebHooksEditPost(ctx *context.Context, form auth.NewWebhookForm) { ctx.Redirect(fmt.Sprintf("%s/settings/hooks/%d", orCtx.Link, w.ID)) } +// GogsHooksEditPost response for editing gogs hook +func GogsHooksEditPost(ctx *context.Context, form auth.NewWebhookForm) { + ctx.Data["Title"] = ctx.Tr("repo.settings.update_webhook") + ctx.Data["PageIsSettingsHooks"] = true + ctx.Data["PageIsSettingsHooksEdit"] = true + + orCtx, w := checkWebhook(ctx) + if ctx.Written() { + return + } + ctx.Data["Webhook"] = w + + if ctx.HasError() { + ctx.HTML(200, orCtx.NewTemplate) + return + } + + contentType := models.ContentTypeJSON + if models.HookContentType(form.ContentType) == models.ContentTypeForm { + contentType = models.ContentTypeForm + } + + w.URL = form.PayloadURL + w.ContentType = contentType + w.Secret = form.Secret + w.HookEvent = ParseHookEvent(form.WebhookForm) + w.IsActive = form.Active + if err := w.UpdateEvent(); err != nil { + ctx.Handle(500, "UpdateEvent", err) + return + } else if err := models.UpdateWebhook(w); err != nil { + ctx.Handle(500, "GogsHooksEditPost", err) + return + } + + ctx.Flash.Success(ctx.Tr("repo.settings.update_hook_success")) + ctx.Redirect(fmt.Sprintf("%s/settings/hooks/%d", orCtx.Link, w.ID)) +} + // SlackHooksEditPost response for editing slack hook func SlackHooksEditPost(ctx *context.Context, form auth.NewSlackHookForm) { ctx.Data["Title"] = ctx.Tr("repo.settings") diff --git a/routers/routes/routes.go b/routers/routes/routes.go index f1c55e1705..0781aef89d 100644 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -379,10 +379,12 @@ func RegisterRoutes(m *macaron.Macaron) { m.Get("", org.Webhooks) m.Post("/delete", org.DeleteWebhook) m.Get("/:type/new", repo.WebhooksNew) - m.Post("/gogs/new", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksNewPost) + m.Post("/gitea/new", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksNewPost) + m.Post("/gogs/new", bindIgnErr(auth.NewGogshookForm{}), repo.GogsHooksNewPost) m.Post("/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost) m.Get("/:id", repo.WebHooksEdit) - m.Post("/gogs/:id", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksEditPost) + m.Post("/gitea/:id", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksEditPost) + m.Post("/gogs/:id", bindIgnErr(auth.NewGogshookForm{}), repo.GogsHooksEditPost) m.Post("/slack/:id", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksEditPost) }) @@ -423,11 +425,13 @@ func RegisterRoutes(m *macaron.Macaron) { m.Get("", repo.Webhooks) m.Post("/delete", repo.DeleteWebhook) m.Get("/:type/new", repo.WebhooksNew) - m.Post("/gogs/new", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksNewPost) + m.Post("/gitea/new", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksNewPost) + m.Post("/gogs/new", bindIgnErr(auth.NewGogshookForm{}), repo.GogsHooksNewPost) m.Post("/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost) m.Get("/:id", repo.WebHooksEdit) m.Post("/:id/test", repo.TestWebhook) - m.Post("/gogs/:id", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksEditPost) + m.Post("/gitea/:id", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksEditPost) + m.Post("/gogs/:id", bindIgnErr(auth.NewGogshookForm{}), repo.GogsHooksNewPost) m.Post("/slack/:id", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksEditPost) m.Group("/git", func() { diff --git a/templates/org/settings/hook_new.tmpl b/templates/org/settings/hook_new.tmpl index 2324788d33..ee3fd2c506 100644 --- a/templates/org/settings/hook_new.tmpl +++ b/templates/org/settings/hook_new.tmpl @@ -9,14 +9,17 @@

{{if .PageIsSettingsHooksNew}}{{.i18n.Tr "repo.settings.add_webhook"}}{{else}}{{.i18n.Tr "repo.settings.update_webhook"}}{{end}}
- {{if eq .HookType "gogs"}} + {{if eq .HookType "gitea"}} + {{else if eq .HookType "gogs"}} + {{else if eq .HookType "slack"}} {{end}}

+ {{template "repo/settings/hook_gitea" .}} {{template "repo/settings/hook_gogs" .}} {{template "repo/settings/hook_slack" .}}
diff --git a/templates/repo/settings/hook_gitea.tmpl b/templates/repo/settings/hook_gitea.tmpl new file mode 100644 index 0000000000..4ac6d718c9 --- /dev/null +++ b/templates/repo/settings/hook_gitea.tmpl @@ -0,0 +1,28 @@ +{{if eq .HookType "gitea"}} +

{{.i18n.Tr "repo.settings.add_webhook_desc" "https://docs.gitea.io/features/webhook.html" | Str2html}}

+
+ {{.CsrfTokenHtml}} +
+ + +
+
+ + +
+ +
+ + +
+ {{template "repo/settings/hook_settings" .}} +
+{{end}} diff --git a/templates/repo/settings/hook_list.tmpl b/templates/repo/settings/hook_list.tmpl index 0b9c4d5057..aba948b952 100644 --- a/templates/repo/settings/hook_list.tmpl +++ b/templates/repo/settings/hook_list.tmpl @@ -5,9 +5,12 @@