Files
GiteaToFeishuMsg/README.md

295 lines
9.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Gitea 到飞书 Webhook 中转服务
将 Gitea 的工单事件(创建、更新、关闭等)通过 Webhook 接收,转换为美观的飞书卡片消息,并转发到飞书群聊。
## 功能特性
- 接收 Gitea Webhook 事件(支持工单相关动作)
- 验证 Webhook 签名(可选)
- 将事件转换为飞书交互式卡片
- 支持自定义卡片标题、颜色、字段
- 完整的错误处理和日志记录
- 健康检查端点
- 易于部署和配置
## 系统架构
```
Gitea → Webhook → 中转服务 (Express) → 飞书机器人 → 飞书群聊
```
## 快速开始
### 前提条件
- Node.js 18+
- 一个飞书机器人,并获取其 Webhook URL
- Gitea 实例(版本 1.20+
### 安装
1. 克隆仓库
```bash
git clone <repository-url>
cd gitea-feishu-webhook-relay
```
2. 安装依赖
```bash
npm install
```
3. 配置环境变量
复制 `.env.example``.env` 并填写实际值:
```bash
cp .env.example .env
```
编辑 `.env`
```env
PORT=3000
GITEA_WEBHOOK_SECRET=your_gitea_webhook_secret
FEISHU_WEBHOOK_URL=https://open.feishu.cn/open-apis/bot/v2/hook/xxx
LOG_LEVEL=info
```
### 运行
开发模式(使用 nodemon
```bash
npm run dev
```
生产模式:
```bash
npm start
```
服务将在 `http://localhost:3000` 启动。
## 配置 Gitea Webhook
### 重要:选择正确的 Webhook 类型
确保在 Gitea 中创建 Webhook 时选择 **“Gitea”** 类型而不是“飞书”或其他类型。Gitea 类型会发送结构化的 JSON 数据,便于解析。
### 详细字段填写(根据用户界面)
在 Gitea 的 Webhook 创建页面中,请按以下说明填写:
| 字段 | 填写示例 | 说明 |
|------|----------|------|
| **目标 URL** | `http://192.168.0.15:3001``http://192.168.0.15:3001/webhook/gitea` | 根据你的服务地址和端口默认为3000若修改了环境变量 `PORT` 则对应调整)。如果服务部署在本地,请使用内网 IP。 |
| **HTTP 方法** | `POST` | 保持默认。 |
| **内容类型** | `application/json` | 保持默认。 |
| **授权标头** | (留空) | 除非你的服务需要 Bearer 或 Basic 认证,否则不需要填写。 |
| **密钥** | (可选)填写与 `GITEA_WEBHOOK_SECRET` 环境变量相同的字符串 | 用于验证 Webhook 请求的签名,增强安全性。如果留空,服务将跳过签名验证。 |
| **触发事件** | 勾选 **“工单事件”**Issue | 可根据需要勾选其他事件,但本服务目前只处理工单事件。 |
### 步骤
1. 进入 Gitea 仓库的设置 → Webhooks → 添加 Webhook。
2. 选择 **“Gitea”** 类型(不要选“飞书”或“自定义”)。
3. 按照上表填写各字段。
4. 点击“添加 Webhook”保存。
### 验证
保存后Gitea 会立即发送一个测试事件ping。检查服务日志以确认接收成功。如果看到日志输出 `Received Gitea webhook` 且没有错误,说明配置正确。
## 飞书机器人配置
1. 在飞书开放平台创建一个自定义机器人,获取 Webhook URL。
2. 将机器人添加到目标群聊。
3. 将 Webhook URL 填入 `FEISHU_WEBHOOK_URL`
## API 端点
- `GET /health` 健康检查
- `POST /webhook/gitea` 接收 Gitea Webhook推荐
- `POST /` 接收 Gitea Webhook备用兼容旧配置
## 日志
日志使用 Winston 输出到控制台和文件:
- `logs/error.log` 错误日志
- `logs/combined.log` 所有日志
## 自定义消息格式
如果你希望修改飞书卡片的样式、字段或映射关系,可以编辑 `src/transformers/giteaToFeishu.js` 文件。该文件导出了 `transformToFeishuCard` 函数,负责将 Gitea 事件转换为飞书卡片。
### 主要可配置部分
1. **动作映射**`getCardInfo(action)` 函数定义了每个 Gitea 动作对应的卡片标题和颜色模板。你可以修改 `mapping` 对象来更改标题或颜色。
2. **优先级提取**`extractPriority(labels)` 函数根据标签确定优先级。你可以调整逻辑以适应你的标签命名规范。
3. **卡片元素**`transformToFeishuCard` 函数中的 `card.elements` 数组定义了卡片显示的字段。你可以添加、删除或修改元素来改变卡片内容。
### 标签颜色映射
服务支持根据工单标签自动调整卡片颜色。例如,如果工单带有 `scope:非必要任务``scope:普通任务``scope:紧急任务``scope:重要任务` 等标签,卡片头部颜色会相应变化:
| 标签 | 颜色 | 说明 |
|------|------|------|
| `scope:非必要任务` | 灰色 (`grey`) | 低优先级任务 |
| `scope:普通任务` | 蓝色 (`blue`) | 默认任务 |
| `scope:紧急任务` | 红色 (`red`) | 需要立即处理 |
| `scope:重要任务` | 橙色 (`orange`) | 重要但不紧急 |
颜色映射逻辑位于 `getScopeColor(labels)` 函数中。你可以修改该函数以支持更多标签或更改颜色。
此外,卡片会显示一个“范围”字段,展示匹配的标签名称。
### 示例:添加新字段
假设你想显示工单的创建时间,可以在 `elements` 数组中添加一个新的 `div` 元素:
```javascript
{
tag: 'div',
text: {
tag: 'lark_md',
content: `**创建时间**${new Date(issue.created_at).toLocaleString()}`
}
}
```
### 高级自定义
如果你需要更灵活的自定义(例如根据不同的仓库使用不同的模板),可以考虑以下方案:
- 创建新的转换器模块,并在 `src/webhooks/gitea.js` 中替换导入。
- 使用配置文件(如 `config/cardTemplates.json`)来定义模板,并在转换器中读取。
### 注意事项
- 飞书卡片支持的元素和样式请参考[飞书开放平台文档](https://open.feishu.cn/document/uAjLw4CM/ukzMukzMukzM/overview)。
- 修改后请重启服务以使更改生效。
## Docker 部署
提供 Dockerfile 便于容器化部署。
构建镜像:
```bash
docker build -t gitea-feishu-relay .
```
运行容器:
```bash
docker run -p 3000:3000 --env-file .env gitea-feishu-relay
```
## 环境变量
| 变量名 | 描述 | 默认值 |
|--------|------|--------|
| PORT | 服务监听端口 | 3000 |
| GITEA_WEBHOOK_SECRET | Gitea Webhook 签名密钥 | (空) |
| FEISHU_WEBHOOK_URL | 飞书机器人 Webhook URL | (必需) |
| LOG_LEVEL | 日志级别 (error, warn, info, debug) | info |
| NODE_ENV | 运行环境 (development, production) | development |
## 开发
### 项目结构
```
src/
├── server.js # Express 服务器入口
├── config.js # 配置管理
├── webhooks/
│ └── gitea.js # Webhook 处理器
├── transformers/
│ └── giteaToFeishu.js # 消息转换器
├── clients/
│ └── feishu.js # 飞书 API 客户端
└── utils/
└── logger.js # 日志工具
```
### 测试
运行单元测试:
```bash
npm test
```
## 测试建议
### 1. 启动服务
确保服务已运行并监听正确端口:
```bash
npm start
```
检查控制台输出是否有 `Server listening on port 3001`(或你设置的端口)。
### 2. 健康检查
使用 curl 或浏览器访问健康检查端点:
```bash
curl http://localhost:3001/health
```
应返回 `{"status":"ok","timestamp":"..."}`
### 3. 模拟 Gitea Webhook 请求
你可以使用 `curl` 发送一个模拟的 Gitea 工单事件来测试转换和转发功能:
```bash
curl -X POST http://localhost:3001/webhook/gitea \
-H "Content-Type: application/json" \
-H "X-Gitea-Signature: sha256=..." \
-d '{
"action": "opened",
"issue": {
"id": 123,
"number": 45,
"title": "测试工单",
"body": "这是一个测试工单",
"state": "open",
"created_at": "2025-12-02T05:00:00Z",
"user": {
"id": 1,
"login": "testuser",
"full_name": "测试用户"
},
"assignee": null,
"labels": [],
"milestone": null
},
"repository": {
"id": 1,
"name": "test-repo",
"full_name": "org/test-repo",
"html_url": "https://gitea.example.com/org/test-repo"
},
"sender": {
"id": 1,
"login": "testuser"
}
}'
```
如果配置了 `FEISHU_WEBHOOK_URL`,服务会将转换后的卡片发送到飞书群聊。检查服务日志和飞书群聊以确认消息送达。
### 4. 查看日志
日志文件位于 `logs/` 目录,或直接在控制台查看。关注 `info``error` 级别的消息。
## 故障排除
1. **收不到飞书消息**
- 检查 `FEISHU_WEBHOOK_URL` 是否正确
- 查看日志中是否有错误信息
- 确认飞书机器人已加入群聊
2. **Gitea Webhook 验证失败**
- 确保 `GITEA_WEBHOOK_SECRET` 与 Gitea 中设置的密钥一致
- 检查请求头中是否包含 `X-Gitea-Signature`
3. **服务无法启动**
- 确认端口未被占用
- 检查 Node.js 版本
4. **Webhook 请求被忽略**
- 确认 Gitea 发送的 JSON 格式符合预期(包含 `action``issue``repository`
- 检查日志中是否有 `Event ignored` 消息,可能是动作被过滤(如 `labeled`
## 许可证
MIT