能效平台设计方案(打通gitlab和飞书)

最近有一个任务,需要实现一个能效平台:把 GitLab、飞书通讯录、飞书项目 Meego、飞书多维表串起来,让gitlab的每次 push 最终都变成研发能效指标。

一、为什么需要这个平台

简单来说,管理层想看,官方点就是研发过程里的数据天然分散,代码在 GitLab,人员信息在飞书通讯录,需求状态和周期在 Meego(我们公司使用的飞书项目),分析看板在飞书多维表。这样的话,管理者看到的是就是一堆碎片了,而这个平台不需要让人重复填数据,而是从研发动作本身采集数据。

当开发者推送代码时,GitLab System Hook 会把 push 事件送进平台。平台再拉取 commit 明细,解析 commit message 和分支名,识别需求 ID、提交类型和 AI 标记。随后,它用飞书通讯录补齐人员和部门,用 Meego 补齐需求名称、状态与周期,最后把结果落到 MySQL,并同步到飞书多维表。

二、总体架构

平台采用 Koa 2 + CommonJS JavaScript 实现,运行在 Node.js 18 以上,数据存储使用 MySQL 5.7,测试体系是 Mocha + Supertest。

整体分层:

层级 目录 主要职责
HTTP app/router/app/controllers/ 路由、鉴权、请求入口、统一响应
Service app/services/ 编排业务流程、后台处理、同步任务
Biz app/biz/ commit 解析、分支解析、指标聚合、周期计算
DAO app/dao/app/common/mysql.dao.js MySQL 表访问
Clients app/clients/ GitLab、飞书、Meego、多维表 OpenAPI
Jobs app/jobs/ cron 调度

Controller 不写业务逻辑,Biz 保持纯函数,外部 API 被收敛到 Client,Service 负责把各个环节串起来。后续无论是扩展指标,还是替换某个外部系统,都不需要把 HTTP 细节、数据库细节和计算逻辑混在一起改。

核心链路可以概括为:

flowchart LR A[GitLab push] --> B[Hook 入队] B --> C[后台处理] C --> D[拉取 commit 和 diff] D --> E[解析需求 ID 与 AI 标记] E --> F[聚合指标] F --> G[飞书通讯录与 Meego 补齐] G --> H[写入 MySQL] H --> I[同步飞书多维表] I --> J[主指标表与衍生统计表]

三、Hook 入口

平台的第一个入口是:

http 复制代码
POST /api/gitlab/system-hooks

校验 X-Gitlab-Token,把原始 payload 写入 dep_gitlab_hook_events

去重键来自 project_id + ref + before + after。也就是说,同一个项目、同一个分支、同一段 commit 范围的重复 hook,不会被反复入队。

这里有一个重要设计取舍:Hook 入口不直接做所有外部 API 查询。

GitLab 回调应该尽快返回。如果在回调线程里同步拉 GitLab commit、查飞书通讯录、查 Meego、写多维表,一旦某个外部系统慢下来,GitLab hook 就会被拖住。平台选择先入队,再由后台任务处理,入口负责"可靠接收",后台负责"慢慢加工"。

dep_gitlab_hook_events 表承担了这个队列角色。它保存原始 payload、状态和错误信息,状态包括 pendingprocessingdonefailed。即使处理失败,事件也不会丢,后续扫描还能继续重试。

四、后台处理

后台处理有三种触发方式:

触发方式 入口
Hook 入库后异步触发 内部 runner
定时兜底 HOOK_PROCESS_CRON,默认每分钟
手动触发 POST /api/jobs/process-hooks?limit=50

处理流程从 serv.hook-processing.js 开始。服务会扫描 pending 或 failed 事件,将其标记为 processing,然后判断是否为 push 事件,非 push 事件会被跳过。

对于 push 事件,平台先解析 Git ref 得到分支名,再通过 GitLab API 拉取 push 对应的 commit 和 diff 统计。随后每条 commit 会被标准化成统一结构,写入 dep_gitlab_commits

这张 commit 明细表保留了几个关键字段:

字段 意义
commit_shaproject_idbranch_name 定位一次提交
author_emailauthor_name 关联人员
requirement_idcommit_type 关联需求和提交类型
ai_generatedai_additions AI 代码识别结果
additionsdeletions 代码增删行统计
valid_messageinvalid_reason commit message 合规性

它的唯一键是 project_id + commit_sha + branch_name,避免同一分支上的同一次提交重复写入。

五、Commit 规范

平台能跑起来,commit message 必须有规则

当前支持的格式类似:

text 复制代码
feat: [123456] 完成登录页面
fix: [123456] 修复登录错误
docs: 更新 README

featfix 必须携带需求 ID,其他类型允许不携带。

系统 merge 和 revert 信息会被识别为 skipped,不参与需求指标。

六、指标聚合

平台的最终指标不是按单个 commit 展示,而是按下面这个维度聚合:

text 复制代码
人员邮箱 + 需求 ID + GitLab project ID + GitLab 分支

聚合后的数据写入 dep_branch_metrics,其中包含人员、需求、项目、分支、代码量、AI 代码量、AI 占比、需求周期、开发周期和 Meego 状态等字段。

其中人员和需求信息来自外部系统补齐:

补齐来源 补齐内容
飞书通讯录 工号、姓名、部门
Meego OpenAPI 需求名称、开始时间、结束时间、开发周期、状态
飞书多维表 人员和部门兜底资料

七、多维表同步

从MySQL同步到飞书多维表

同步入口有两个:

http 复制代码
POST /api/jobs/sync-base

以及定时任务,默认每天 02:00 执行。

同步时,平台会创建一条 dep_sync_runs 记录,用来追踪本次同步的状态、记录数、错误信息和完成时间。随后读取 dep_branch_metrics 全量指标,通过人员邮箱、需求 ID、GitLab project ID、GitLab 分支查找目标多维表中的已有记录,存在则更新,不存在则创建。

相关推荐
宋均浩1 小时前
# REST 的四个成熟度等级:为什么你不需要 Level 3
后端
万少1 小时前
22 点后,我靠这个 AI 工具成了"夜间天才程序员"
前端·后端
IT_陈寒2 小时前
React hooks 闭包陷阱把我的状态吃掉了,原来问题出在这里
前端·人工智能·后端
壹方秘境2 小时前
使用ApiCatcher在 iOS 上像修改 hosts 一样自定义域名解析
前端·后端·客户端
葫芦和十三3 小时前
图解 MongoDB 22|读写关注:持久性与一致性的档位选择
后端·mongodb·agent
葫芦和十三9 小时前
图解 MongoDB 21|选举与 failover:Primary 是怎么选出来的
后端·mongodb·agent
GetcharZp10 小时前
26k Star 开源内网穿透神器 NetBird,一分钟实现全球设备互联!
后端
考虑考虑10 小时前
Mybatis实现批量插入
java·后端·mybatis
咖啡八杯11 小时前
GoF设计模式——中介者模式
java·后端·spring·设计模式