[BRANDING] add the forgejo webhook type & update webhook docs URLs
templates/swagger/v1_json.tmpl updated with `make generate-swagger` (cherry picked from commit88899c492e
) (cherry picked from commit7171bd9617
) (cherry picked from commit1a742446c1
) (cherry picked from commitd7c189d7b2
) Conflicts: routers/web/web.go (cherry picked from commitcbdea868e4
) (cherry picked from commit6cd150483b
) (cherry picked from commit47246da8d3
) (cherry picked from commitf2aa0e6b76
) (cherry picked from commit5a4fc69a16
) (cherry picked from commit48e444ca09
) (cherry picked from commit888e537811
) (cherry picked from commit5121f493c9
) (cherry picked from commit9394e55fdf
) (cherry picked from commit3a2ce51768
) (cherry picked from commit719ead3a65
) (cherry picked from commit83e6f82e2a
) (cherry picked from commit494a429b21
) (cherry picked from commit4d775db6b4
) (cherry picked from commitb68f777dc2
) (cherry picked from commit5b934023fa
) (cherry picked from commit3b1ed8b16c
) (cherry picked from commit6bc4a46c9f
) (cherry picked from commit8064bb24a3
) Conflicts: templates/admin/hook_new.tmpl templates/org/settings/hook_new.tmpl templates/repo/settings/webhook/base_list.tmpl templates/repo/settings/webhook/new.tmpl templates/user/settings/hook_new.tmpl https://codeberg.org/forgejo/forgejo/pulls/1181 (cherry picked from commit55f5588a91
) (cherry picked from commita428bc06b3
) (cherry picked from commitd2186eceb9
) (cherry picked from commitb4e126e9af
) (cherry picked from commite4c7a92c2d
) (cherry picked from commita7165c8146
) Conflicts: templates/admin/hook_new.tmpl templates/repo/settings/webhook/new.tmpl https://codeberg.org/forgejo/forgejo/pulls/1420 [BRANDING] add the forgejo webhook type & update webhook docs URLs (squash) gitea logo for gitea webhooks Refs: https://codeberg.org/forgejo/forgejo/issues/1367 (cherry picked from commit2d8c1b9373
) (cherry picked from commit9135a5e1db
) (cherry picked from commit270f4020b0
) (cherry picked from commit33e5e2f0d8
) (cherry picked from commit7af8bcf479
) Conflicts: tests/integration/links_test.go https://codeberg.org/forgejo/forgejo/pulls/1548 (cherry picked from commitce2a434dcf
) (cherry picked from commitc2fa42b4fd
) (cherry picked from commit3858c8d4db
) (cherry picked from commitebb0ae4920
)
This commit is contained in:
parent
3f622c51a7
commit
93d354c418
14 changed files with 118 additions and 9 deletions
|
@ -35,7 +35,7 @@ func loadWebhookFrom(rootCfg ConfigProvider) {
|
||||||
Webhook.DeliverTimeout = sec.Key("DELIVER_TIMEOUT").MustInt(5)
|
Webhook.DeliverTimeout = sec.Key("DELIVER_TIMEOUT").MustInt(5)
|
||||||
Webhook.SkipTLSVerify = sec.Key("SKIP_TLS_VERIFY").MustBool()
|
Webhook.SkipTLSVerify = sec.Key("SKIP_TLS_VERIFY").MustBool()
|
||||||
Webhook.AllowedHostList = sec.Key("ALLOWED_HOST_LIST").MustString("")
|
Webhook.AllowedHostList = sec.Key("ALLOWED_HOST_LIST").MustString("")
|
||||||
Webhook.Types = []string{"gitea", "gogs", "slack", "discord", "dingtalk", "telegram", "msteams", "feishu", "matrix", "wechatwork", "packagist"}
|
Webhook.Types = []string{"forgejo", "gitea", "gogs", "slack", "discord", "dingtalk", "telegram", "msteams", "feishu", "matrix", "wechatwork", "packagist"}
|
||||||
Webhook.PagingNum = sec.Key("PAGING_NUM").MustInt(10)
|
Webhook.PagingNum = sec.Key("PAGING_NUM").MustInt(10)
|
||||||
Webhook.ProxyURL = sec.Key("PROXY_URL").MustString("")
|
Webhook.ProxyURL = sec.Key("PROXY_URL").MustString("")
|
||||||
if Webhook.ProxyURL != "" {
|
if Webhook.ProxyURL != "" {
|
||||||
|
|
|
@ -41,7 +41,7 @@ type CreateHookOptionConfig map[string]string
|
||||||
// CreateHookOption options when create a hook
|
// CreateHookOption options when create a hook
|
||||||
type CreateHookOption struct {
|
type CreateHookOption struct {
|
||||||
// required: true
|
// required: true
|
||||||
// enum: dingtalk,discord,gitea,gogs,msteams,slack,telegram,feishu,wechatwork,packagist
|
// enum: forgejo,dingtalk,discord,gitea,gogs,msteams,slack,telegram,feishu,wechatwork,packagist
|
||||||
Type string `json:"type" binding:"Required"`
|
Type string `json:"type" binding:"Required"`
|
||||||
// required: true
|
// required: true
|
||||||
Config CreateHookOptionConfig `json:"config" binding:"Required"`
|
Config CreateHookOptionConfig `json:"config" binding:"Required"`
|
||||||
|
|
|
@ -72,6 +72,7 @@ type HookType = string
|
||||||
|
|
||||||
// Types of webhooks
|
// Types of webhooks
|
||||||
const (
|
const (
|
||||||
|
FORGEJO HookType = "forgejo"
|
||||||
GITEA HookType = "gitea"
|
GITEA HookType = "gitea"
|
||||||
GOGS HookType = "gogs"
|
GOGS HookType = "gogs"
|
||||||
SLACK HookType = "slack"
|
SLACK HookType = "slack"
|
||||||
|
|
|
@ -44,7 +44,7 @@ func Webhooks(ctx *context.Context) {
|
||||||
ctx.Data["PageIsSettingsHooks"] = true
|
ctx.Data["PageIsSettingsHooks"] = true
|
||||||
ctx.Data["BaseLink"] = ctx.Repo.RepoLink + "/settings/hooks"
|
ctx.Data["BaseLink"] = ctx.Repo.RepoLink + "/settings/hooks"
|
||||||
ctx.Data["BaseLinkNew"] = ctx.Repo.RepoLink + "/settings/hooks"
|
ctx.Data["BaseLinkNew"] = ctx.Repo.RepoLink + "/settings/hooks"
|
||||||
ctx.Data["Description"] = ctx.Tr("repo.settings.hooks_desc", "https://docs.gitea.com/usage/webhooks")
|
ctx.Data["Description"] = ctx.Tr("repo.settings.hooks_desc", "https://forgejo.org/docs/latest/user/webhooks/")
|
||||||
|
|
||||||
ws, err := webhook.ListWebhooksByOpts(ctx, &webhook.ListWebhookOptions{RepoID: ctx.Repo.Repository.ID})
|
ws, err := webhook.ListWebhooksByOpts(ctx, &webhook.ListWebhookOptions{RepoID: ctx.Repo.Repository.ID})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -309,6 +309,34 @@ func editWebhook(ctx *context.Context, params webhookParams) {
|
||||||
ctx.Redirect(fmt.Sprintf("%s/%d", orCtx.Link, w.ID))
|
ctx.Redirect(fmt.Sprintf("%s/%d", orCtx.Link, w.ID))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ForgejoHooksNewPost response for creating Forgejo webhook
|
||||||
|
func ForgejoHooksNewPost(ctx *context.Context) {
|
||||||
|
createWebhook(ctx, forgejoHookParams(ctx))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ForgejoHooksEditPost response for editing Forgejo webhook
|
||||||
|
func ForgejoHooksEditPost(ctx *context.Context) {
|
||||||
|
editWebhook(ctx, forgejoHookParams(ctx))
|
||||||
|
}
|
||||||
|
|
||||||
|
func forgejoHookParams(ctx *context.Context) webhookParams {
|
||||||
|
form := web.GetForm(ctx).(*forms.NewWebhookForm)
|
||||||
|
|
||||||
|
contentType := webhook.ContentTypeJSON
|
||||||
|
if webhook.HookContentType(form.ContentType) == webhook.ContentTypeForm {
|
||||||
|
contentType = webhook.ContentTypeForm
|
||||||
|
}
|
||||||
|
|
||||||
|
return webhookParams{
|
||||||
|
Type: webhook_module.FORGEJO,
|
||||||
|
URL: form.PayloadURL,
|
||||||
|
ContentType: contentType,
|
||||||
|
Secret: form.Secret,
|
||||||
|
HTTPMethod: form.HTTPMethod,
|
||||||
|
WebhookForm: form.WebhookForm,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// GiteaHooksNewPost response for creating Gitea webhook
|
// GiteaHooksNewPost response for creating Gitea webhook
|
||||||
func GiteaHooksNewPost(ctx *context.Context) {
|
func GiteaHooksNewPost(ctx *context.Context) {
|
||||||
createWebhook(ctx, giteaHookParams(ctx))
|
createWebhook(ctx, giteaHookParams(ctx))
|
||||||
|
|
|
@ -389,6 +389,7 @@ func registerRoutes(m *web.Route) {
|
||||||
|
|
||||||
addWebhookAddRoutes := func() {
|
addWebhookAddRoutes := func() {
|
||||||
m.Get("/{type}/new", repo_setting.WebhooksNew)
|
m.Get("/{type}/new", repo_setting.WebhooksNew)
|
||||||
|
m.Post("/forgejo/new", web.Bind(forms.NewWebhookForm{}), repo_setting.ForgejoHooksNewPost)
|
||||||
m.Post("/gitea/new", web.Bind(forms.NewWebhookForm{}), repo_setting.GiteaHooksNewPost)
|
m.Post("/gitea/new", web.Bind(forms.NewWebhookForm{}), repo_setting.GiteaHooksNewPost)
|
||||||
m.Post("/gogs/new", web.Bind(forms.NewGogshookForm{}), repo_setting.GogsHooksNewPost)
|
m.Post("/gogs/new", web.Bind(forms.NewGogshookForm{}), repo_setting.GogsHooksNewPost)
|
||||||
m.Post("/slack/new", web.Bind(forms.NewSlackHookForm{}), repo_setting.SlackHooksNewPost)
|
m.Post("/slack/new", web.Bind(forms.NewSlackHookForm{}), repo_setting.SlackHooksNewPost)
|
||||||
|
@ -403,6 +404,7 @@ func registerRoutes(m *web.Route) {
|
||||||
}
|
}
|
||||||
|
|
||||||
addWebhookEditRoutes := func() {
|
addWebhookEditRoutes := func() {
|
||||||
|
m.Post("/forgejo/{id}", web.Bind(forms.NewWebhookForm{}), repo_setting.ForgejoHooksEditPost)
|
||||||
m.Post("/gitea/{id}", web.Bind(forms.NewWebhookForm{}), repo_setting.GiteaHooksEditPost)
|
m.Post("/gitea/{id}", web.Bind(forms.NewWebhookForm{}), repo_setting.GiteaHooksEditPost)
|
||||||
m.Post("/gogs/{id}", web.Bind(forms.NewGogshookForm{}), repo_setting.GogsHooksEditPost)
|
m.Post("/gogs/{id}", web.Bind(forms.NewGogshookForm{}), repo_setting.GogsHooksEditPost)
|
||||||
m.Post("/slack/{id}", web.Bind(forms.NewSlackHookForm{}), repo_setting.SlackHooksEditPost)
|
m.Post("/slack/{id}", web.Bind(forms.NewSlackHookForm{}), repo_setting.SlackHooksEditPost)
|
||||||
|
|
|
@ -70,7 +70,7 @@ var webhooks = map[webhook_module.HookType]*webhook{
|
||||||
|
|
||||||
// IsValidHookTaskType returns true if a webhook registered
|
// IsValidHookTaskType returns true if a webhook registered
|
||||||
func IsValidHookTaskType(name string) bool {
|
func IsValidHookTaskType(name string) bool {
|
||||||
if name == webhook_module.GITEA || name == webhook_module.GOGS {
|
if name == webhook_module.FORGEJO || name == webhook_module.GITEA || name == webhook_module.GOGS {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
_, ok := webhooks[name]
|
_, ok := webhooks[name]
|
||||||
|
@ -177,7 +177,7 @@ func PrepareWebhook(ctx context.Context, w *webhook_model.Webhook, event webhook
|
||||||
// Avoid sending "0 new commits" to non-integration relevant webhooks (e.g. slack, discord, etc.).
|
// Avoid sending "0 new commits" to non-integration relevant webhooks (e.g. slack, discord, etc.).
|
||||||
// Integration webhooks (e.g. drone) still receive the required data.
|
// Integration webhooks (e.g. drone) still receive the required data.
|
||||||
if pushEvent, ok := p.(*api.PushPayload); ok &&
|
if pushEvent, ok := p.(*api.PushPayload); ok &&
|
||||||
w.Type != webhook_module.GITEA && w.Type != webhook_module.GOGS &&
|
w.Type != webhook_module.FORGEJO && w.Type != webhook_module.GITEA && w.Type != webhook_module.GOGS &&
|
||||||
len(pushEvent.Commits) == 0 {
|
len(pushEvent.Commits) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,10 @@
|
||||||
<div class="ui jump dropdown">
|
<div class="ui jump dropdown">
|
||||||
<div class="ui primary tiny button">{{ctx.Locale.Tr "repo.settings.add_webhook"}}</div>
|
<div class="ui primary tiny button">{{ctx.Locale.Tr "repo.settings.add_webhook"}}</div>
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
|
<a class="item" href="{{.BaseLinkNew}}/forgejo/new">
|
||||||
|
{{template "shared/webhook/icon" (dict "HookType" "forgejo" "Size" 20)}}
|
||||||
|
{{.locale.Tr "repo.settings.web_hook_name_forgejo"}}
|
||||||
|
</a>
|
||||||
<a class="item" href="{{.BaseLinkNew}}/gitea/new">
|
<a class="item" href="{{.BaseLinkNew}}/gitea/new">
|
||||||
{{template "shared/webhook/icon" (dict "HookType" "gitea" "Size" 20)}}
|
{{template "shared/webhook/icon" (dict "HookType" "gitea" "Size" 20)}}
|
||||||
{{ctx.Locale.Tr "repo.settings.web_hook_name_gitea"}}
|
{{ctx.Locale.Tr "repo.settings.web_hook_name_gitea"}}
|
||||||
|
|
40
templates/repo/settings/webhook/forgejo.tmpl
Normal file
40
templates/repo/settings/webhook/forgejo.tmpl
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
{{if eq .HookType "forgejo"}}
|
||||||
|
<p>{{.locale.Tr "repo.settings.add_web_hook_desc" "https://forgejo.org/docs/latest/user/webhooks/" (.locale.Tr "repo.settings.web_hook_name_forgejo") | Str2html}}</p>
|
||||||
|
<form class="ui form" action="{{.BaseLink}}/forgejo/{{or .Webhook.ID "new"}}" method="post">
|
||||||
|
{{template "base/disable_form_autofill"}}
|
||||||
|
{{.CsrfTokenHtml}}
|
||||||
|
<div class="required field {{if .Err_PayloadURL}}error{{end}}">
|
||||||
|
<label for="payload_url">{{.locale.Tr "repo.settings.payload_url"}}</label>
|
||||||
|
<input id="payload_url" name="payload_url" type="url" value="{{.Webhook.URL}}" autofocus required>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label>{{.locale.Tr "repo.settings.http_method"}}</label>
|
||||||
|
<div class="ui selection dropdown">
|
||||||
|
<input type="hidden" id="http_method" name="http_method" value="{{if .Webhook.HTTPMethod}}{{.Webhook.HTTPMethod}}{{else}}POST{{end}}">
|
||||||
|
<div class="default text"></div>
|
||||||
|
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||||
|
<div class="menu">
|
||||||
|
<div class="item" data-value="POST">POST</div>
|
||||||
|
<div class="item" data-value="GET">GET</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label>{{.locale.Tr "repo.settings.content_type"}}</label>
|
||||||
|
<div class="ui selection dropdown">
|
||||||
|
<input type="hidden" id="content_type" name="content_type" value="{{if .Webhook.ContentType}}{{.Webhook.ContentType}}{{else}}1{{end}}">
|
||||||
|
<div class="default text"></div>
|
||||||
|
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||||
|
<div class="menu">
|
||||||
|
<div class="item" data-value="1">application/json</div>
|
||||||
|
<div class="item" data-value="2">application/x-www-form-urlencoded</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="field {{if .Err_Secret}}error{{end}}">
|
||||||
|
<label for="secret">{{.locale.Tr "repo.settings.secret"}}</label>
|
||||||
|
<input id="secret" name="secret" type="password" value="{{.Webhook.Secret}}" autocomplete="off">
|
||||||
|
</div>
|
||||||
|
{{template "repo/settings/webhook/settings" .}}
|
||||||
|
</form>
|
||||||
|
{{end}}
|
|
@ -1,5 +1,5 @@
|
||||||
{{if eq .HookType "gitea"}}
|
{{if eq .HookType "gitea"}}
|
||||||
<p>{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://docs.gitea.com/usage/webhooks" (ctx.Locale.Tr "repo.settings.web_hook_name_gitea") | Str2html}}</p>
|
<p>{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://forgejo.org/docs/latest/user/webhooks/" (ctx.Locale.Tr "repo.settings.web_hook_name_gitea") | Str2html}}</p>
|
||||||
<form class="ui form" action="{{.BaseLink}}/gitea/{{or .Webhook.ID "new"}}" method="post">
|
<form class="ui form" action="{{.BaseLink}}/gitea/{{or .Webhook.ID "new"}}" method="post">
|
||||||
{{template "base/disable_form_autofill"}}
|
{{template "base/disable_form_autofill"}}
|
||||||
{{.CsrfTokenHtml}}
|
{{.CsrfTokenHtml}}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{{if eq .HookType "gogs"}}
|
{{if eq .HookType "gogs"}}
|
||||||
<p>{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://docs.gitea.com/usage/webhooks" (ctx.Locale.Tr "repo.settings.web_hook_name_gogs") | Str2html}}</p>
|
<p>{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://forgejo.org/docs/latest/user/webhooks/" (ctx.Locale.Tr "repo.settings.web_hook_name_gogs") | Str2html}}</p>
|
||||||
<form class="ui form" action="{{.BaseLink}}/gogs/{{or .Webhook.ID "new"}}" method="post">
|
<form class="ui form" action="{{.BaseLink}}/gogs/{{or .Webhook.ID "new"}}" method="post">
|
||||||
{{template "base/disable_form_autofill"}}
|
{{template "base/disable_form_autofill"}}
|
||||||
{{.CsrfTokenHtml}}
|
{{.CsrfTokenHtml}}
|
||||||
|
|
|
@ -2,8 +2,10 @@
|
||||||
{{if .Size}}
|
{{if .Size}}
|
||||||
{{$size = .Size}}
|
{{$size = .Size}}
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if eq .HookType "gitea"}}
|
{{if eq .HookType "forgejo"}}
|
||||||
<img width="{{$size}}" height="{{$size}}" src="{{AssetUrlPrefix}}/img/gitea.svg">
|
<img width="{{$size}}" height="{{$size}}" src="{{AssetUrlPrefix}}/img/forgejo.svg">
|
||||||
|
{{else if eq .HookType "gitea"}}
|
||||||
|
<img width="{{$size}}" height="{{$size}}" src="{{AssetUrlPrefix}}/img/gitea-original.svg">
|
||||||
{{else if eq .HookType "gogs"}}
|
{{else if eq .HookType "gogs"}}
|
||||||
<img width="{{$size}}" height="{{$size}}" src="{{AssetUrlPrefix}}/img/gogs.ico">
|
<img width="{{$size}}" height="{{$size}}" src="{{AssetUrlPrefix}}/img/gogs.ico">
|
||||||
{{else if eq .HookType "slack"}}
|
{{else if eq .HookType "slack"}}
|
||||||
|
|
1
templates/swagger/v1_json.tmpl
generated
1
templates/swagger/v1_json.tmpl
generated
|
@ -17820,6 +17820,7 @@
|
||||||
"type": {
|
"type": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": [
|
"enum": [
|
||||||
|
"forgejo",
|
||||||
"dingtalk",
|
"dingtalk",
|
||||||
"discord",
|
"discord",
|
||||||
"gitea",
|
"gitea",
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
</div>
|
</div>
|
||||||
</h4>
|
</h4>
|
||||||
<div class="ui attached segment">
|
<div class="ui attached segment">
|
||||||
|
{{template "repo/settings/webhook/forgejo" .ctxData}}
|
||||||
{{template "repo/settings/webhook/gitea" .ctxData}}
|
{{template "repo/settings/webhook/gitea" .ctxData}}
|
||||||
{{template "repo/settings/webhook/gogs" .ctxData}}
|
{{template "repo/settings/webhook/gogs" .ctxData}}
|
||||||
{{template "repo/settings/webhook/slack" .ctxData}}
|
{{template "repo/settings/webhook/slack" .ctxData}}
|
||||||
|
|
|
@ -176,6 +176,36 @@ func TestLinksLogin(t *testing.T) {
|
||||||
testLinksAsUser("user2", t)
|
testLinksAsUser("user2", t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRedirectsWebhooks(t *testing.T) {
|
||||||
|
defer tests.PrepareTestEnv(t)()
|
||||||
|
|
||||||
|
//
|
||||||
|
// A redirect means the route exists but not if it performs as intended.
|
||||||
|
//
|
||||||
|
for _, kind := range []string{"forgejo", "gitea"} {
|
||||||
|
redirects := []struct {
|
||||||
|
from string
|
||||||
|
to string
|
||||||
|
verb string
|
||||||
|
}{
|
||||||
|
{from: "/user2/repo1/settings/hooks/" + kind + "/new", to: "/user/login", verb: "GET"},
|
||||||
|
{from: "/user/settings/hooks/" + kind + "/new", to: "/user/login", verb: "GET"},
|
||||||
|
{from: "/admin/system-hooks/" + kind + "/new", to: "/user/login", verb: "GET"},
|
||||||
|
{from: "/admin/default-hooks/" + kind + "/new", to: "/user/login", verb: "GET"},
|
||||||
|
{from: "/user2/repo1/settings/hooks/" + kind + "/new", to: "/", verb: "POST"},
|
||||||
|
{from: "/admin/system-hooks/" + kind + "/new", to: "/", verb: "POST"},
|
||||||
|
{from: "/admin/default-hooks/" + kind + "/new", to: "/", verb: "POST"},
|
||||||
|
{from: "/user2/repo1/settings/hooks/" + kind + "/1", to: "/", verb: "POST"},
|
||||||
|
{from: "/admin/hooks/" + kind + "/1", to: "/", verb: "POST"},
|
||||||
|
}
|
||||||
|
for _, info := range redirects {
|
||||||
|
req := NewRequest(t, info.verb, info.from)
|
||||||
|
resp := MakeRequest(t, req, http.StatusSeeOther)
|
||||||
|
assert.EqualValues(t, path.Join(setting.AppSubURL, info.to), test.RedirectURL(resp), info.from)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestRepoLinks(t *testing.T) {
|
func TestRepoLinks(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue