From e72d74244e7f941bbfbb289c92d33827aeb43213 Mon Sep 17 00:00:00 2001 From: ZeroDeng Date: Tue, 21 Oct 2025 12:13:56 +0800 Subject: [PATCH 1/3] Add support for Bark webhook integration This commit introduces the Bark notification integration, allowing users to configure Bark webhooks in repositories. It includes form models, templates, routing changes, and test cases to handle Bark webhook functionality. --- modules/setting/webhook.go | 2 +- modules/webhook/type.go | 1 + options/locale/locale_en-US.ini | 5 + options/locale/locale_zh-CN.ini | 5 + public/assets/img/bark.png | Bin 0 -> 870 bytes routers/web/repo/setting/webhook.go | 28 ++ routers/web/web.go | 2 + services/forms/repo_form.go | 14 + services/webhook/bark.go | 349 ++++++++++++++++++ services/webhook/bark_test.go | 214 +++++++++++ templates/repo/settings/webhook/bark.tmpl | 20 + .../repo/settings/webhook/link_menu.tmpl | 4 + templates/shared/webhook/icon.tmpl | 2 + templates/webhook/new.tmpl | 1 + 14 files changed, 646 insertions(+), 1 deletion(-) create mode 100644 public/assets/img/bark.png create mode 100644 services/webhook/bark.go create mode 100644 services/webhook/bark_test.go create mode 100644 templates/repo/settings/webhook/bark.tmpl diff --git a/modules/setting/webhook.go b/modules/setting/webhook.go index c01261dbbd6e9..17e490644323e 100644 --- a/modules/setting/webhook.go +++ b/modules/setting/webhook.go @@ -35,7 +35,7 @@ func loadWebhookFrom(rootCfg ConfigProvider) { Webhook.DeliverTimeout = sec.Key("DELIVER_TIMEOUT").MustInt(5) Webhook.SkipTLSVerify = sec.Key("SKIP_TLS_VERIFY").MustBool() 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{"gitea", "gogs", "slack", "discord", "dingtalk", "telegram", "msteams", "feishu", "matrix", "wechatwork", "packagist", "bark"} Webhook.PagingNum = sec.Key("PAGING_NUM").MustInt(10) Webhook.ProxyURL = sec.Key("PROXY_URL").MustString("") if Webhook.ProxyURL != "" { diff --git a/modules/webhook/type.go b/modules/webhook/type.go index 89c6a4bfe5907..3f8f763bd2cae 100644 --- a/modules/webhook/type.go +++ b/modules/webhook/type.go @@ -114,6 +114,7 @@ const ( MATRIX HookType = "matrix" WECHATWORK HookType = "wechatwork" PACKAGIST HookType = "packagist" + BARK HookType = "bark" ) // HookStatus is the status of a web hook diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 46fdf060229e8..e611512b3d3e1 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -2467,9 +2467,14 @@ settings.web_hook_name_feishu = Feishu settings.web_hook_name_larksuite = Lark Suite settings.web_hook_name_wechatwork = WeCom (Wechat Work) settings.web_hook_name_packagist = Packagist +settings.web_hook_name_bark = Bark settings.packagist_username = Packagist username settings.packagist_api_token = API token settings.packagist_package_url = Packagist package URL +settings.bark_url = Bark URL +settings.bark_url_help = Full Bark URL including device key (e.g., https://api.day.app/your_device_key/) +settings.bark_sound = Sound (optional) +settings.bark_group = Group (optional) settings.deploy_keys = Deploy Keys settings.add_deploy_key = Add Deploy Key settings.deploy_key_desc = Deploy keys have read-only pull access to the repository. diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index 29eb6be949a7f..d6804fd3c433c 100644 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -2465,9 +2465,14 @@ settings.web_hook_name_feishu=飞书 settings.web_hook_name_larksuite=Lark Suite settings.web_hook_name_wechatwork=企业微信 settings.web_hook_name_packagist=Packagist +settings.web_hook_name_bark=Bark settings.packagist_username=Packagist 用户名 settings.packagist_api_token=API 令牌 settings.packagist_package_url=Packagist 软件包 URL +settings.bark_url=Bark URL +settings.bark_url_help=完整的 Bark URL,包含设备密钥(例如:https://api.day.app/your_device_key/) +settings.bark_sound=提示音(可选) +settings.bark_group=分组(可选) settings.deploy_keys=部署密钥 settings.add_deploy_key=添加部署密钥 settings.deploy_key_desc=部署密钥具有对仓库的只读拉取权限。 diff --git a/public/assets/img/bark.png b/public/assets/img/bark.png new file mode 100644 index 0000000000000000000000000000000000000000..96728016cc45c30576ac816757f40cc4271600e5 GIT binary patch literal 870 zcmV-s1DX7ZP)9 z*0M(;3IVu?f^neVL*uG1K(ljN#A|_I0*gU105;v908sqsGw#ZB z`f?h~$w&<+0MH?3J*70&I3lkL z?b?B=E3mSr&{+U_U*#o-4F2iYT$HpTBqR zJaFrFxwU5i*Up^v$4t-8-zZIH7NGwvz07HQy2p+Kj~=U1TV0oP?by_5Pe5mC{-z|g z_+n=PUcJ!H(r~(+;v<~}=x+nI3d5Z3Ca}%X&Q~D|z>RGc2*Z8|c4{hCQBZ|E0EOEs z#LL3@E~r8tfO2gW*bdE{Dii~-3WEs${R?=xrt$PiecRu!zr)_%p)ad&*em{P(agVl zTmKj7=MP|W19@+tmKzv0l2bK}#(vt^gf;Rp8vxJ&m~;4Yuk3FSaAUdIYbE z!6VK6=toQKRSsaC>;k@N3`Aqw`V8~lT-SK8sBxvOO%(~`#`Ek|4M4GJ^8|DE9k@>z z8etv^6u~NjR0A+TlcE{F$auVp#+|Wx0M4S2x)Xp=S7TCvNd<)4L&g~0a;02CsLpLy>ZpAw))*D7JtN5h=Vr#9cwlKB*9qS1=Tg0B}E26-hfi$aTg@fRy^cM z0C*SF)~@se2BG*byVpc_@)5yF+ccD13?MKF5l&6Y5f6EC05S$bsH7SK!vLeQNL{CJ wWfDtuS^EP30RR8A^{WQ}000I_L_t&o0L93M!ye){{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://github.com/Finb/Bark" (ctx.Locale.Tr "repo.settings.web_hook_name_bark")}}

+
+ {{.CsrfTokenHtml}} +
+ + +

{{ctx.Locale.Tr "repo.settings.bark_url_help"}}

+
+
+ + +
+
+ + +
+ {{template "repo/settings/webhook/settings" dict "BaseLink" .BaseLink "Webhook" .Webhook "UseAuthorizationHeader" false}} +
+{{end}} diff --git a/templates/repo/settings/webhook/link_menu.tmpl b/templates/repo/settings/webhook/link_menu.tmpl index e2c86dcc3c089..51e2e242425d1 100644 --- a/templates/repo/settings/webhook/link_menu.tmpl +++ b/templates/repo/settings/webhook/link_menu.tmpl @@ -47,4 +47,8 @@ {{template "shared/webhook/icon" (dict "HookType" "packagist" "Size" $size)}} {{ctx.Locale.Tr "repo.settings.web_hook_name_packagist"}} + + {{template "shared/webhook/icon" (dict "HookType" "bark" "Size" $size)}} + {{ctx.Locale.Tr "repo.settings.web_hook_name_bark"}} + diff --git a/templates/shared/webhook/icon.tmpl b/templates/shared/webhook/icon.tmpl index 105212eb56928..c87b056be583c 100644 --- a/templates/shared/webhook/icon.tmpl +++ b/templates/shared/webhook/icon.tmpl @@ -24,4 +24,6 @@ {{else if eq .HookType "packagist"}} +{{else if eq .HookType "bark"}} + {{end}} diff --git a/templates/webhook/new.tmpl b/templates/webhook/new.tmpl index 8ef33df25b45b..7d75b1a5c4dc8 100644 --- a/templates/webhook/new.tmpl +++ b/templates/webhook/new.tmpl @@ -21,5 +21,6 @@ {{template "repo/settings/webhook/matrix" .ctxData}} {{template "repo/settings/webhook/wechatwork" .ctxData}} {{template "repo/settings/webhook/packagist" .ctxData}} + {{template "repo/settings/webhook/bark" .ctxData}} {{template "repo/settings/webhook/history" .ctxData}} From c7f83586519783cf149647a5486c67ed50780c5e Mon Sep 17 00:00:00 2001 From: ZeroDeng Date: Tue, 21 Oct 2025 12:51:39 +0800 Subject: [PATCH 2/3] Simplify string concatenation in Bark webhook integration --- services/webhook/bark.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/services/webhook/bark.go b/services/webhook/bark.go index e9fee6f0942d5..00d9a2d9e44ef 100644 --- a/services/webhook/bark.go +++ b/services/webhook/bark.go @@ -121,7 +121,7 @@ func (bc barkConvertor) Push(p *api.PushPayload) (BarkPayload, error) { for i, commit := range p.Commits { body.WriteString(fmt.Sprintf("%s: %s", commit.ID[:7], strings.TrimRight(commit.Message, "\r\n"))) if commit.Author != nil { - body.WriteString(fmt.Sprintf(" - %s", commit.Author.Name)) + body.WriteString(" - " + commit.Author.Name) } if i < len(p.Commits)-1 { body.WriteString("\n") @@ -230,10 +230,10 @@ func (bc barkConvertor) Repository(p *api.RepositoryPayload) (BarkPayload, error switch p.Action { case api.HookRepoCreated: title = fmt.Sprintf("[%s] Repository created", p.Repository.FullName) - body = fmt.Sprintf("%s created repository", p.Sender.UserName) + body = p.Sender.UserName + "created repository" case api.HookRepoDeleted: title = fmt.Sprintf("[%s] Repository deleted", p.Repository.FullName) - body = fmt.Sprintf("%s deleted repository", p.Sender.UserName) + body = p.Sender.UserName + "deleted repository" default: return BarkPayload{}, nil } From de226ad79afd92d0316b769e9ff47b759080b38f Mon Sep 17 00:00:00 2001 From: ZeroDeng Date: Tue, 21 Oct 2025 13:14:55 +0800 Subject: [PATCH 3/3] Fix Bark webhook payload formatting and test adjustments Refine string formatting in Bark webhook handler for repo events, handle cases with nil repository in package payloads, and update related test assertions for clarity. --- services/webhook/bark.go | 13 +++++++++---- services/webhook/bark_test.go | 7 ++++--- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/services/webhook/bark.go b/services/webhook/bark.go index 00d9a2d9e44ef..2742891aee771 100644 --- a/services/webhook/bark.go +++ b/services/webhook/bark.go @@ -230,10 +230,10 @@ func (bc barkConvertor) Repository(p *api.RepositoryPayload) (BarkPayload, error switch p.Action { case api.HookRepoCreated: title = fmt.Sprintf("[%s] Repository created", p.Repository.FullName) - body = p.Sender.UserName + "created repository" + body = p.Sender.UserName + " created repository" case api.HookRepoDeleted: title = fmt.Sprintf("[%s] Repository deleted", p.Repository.FullName) - body = p.Sender.UserName + "deleted repository" + body = p.Sender.UserName + " deleted repository" default: return BarkPayload{}, nil } @@ -266,7 +266,12 @@ func (bc barkConvertor) Release(p *api.ReleasePayload) (BarkPayload, error) { // Package implements PayloadConvertor Package method func (bc barkConvertor) Package(p *api.PackagePayload) (BarkPayload, error) { - title := fmt.Sprintf("[%s] Package %s", p.Repository.FullName, p.Action) + repoFullName := "" + if p.Repository != nil { + repoFullName = p.Repository.FullName + } + + title := fmt.Sprintf("[%s] Package %s", repoFullName, p.Action) body := fmt.Sprintf("%s %s package %s:%s", p.Sender.UserName, p.Action, p.Package.Name, p.Package.Version) @@ -274,7 +279,7 @@ func (bc barkConvertor) Package(p *api.PackagePayload) (BarkPayload, error) { Title: title, Body: body, URL: p.Package.HTMLURL, - Group: bc.getGroup(p.Repository.FullName), + Group: bc.getGroup(repoFullName), Sound: bc.Sound, }, nil } diff --git a/services/webhook/bark_test.go b/services/webhook/bark_test.go index 5d5eea0de2a9a..821f8974cc37b 100644 --- a/services/webhook/bark_test.go +++ b/services/webhook/bark_test.go @@ -124,6 +124,7 @@ func TestBarkPayload(t *testing.T) { t.Run("Review", func(t *testing.T) { p := pullRequestTestPayload() p.Action = api.HookIssueReviewed + p.Review = nil // Remove review content for clean test pl, err := bc.Review(p, webhook_module.HookEventPullRequestReviewApproved) require.NoError(t, err) @@ -152,9 +153,9 @@ func TestBarkPayload(t *testing.T) { pl, err := bc.Package(p) require.NoError(t, err) - assert.Equal(t, "[test/repo] Package published", pl.Title) - assert.Contains(t, pl.Body, "user1 published package") - assert.Equal(t, "test/repo", pl.Group) + assert.Equal(t, "[] Package created", pl.Title) + assert.Contains(t, pl.Body, "user1 created package") + assert.Empty(t, pl.Group) }) t.Run("Wiki", func(t *testing.T) {