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")}}
+
+{{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) {