From 9c08df8bc8001fc7cb59633fefc46c43e1c34122 Mon Sep 17 00:00:00 2001 From: Shudhanshu Singh Date: Tue, 14 Jul 2026 23:24:55 +0530 Subject: [PATCH 1/5] fix(org): align follow button and wrap description (#38448) ### Description Fixes the organization page header layout issue where: 1. Long organization descriptions did not wrap and instead stretched the header container out of bounds. 2. The "Follow" button floated dynamically adjacent to the description's right edge depending on the description length, instead of remaining at a fixed position aligned with the right edge of the page container. Fixes https://github.com/go-gitea/gitea/issues/38445 ### Cause The flex container `
` lacked `tw-flex-1` (to grow to fill the container) and `tw-min-w-0` (to allow it to shrink below its content's size). Consequently, the flex minimum width defaulted to `min-content`, stretching the container for long unwrapped descriptions. ### Solution Added `tw-flex-1 tw-min-w-0` to the `
` container in `templates/org/header.tmpl`. This restricts the width, enables proper text wrapping, and fixes the "Follow" button to the right edge of the content container. ### Screenshots Before image After image --------- Co-authored-by: wxiaoguang --- templates/devtest/flex-list.tmpl | 16 +++++++++++++--- templates/org/header.tmpl | 4 ++-- web_src/css/shared/flex-list.css | 2 ++ 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/templates/devtest/flex-list.tmpl b/templates/devtest/flex-list.tmpl index 26df0920c5d..2551941f7ff 100644 --- a/templates/devtest/flex-list.tmpl +++ b/templates/devtest/flex-list.tmpl @@ -1,7 +1,17 @@ {{template "devtest/devtest-header"}}
-

Flex List (standalone)

+

Flex Relaxed List

+
+
+
+ left looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong + right +
+
+
+ +

Flex Divided List (standalone)

@@ -87,7 +97,7 @@
-

Flex List (with "ui segment")

+

Flex Divided List (with "ui segment")

item 1
@@ -101,7 +111,7 @@
item 2
-

Flex List (with "ui segment fitted", items have their own padding)

+

Flex Divided List (with "ui segment fitted", items have their own padding)

item 1
diff --git a/templates/org/header.tmpl b/templates/org/header.tmpl index 4f9e54b6109..58300edc5b6 100644 --- a/templates/org/header.tmpl +++ b/templates/org/header.tmpl @@ -1,6 +1,6 @@ -
+
{{ctx.AvatarUtils.Avatar .Org 100}}
-
+
{{.Org.DisplayName}} diff --git a/web_src/css/shared/flex-list.css b/web_src/css/shared/flex-list.css index 99515c13428..cb6c69957af 100644 --- a/web_src/css/shared/flex-list.css +++ b/web_src/css/shared/flex-list.css @@ -3,6 +3,8 @@ display: flex; flex-direction: column; gap: var(--gap-block); + min-width: 0; /* keep the same style as "flex-text-block" etc, make the text content wrap/ellipse correctly */ + max-width: 100%; } .flex-relaxed-list > .divider { From b6904c97302db0e05d94cb0231cd790a0d2e7af2 Mon Sep 17 00:00:00 2001 From: Harsh Satyajit Thakur Date: Wed, 15 Jul 2026 04:24:18 +1000 Subject: [PATCH 2/5] fix: make "test push webhook" always work (#38425) * fix #38309 * fix #26238 * fix #37886 --------- Co-authored-by: wxiaoguang --- options/locale/locale_en-US.json | 1 - routers/api/v1/repo/hook.go | 2 +- routers/web/repo/setting/webhook.go | 27 ++++++--------- services/webhook/webhook.go | 27 +++++++++++++++ services/webhook/webhook_test.go | 35 ++++++++++++++++++++ templates/repo/settings/webhook/history.tmpl | 18 ++++------ 6 files changed, 81 insertions(+), 29 deletions(-) diff --git a/options/locale/locale_en-US.json b/options/locale/locale_en-US.json index 9373aa83a90..91e66940765 100644 --- a/options/locale/locale_en-US.json +++ b/options/locale/locale_en-US.json @@ -2251,7 +2251,6 @@ "repo.settings.webhook_deletion_success": "The webhook has been removed.", "repo.settings.webhook.test_delivery": "Test Push Event", "repo.settings.webhook.test_delivery_desc": "Test this webhook with a fake push event.", - "repo.settings.webhook.test_delivery_desc_disabled": "To test this webhook with a fake event, activate it.", "repo.settings.webhook.request": "Request", "repo.settings.webhook.response": "Response", "repo.settings.webhook.headers": "Headers", diff --git a/routers/api/v1/repo/hook.go b/routers/api/v1/repo/hook.go index c247fc00390..b3154696b76 100644 --- a/routers/api/v1/repo/hook.go +++ b/routers/api/v1/repo/hook.go @@ -177,7 +177,7 @@ func TestHook(ctx *context.APIContext) { commit := convert.ToPayloadCommit(ctx, ctx.Repo.Repository, ctx.Repo.Commit) commitID := ctx.Repo.Commit.ID.String() - if err := webhook_service.PrepareWebhook(ctx, hook, webhook_module.HookEventPush, &api.PushPayload{ + if err := webhook_service.PrepareTestWebhook(ctx, hook, webhook_module.HookEventPush, &api.PushPayload{ Ref: ref, Before: commitID, After: commitID, diff --git a/routers/web/repo/setting/webhook.go b/routers/web/repo/setting/webhook.go index 4d3120618f4..f128209f1be 100644 --- a/routers/web/repo/setting/webhook.go +++ b/routers/web/repo/setting/webhook.go @@ -664,19 +664,14 @@ func TestWebhook(ctx *context.Context) { return } - // Grab latest commit or fake one if it's empty repository. - // Note: in old code, the "ctx.Repo.Commit" is the last commit of the default branch. - // New code doesn't set that commit, so it always uses the fake commit to test webhook. - commit := ctx.Repo.Commit - if commit == nil { - ghost := user_model.NewGhostUser() - objectFormat := git.ObjectFormatFromName(ctx.Repo.Repository.ObjectFormatName) - commit = &git.Commit{ - ID: objectFormat.EmptyObjectID(), - Author: ghost.NewGitSig(), - Committer: ghost.NewGitSig(), - CommitMessage: git.CommitMessage{MessageRaw: "This is a fake commit"}, - } + // use a fake commit to test webhook + ghostUser := user_model.NewGhostUser() + objectFormat := git.ObjectFormatFromName(ctx.Repo.Repository.ObjectFormatName) + commit := &git.Commit{ + ID: objectFormat.EmptyObjectID(), + Author: ghostUser.NewGitSig(), + Committer: ghostUser.NewGitSig(), + CommitMessage: git.CommitMessage{MessageRaw: "This is a fake commit for webhook push test"}, } apiUser := convert.ToUserWithAccessMode(ctx, ctx.Doer, perm.AccessModeNone) @@ -697,7 +692,7 @@ func TestWebhook(ctx *context.Context) { commitID := commit.ID.String() p := &api.PushPayload{ - Ref: git.BranchPrefix + ctx.Repo.Repository.DefaultBranch, + Ref: git.RefNameFromBranch(ctx.Repo.Repository.DefaultBranch).String(), Before: commitID, After: commitID, CompareURL: setting.AppURL + ctx.Repo.Repository.ComposeCompareURL(commitID, commitID), @@ -708,8 +703,8 @@ func TestWebhook(ctx *context.Context) { Pusher: apiUser, Sender: apiUser, } - if err := webhook_service.PrepareWebhook(ctx, w, webhook_module.HookEventPush, p); err != nil { - ctx.Flash.Error("PrepareWebhook: " + err.Error()) + if err := webhook_service.PrepareTestWebhook(ctx, w, webhook_module.HookEventPush, p); err != nil { + ctx.Flash.Error("PrepareTestWebhook: " + err.Error()) ctx.Status(http.StatusInternalServerError) } else { ctx.Flash.Info(ctx.Tr("repo.settings.webhook.delivery.success")) diff --git a/services/webhook/webhook.go b/services/webhook/webhook.go index 5e8107772ac..0a53f289aa9 100644 --- a/services/webhook/webhook.go +++ b/services/webhook/webhook.go @@ -129,6 +129,33 @@ func checkBranchFilter(branchFilter string, ref git.RefName) bool { return g.Match(ref.String()) } +// PrepareTestWebhook always creates and enqueues a hook task for manual testing. +// Unlike PrepareWebhook, it ignores event subscriptions and branch filters so the +// Test Push Event control can verify delivery even when those gates would suppress +// a real event. +func PrepareTestWebhook(ctx context.Context, w *webhook_model.Webhook, event webhook_module.HookEventType, p api.Payloader) error { + if setting.DisableWebhooks { + return nil + } + + payload, err := p.JSONPayload() + if err != nil { + return fmt.Errorf("JSONPayload for %s: %w", event, err) + } + + task, err := webhook_model.CreateHookTask(ctx, &webhook_model.HookTask{ + HookID: w.ID, + PayloadContent: string(payload), + EventType: event, + PayloadVersion: 2, + }) + if err != nil { + return fmt.Errorf("CreateHookTask for %s: %w", event, err) + } + + return enqueueHookTask(task.ID) +} + // PrepareWebhook creates a hook task and enqueues it for processing. // The payload is saved as-is. The adjustments depending on the webhook type happen // right before delivery, in the [Deliver] method. diff --git a/services/webhook/webhook_test.go b/services/webhook/webhook_test.go index f20510c9a61..6ecf24337c7 100644 --- a/services/webhook/webhook_test.go +++ b/services/webhook/webhook_test.go @@ -30,6 +30,7 @@ func TestWebhookService(t *testing.T) { t.Run("PrepareBranchFilterNoMatch", testWebhookPrepareBranchFilterNoMatch) t.Run("WebhookUserMail", testWebhookUserMail) t.Run("CheckBranchFilter", testWebhookCheckBranchFilter) + t.Run("PrepareTestWebhookIgnoresGates", testPrepareTestWebhookIgnoresGates) } func testWebhookGetSlackHook(t *testing.T) { @@ -132,3 +133,37 @@ func testWebhookCheckBranchFilter(t *testing.T) { assert.Equal(t, v.match, checkBranchFilter(v.filter, v.ref), "filter: %q ref: %q", v.filter, v.ref) } } + +func testPrepareTestWebhookIgnoresGates(t *testing.T) { + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + hook := &webhook_model.Webhook{ + RepoID: repo.ID, + URL: "http://localhost/gitea-webhook-test-prepare_test_webhook", + ContentType: webhook_model.ContentTypeJSON, + IsActive: true, + HookEvent: &webhook_module.HookEvent{ + ChooseEvents: true, + BranchFilter: "dev", + HookEvents: webhook_module.HookEvents{ + webhook_module.HookEventWorkflowRun: true, + }, + }, + } + require.NoError(t, hook.UpdateEvent()) + require.NoError(t, db.Insert(t.Context(), hook)) + + payload := &api.PushPayload{ + Ref: "refs/heads/master", + Commits: []*api.PayloadCommit{{}}, + } + hookTask := &webhook_model.HookTask{HookID: hook.ID, EventType: webhook_module.HookEventPush} + + // Real deliveries stay gated: no push event + branch filter mismatch => nothing queued. + unittest.AssertNotExistsBean(t, hookTask) + require.NoError(t, PrepareWebhook(t.Context(), hook, webhook_module.HookEventPush, payload)) + unittest.AssertNotExistsBean(t, hookTask) + + // Manual test delivery always queues so the endpoint can be verified. + require.NoError(t, PrepareTestWebhook(t.Context(), hook, webhook_module.HookEventPush, payload)) + unittest.AssertExistsAndLoadBean(t, hookTask) +} diff --git a/templates/repo/settings/webhook/history.tmpl b/templates/repo/settings/webhook/history.tmpl index d57913042be..7762fca85f2 100644 --- a/templates/repo/settings/webhook/history.tmpl +++ b/templates/repo/settings/webhook/history.tmpl @@ -1,16 +1,12 @@ -{{$isNew:=or .PageIsSettingsHooksNew .PageIsAdminDefaultHooksNew .PageIsAdminSystemHooksNew}} {{if .PageIsSettingsHooksEdit}} -

- {{ctx.Locale.Tr "repo.settings.recent_deliveries"}} +

+ {{ctx.Locale.Tr "repo.settings.recent_deliveries"}} {{if .Permission.IsAdmin}} -
- - - - -
+ {{end}}

From 7c629e1ba73f7cb777ac76f7acee98a2ad9c7aff Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Wed, 15 Jul 2026 00:45:33 +0000 Subject: [PATCH 3/5] [skip ci] Updated translations via Crowdin --- options/locale/locale_cs-CZ.json | 1 - options/locale/locale_de-DE.json | 1 - options/locale/locale_el-GR.json | 1 - options/locale/locale_es-ES.json | 1 - options/locale/locale_fr-FR.json | 1 - options/locale/locale_ga-IE.json | 1 - options/locale/locale_ja-JP.json | 1 - options/locale/locale_ko-KR.json | 1 - options/locale/locale_lv-LV.json | 1 - options/locale/locale_pt-BR.json | 1 - options/locale/locale_pt-PT.json | 1 - options/locale/locale_tr-TR.json | 1 - options/locale/locale_zh-CN.json | 1 - options/locale/locale_zh-TW.json | 1 - 14 files changed, 14 deletions(-) diff --git a/options/locale/locale_cs-CZ.json b/options/locale/locale_cs-CZ.json index 1b563c085a0..73c5f2221c6 100644 --- a/options/locale/locale_cs-CZ.json +++ b/options/locale/locale_cs-CZ.json @@ -1950,7 +1950,6 @@ "repo.settings.webhook_deletion": "Odstranit webový háček", "repo.settings.webhook_deletion_desc": "Odstranění webového háčku smaže jeho nastavení a historii doručení. Pokračovat?", "repo.settings.webhook_deletion_success": "Webový háček byl smazán.", - "repo.settings.webhook.test_delivery_desc_disabled": "Chcete-li tento webový háček otestovat s falešnou událostí, aktivujte ho.", "repo.settings.webhook.request": "Požadavek", "repo.settings.webhook.response": "Odpověď", "repo.settings.webhook.headers": "Hlavičky", diff --git a/options/locale/locale_de-DE.json b/options/locale/locale_de-DE.json index 569e0fcc4cc..44f42c58311 100644 --- a/options/locale/locale_de-DE.json +++ b/options/locale/locale_de-DE.json @@ -2251,7 +2251,6 @@ "repo.settings.webhook_deletion_success": "Webhook wurde entfernt.", "repo.settings.webhook.test_delivery": "Test Push Ereignis", "repo.settings.webhook.test_delivery_desc": "Teste diesen Webhook mit einem Fake-Push-Event.", - "repo.settings.webhook.test_delivery_desc_disabled": "Um diesen Webhook mit einem Fake-Event zu testen, aktiviere ihn.", "repo.settings.webhook.request": "Anfrage", "repo.settings.webhook.response": "Antwort", "repo.settings.webhook.headers": "Kopfzeilen", diff --git a/options/locale/locale_el-GR.json b/options/locale/locale_el-GR.json index ad0012c7a48..ab251040286 100644 --- a/options/locale/locale_el-GR.json +++ b/options/locale/locale_el-GR.json @@ -1781,7 +1781,6 @@ "repo.settings.webhook_deletion": "Αφαίρεση Webhook", "repo.settings.webhook_deletion_desc": "Η αφαίρεση ενός webhook διαγράφει τις ρυθμίσεις και το ιστορικό παραδόσεων. Συνέχεια;", "repo.settings.webhook_deletion_success": "Το webhook έχει αφαιρεθεί.", - "repo.settings.webhook.test_delivery_desc_disabled": "Για να δοκιμάσετε αυτό το webhook με μια ψεύτικη κλήση, ενεργοποιήστε το.", "repo.settings.webhook.request": "Αίτημα", "repo.settings.webhook.response": "Απάντηση", "repo.settings.webhook.headers": "Κεφαλίδες", diff --git a/options/locale/locale_es-ES.json b/options/locale/locale_es-ES.json index 6dc1065cdbf..bc5ea04d6a9 100644 --- a/options/locale/locale_es-ES.json +++ b/options/locale/locale_es-ES.json @@ -1753,7 +1753,6 @@ "repo.settings.webhook_deletion": "Eliminar Webhook", "repo.settings.webhook_deletion_desc": "Eliminar un webhook borra sus ajustes e historial de entrega. ¿Continuar?", "repo.settings.webhook_deletion_success": "El webhook ha sido eliminado.", - "repo.settings.webhook.test_delivery_desc_disabled": "Para probar este webhook con un evento falso, actívalo.", "repo.settings.webhook.request": "Petición", "repo.settings.webhook.response": "Respuesta", "repo.settings.webhook.headers": "Encabezado", diff --git a/options/locale/locale_fr-FR.json b/options/locale/locale_fr-FR.json index 047d8420cb3..739acec24d6 100644 --- a/options/locale/locale_fr-FR.json +++ b/options/locale/locale_fr-FR.json @@ -2251,7 +2251,6 @@ "repo.settings.webhook_deletion_success": "Le webhook a été supprimé.", "repo.settings.webhook.test_delivery": "Tester l’envoi", "repo.settings.webhook.test_delivery_desc": "Testez ce webhook avec un faux événement.", - "repo.settings.webhook.test_delivery_desc_disabled": "Pour tester ce webhook avec un faux événement, activez-le.", "repo.settings.webhook.request": "Requête", "repo.settings.webhook.response": "Réponse", "repo.settings.webhook.headers": "Entêtes", diff --git a/options/locale/locale_ga-IE.json b/options/locale/locale_ga-IE.json index ef4c368d2b5..132c9d325d8 100644 --- a/options/locale/locale_ga-IE.json +++ b/options/locale/locale_ga-IE.json @@ -2251,7 +2251,6 @@ "repo.settings.webhook_deletion_success": "Tá an Crúca Gréasán bainte amach.", "repo.settings.webhook.test_delivery": "Imeacht Brúigh Tástála", "repo.settings.webhook.test_delivery_desc": "Déan tástáil ar an webhook seo le teagmhas brú bréige.", - "repo.settings.webhook.test_delivery_desc_disabled": "Chun an Crúca Gréasán seo a thástáil le himeacht bhréige, gníomhachtaigh é.", "repo.settings.webhook.request": "Iarratas", "repo.settings.webhook.response": "Freagra", "repo.settings.webhook.headers": "Ceanntásca", diff --git a/options/locale/locale_ja-JP.json b/options/locale/locale_ja-JP.json index 7486bf5473e..a9dabf1772d 100644 --- a/options/locale/locale_ja-JP.json +++ b/options/locale/locale_ja-JP.json @@ -2251,7 +2251,6 @@ "repo.settings.webhook_deletion_success": "Webhookを削除しました。", "repo.settings.webhook.test_delivery": "プッシュ・イベントによるテスト", "repo.settings.webhook.test_delivery_desc": "ダミーのプッシュ・イベントでこのWebhookをテストします。", - "repo.settings.webhook.test_delivery_desc_disabled": "このWebhookをダミーのイベントでテストするには、有効にしてください。", "repo.settings.webhook.request": "リクエスト", "repo.settings.webhook.response": "レスポンス", "repo.settings.webhook.headers": "ヘッダー", diff --git a/options/locale/locale_ko-KR.json b/options/locale/locale_ko-KR.json index 20497594251..41e5771ee3a 100644 --- a/options/locale/locale_ko-KR.json +++ b/options/locale/locale_ko-KR.json @@ -2248,7 +2248,6 @@ "repo.settings.webhook_deletion_success": "Webhook을 삭제했습니다.", "repo.settings.webhook.test_delivery": "푸시 이벤트 테스트", "repo.settings.webhook.test_delivery_desc": "가짜 푸시 이벤트로 웹훅을 테스트합니다.", - "repo.settings.webhook.test_delivery_desc_disabled": "가짜 이벤트로 이 웹훅을 테스트하려면 활성화하십시오.", "repo.settings.webhook.request": "요청", "repo.settings.webhook.response": "응답", "repo.settings.webhook.headers": "제목", diff --git a/options/locale/locale_lv-LV.json b/options/locale/locale_lv-LV.json index bfc3efc8edf..fedce5f0f39 100644 --- a/options/locale/locale_lv-LV.json +++ b/options/locale/locale_lv-LV.json @@ -1812,7 +1812,6 @@ "repo.settings.webhook_deletion": "Noņemt tīmekļa āķi", "repo.settings.webhook_deletion_desc": "Noņemot tīmekļa āķi, tiks dzēsti visi tā iestatījumi un piegādes vēsture. Vai turpināt?", "repo.settings.webhook_deletion_success": "Tīmekļa āķis tika noņemts.", - "repo.settings.webhook.test_delivery_desc_disabled": "Lai pārbaudītu šo tīmekļa āķi ar neīstu notikumu, tas ir jāiespējo.", "repo.settings.webhook.request": "Pieprasījums", "repo.settings.webhook.response": "Atbilde", "repo.settings.webhook.headers": "Galvenes", diff --git a/options/locale/locale_pt-BR.json b/options/locale/locale_pt-BR.json index 8d42a84e5c6..4d3633f8b02 100644 --- a/options/locale/locale_pt-BR.json +++ b/options/locale/locale_pt-BR.json @@ -2019,7 +2019,6 @@ "repo.settings.webhook_deletion_success": "O webhook foi removido.", "repo.settings.webhook.test_delivery": "Testar Evento de Push", "repo.settings.webhook.test_delivery_desc": "Teste este webhook com um evento falso.", - "repo.settings.webhook.test_delivery_desc_disabled": "Para testar este webhook com um evento falso, ative-o.", "repo.settings.webhook.request": "Solicitação", "repo.settings.webhook.response": "Resposta", "repo.settings.webhook.headers": "Cabeçalhos", diff --git a/options/locale/locale_pt-PT.json b/options/locale/locale_pt-PT.json index b02ac313810..23cb9425231 100644 --- a/options/locale/locale_pt-PT.json +++ b/options/locale/locale_pt-PT.json @@ -2251,7 +2251,6 @@ "repo.settings.webhook_deletion_success": "O automatismo web foi removido.", "repo.settings.webhook.test_delivery": "Testar o envio", "repo.settings.webhook.test_delivery_desc": "Testar este automatismo web com um evento de envio falso.", - "repo.settings.webhook.test_delivery_desc_disabled": "Para testar este automatismo web com um evento falso, habilite-o.", "repo.settings.webhook.request": "Pedido", "repo.settings.webhook.response": "Resposta", "repo.settings.webhook.headers": "Cabeçalhos", diff --git a/options/locale/locale_tr-TR.json b/options/locale/locale_tr-TR.json index d1aeed537b8..5ef8d890e2a 100644 --- a/options/locale/locale_tr-TR.json +++ b/options/locale/locale_tr-TR.json @@ -2204,7 +2204,6 @@ "repo.settings.webhook_deletion_success": "Web isteği silindi.", "repo.settings.webhook.test_delivery": "İtme Olayını Sına", "repo.settings.webhook.test_delivery_desc": "Bu web istemcisini sahte bir itme olayıyla sınayın.", - "repo.settings.webhook.test_delivery_desc_disabled": "Bu web istemcisini sahte bir olayla denemek için etkinleştirin.", "repo.settings.webhook.request": "İstekler", "repo.settings.webhook.response": "Cevaplar", "repo.settings.webhook.headers": "Başlıklar", diff --git a/options/locale/locale_zh-CN.json b/options/locale/locale_zh-CN.json index a81cd20d796..6759b09b579 100644 --- a/options/locale/locale_zh-CN.json +++ b/options/locale/locale_zh-CN.json @@ -2251,7 +2251,6 @@ "repo.settings.webhook_deletion_success": "Web 钩子删除成功!", "repo.settings.webhook.test_delivery": "测试推送事件", "repo.settings.webhook.test_delivery_desc": "用假推送事件测试这个 Web 钩子。", - "repo.settings.webhook.test_delivery_desc_disabled": "要用假事件测试这个 Web钩子,请激活它。", "repo.settings.webhook.request": "请求内容", "repo.settings.webhook.response": "响应内容", "repo.settings.webhook.headers": "头信息", diff --git a/options/locale/locale_zh-TW.json b/options/locale/locale_zh-TW.json index ef25bbe25d8..41e4cb5f224 100644 --- a/options/locale/locale_zh-TW.json +++ b/options/locale/locale_zh-TW.json @@ -1952,7 +1952,6 @@ "repo.settings.webhook_deletion": "移除 Webhook", "repo.settings.webhook_deletion_desc": "移除 Webhook 將刪除它的設定及傳送記錄,是否繼續?", "repo.settings.webhook_deletion_success": "Webhook 已移除。", - "repo.settings.webhook.test_delivery_desc_disabled": "要使用假事件測試此 Webhook,請啟用它。", "repo.settings.webhook.request": "請求", "repo.settings.webhook.response": "回應", "repo.settings.webhook.headers": "標頭", From 880ddb572456dfbec87eee703513bb78edc4b7ce Mon Sep 17 00:00:00 2001 From: xkm Date: Wed, 15 Jul 2026 10:36:03 +0800 Subject: [PATCH 4/5] fix(actions): prevent bulk actions from affecting all runners (#38453) Fix the bug in the site-admin runner bulk actions introduced by #37869: the runner IDs are empty then all runners will be deleted. Fixes #38449 --------- Co-authored-by: wxiaoguang --- routers/web/shared/actions/runners.go | 16 +++++++++------- templates/shared/actions/runner_list.tmpl | 6 +++--- tests/integration/actions_runner_modify_test.go | 7 +++++++ web_src/js/features/admin/common.ts | 10 +--------- 4 files changed, 20 insertions(+), 19 deletions(-) diff --git a/routers/web/shared/actions/runners.go b/routers/web/shared/actions/runners.go index f174bfb1cd4..21a2bb8fc1d 100644 --- a/routers/web/shared/actions/runners.go +++ b/routers/web/shared/actions/runners.go @@ -373,16 +373,18 @@ func RunnerBulkActionPost(ctx *context.Context) { return } - var runnerIDs []int64 - if rCtx.IsAdmin { - // ATTENTION: it completely depends on the assumption that the doer is "site admin" - // So it doesn't do extra permission check to the runner IDs - // In the future, if you need to support such operation on non-admin pages, be careful! - runnerIDs = ctx.FormStringInt64s("ids") - } else { + if !rCtx.IsAdmin { ctx.HTTPError(http.StatusForbidden, "bulk actions are admin-only") return } + // ATTENTION: it completely depends on the assumption that the doer is "site admin" + // So it doesn't do extra permission check to the runner IDs + // In the future, if you need to support such operation on non-admin pages, be careful! + runnerIDs := ctx.FormStringInt64s("ids") + if len(runnerIDs) == 0 { + ctx.HTTPError(http.StatusBadRequest, "missing runner IDs") + return + } action := ctx.FormString("action") var successKey, failedKey string diff --git a/templates/shared/actions/runner_list.tmpl b/templates/shared/actions/runner_list.tmpl index 1b287cdabc2..03400fa3a79 100644 --- a/templates/shared/actions/runner_list.tmpl +++ b/templates/shared/actions/runner_list.tmpl @@ -44,9 +44,9 @@
- - - + +