diff --git a/backend/docs/API.md b/backend/docs/API.md index 6a4d486..f39da58 100644 --- a/backend/docs/API.md +++ b/backend/docs/API.md @@ -85,7 +85,7 @@ curl -X POST http://localhost:9527/api/ai/release \ | `/api/build-nodes/:id/disk-test` | POST | dd 磁盘性能实测(256MB,本机 exec 或 SSH 远程;返回读写 MB/s) | | `/api/tools` | GET/PUT | 工具清单与安装策略 | | `/api/tools/:id/check` | POST | 真实执行版本探测命令 | -| `/api/webhooks` | CRUD + `/:id/test` | 出站 Webhook(HMAC-SHA256 签名发送) | +| `/api/webhooks` | CRUD + `/:id/test` | 出站 Webhook(HMAC-SHA256 签名发送,配置入口:系统设置→消息通知) | | `/api/hooks/pipeline/:id?token=` | POST | 入站触发流水线(免鉴权,token 校验) | ## Jenkins diff --git a/backend/docs/GUIDE.md b/backend/docs/GUIDE.md index a0c26ba..271efbe 100644 --- a/backend/docs/GUIDE.md +++ b/backend/docs/GUIDE.md @@ -89,13 +89,15 @@ cex-agent-admin - 「检测」真实执行版本探测命令(如 `java -version`);「安装」是保守策略——只检测不自动下载 - `deploy/Dockerfile.buildnode` 一键构建 Ubuntu 构建节点镜像 -## 飞书 / Lark 通知 +## 飞书 / Lark 通知与 Webhook **是什么**:发布成功/失败自动向群推送结果卡片(应用/分支/构建/状态/时间 + 「查看构建详情」按钮直达 Jenkins)。 **怎么用**:系统设置 → 消息通知 → 填群机器人 Webhook(和可选的签名密钥)→「发送测试卡片」验证。 -**技巧**:单条流水线可在「基本信息」里单独填通知 Webhook,优先于全局配置。 +**技巧**: +- 单条流水线可在「基本信息」里单独填通知 Webhook,优先于全局配置 +- 通用 Webhook 回调(发给第三方系统,HMAC-SHA256 签名)也在系统设置 → 消息通知里配置 ## 用户与 LDAP diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 137ffe8..346def5 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -17,7 +17,6 @@ import ToolConfig from '@/pages/ToolConfig'; import JenkinsImport from '@/pages/JenkinsImport'; import BatchRelease from '@/pages/BatchRelease'; import ReleaseRecords from '@/pages/ReleaseRecords'; -import WebhookConfig from '@/pages/WebhookConfig'; import GitOpsDeploy from '@/pages/GitOpsDeploy'; import PluginManager from '@/pages/PluginManager'; import SystemSettings from '@/pages/SystemSettings'; @@ -27,7 +26,7 @@ import UserManage from '@/pages/UserManage'; import Docs from '@/pages/Docs'; import { apiClient, auth } from '@/lib/api'; -export type ModuleType = 'pipelines' | 'gitops' | 'batch-release' | 'release-records' | 'environments' | 'credentials' | 'build-nodes' | 'tools' | 'jenkins-import' | 'webhooks' | 'plugins' | 'users' | 'docs' | 'settings'; +export type ModuleType = 'pipelines' | 'gitops' | 'batch-release' | 'release-records' | 'environments' | 'credentials' | 'build-nodes' | 'tools' | 'jenkins-import' | 'plugins' | 'users' | 'docs' | 'settings'; export type EditorTab = '基本信息' | '流程配置' | '触发设置' | '变量和缓存' | '发布'; // 路由 ↔ 模块映射(用户可直接访问 /release、/pipelines/1 等) @@ -42,7 +41,6 @@ const ROUTE_TO_MODULE: Record = { '/build-nodes': 'build-nodes', '/tools': 'tools', '/jenkins-import': 'jenkins-import', - '/webhooks': 'webhooks', '/plugins': 'plugins', '/users': 'users', '/docs': 'docs', @@ -59,7 +57,6 @@ const MODULE_TO_ROUTE: Record = { 'build-nodes': '/build-nodes', tools: '/tools', 'jenkins-import': '/jenkins-import', - webhooks: '/webhooks', plugins: '/plugins', users: '/users', docs: '/docs', @@ -230,8 +227,6 @@ export default function App() { return goToModule('release-records')} />; case 'release-records': return ; - case 'webhooks': - return ; case 'gitops': return ; case 'plugins': diff --git a/frontend/src/components/Sidebar.tsx b/frontend/src/components/Sidebar.tsx index e3be8d4..4588157 100644 --- a/frontend/src/components/Sidebar.tsx +++ b/frontend/src/components/Sidebar.tsx @@ -10,7 +10,6 @@ import { Rocket, Zap, History, - Webhook, CloudSync, Puzzle, Settings, @@ -24,7 +23,7 @@ import { useQuery } from '@tanstack/react-query'; import { apiClient } from '@/lib/api'; import { useTheme } from '@/providers/theme'; -type ModuleType = 'pipelines' | 'gitops' | 'batch-release' | 'release-records' | 'environments' | 'credentials' | 'build-nodes' | 'tools' | 'jenkins-import' | 'webhooks' | 'plugins' | 'users' | 'docs' | 'settings'; +type ModuleType = 'pipelines' | 'gitops' | 'batch-release' | 'release-records' | 'environments' | 'credentials' | 'build-nodes' | 'tools' | 'jenkins-import' | 'plugins' | 'users' | 'docs' | 'settings'; interface SidebarProps { activeModule: ModuleType; @@ -56,7 +55,6 @@ const menuGroups: { label: string; items: { id: ModuleType; label: string; icon: label: '集成', items: [ { id: 'jenkins-import', label: 'Jenkins导入', icon: Download, badge: null }, - { id: 'webhooks', label: 'Webhook', icon: Webhook, badge: null }, { id: 'tools', label: '工具配置', icon: Wrench, badge: null }, ], }, diff --git a/frontend/src/pages/WebhookConfig.tsx b/frontend/src/components/settings/WebhookManager.tsx similarity index 95% rename from frontend/src/pages/WebhookConfig.tsx rename to frontend/src/components/settings/WebhookManager.tsx index 16649e1..a71a0de 100644 --- a/frontend/src/pages/WebhookConfig.tsx +++ b/frontend/src/components/settings/WebhookManager.tsx @@ -49,7 +49,7 @@ const formatTime = (v: string | null | undefined) => { const emptyForm = { name: '', url: '', secret: '', events: [] as string[] }; -export default function WebhookConfig() { +export default function WebhookManager() { const queryClient = useQueryClient(); const [showForm, setShowForm] = useState(false); const [editingId, setEditingId] = useState(null); @@ -137,14 +137,13 @@ export default function WebhookConfig() { }; return ( -
- {/* Header */} -
-
-

Webhook 配置

- - {webhooks.length} - +
+ {/* Card Header */} +
+
+ + Webhook 通知 + 发布事件回调第三方(HMAC-SHA256 签名)
- {/* Content */} -
+ {/* Body */} +
{showForm && (

{editingId != null ? '编辑 Webhook' : '新建 Webhook'}

diff --git a/frontend/src/pages/SystemSettings.tsx b/frontend/src/pages/SystemSettings.tsx index 4a6f40c..4a035c3 100644 --- a/frontend/src/pages/SystemSettings.tsx +++ b/frontend/src/pages/SystemSettings.tsx @@ -7,6 +7,7 @@ import { toast } from 'sonner'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { apiClient } from '@/lib/api'; import { useTheme, type ThemeMode } from '@/providers/theme'; +import WebhookManager from '@/components/settings/WebhookManager'; interface ThemeConfig { mode: 'light' | 'dark' | 'system'; @@ -638,6 +639,10 @@ export default function SystemSettings() {
+ +
+ +
)}