一个适用于openharmony中多维度代码审查的webhook服务
开源代码管控系统 (Python+MySQL版)
🌟 项目简介
基于Python Flask框架和MySQL数据库构建的轻量级代码管理系统,提供完整的代码版本控制、团队协作和项目管理功能。
📂 项目结构
├── code_spectra/
│ ├── __init__.py
│ ├── code_spectra.py # 事件处理
│ └── manifest.json # hook事件及子事件配置文件
├── constants/ # 常量
├── config/ # 托管平台配置
├── db/
│ ├── database.py # 数据库模型
│ └── utils.py # 数据库操作常用函数
└── log/ # 仅用于存放日志的目录
└── logger/ # 日志模型
└── tools/ # 工具模型
│ ├── file_searcher.py # 用于检查目录或文件是否属于给出的目录和文件当中
│ ├── git_clinet.py # 用于与托管平台进行交互,如检视/评论/获取评论/获取文件等等
│ ├── owner_config_mgr.py # 用于更新库上最新的owner_config.json文件到本地
│ ├── mapping_check.py # 用于更新库上最新的多线程映射(一个特殊的子事件,并非必须)文件
│ └── webhook.py # webhook模型
└── sub_events/ # 子事件,不一一介绍
│ └── __init__.py # 遍历整个目录将所有的子事件注册到ALL_REGISTERED_EVENTS中
└── tests/ # TDD
└── database.toml # 数据库/API配置文件
└── main.py # 代码入口
└── start.sh # 启动脚本
✨ 核心功能
通过审查权力拆分,配置code_spectra/manifest.json,对各种webhook自定义子事件,完成个性化的代码合入前管控。
概念介绍
- 一个webhook称为一个事件,该事件可以配置多个子事件(sub_events),对他的子事件而言,该hook事件为父事件。
- sub_events中定义了所有可配置的子事件。
- 审查权力拆分: 原来给PR进行加分,只需要审查人的个人账号点击“审查通过”即可完成。
graph TD
A[个人账号] --> B[点击审查通过]
B --> C[审查通过]
现在,我们成立了多个逻辑上的小组,每个小组有一个独立的平台账号,负责自己责任模块的代码文件,相应的,PR只允许组账号进行加分,而不是个人账号。
每个逻辑小组内配备负责该模块的组员。
graph TD
A[个人账号] --> B[在PR下面评论pass]
B --> C[触发gitee的webhook]
C -->|在这里植入我们的管控| D{管控检查通过?}
D --> E[使用这个人所属的小组账号进行审查]
E -->|是| F[审查通过,成功加分]
E -->|否| G[审查失败,不允许加分]
这样在个人加分转变成组加分的过程中,便可插入我们的管控事件,实现审查权力的拆分。
运行流程
每个子事件有三个阶段
- pre_execute:事件执行前的检查,是否满足执行条件,如果没有校验条件可不重写该函数,返回false则不执行execute/post_execute。
- execute:事件执行逻辑,每个子事件必须重写该函数,返回false则不执行post_execute。
- send_comment:对PR进行评论回复,由框架统一控制。
🚀 快速开始
前置条件
python环境搭建
- 本地安装python(≥3.8版本),可在互联网上搜索教程,本文不赘述。
- 装好python后,打开终端(cmd),执行以下命令安装uv:
pip install uv
- 进入项目目录所在目录,打开终端(cmd),执行以下命令:
uv sync # 同步项目依赖,时间可能较长,请耐心等待
成立小组
- 将自己域内的业务范围按模块划分,注册新的托管平台账号,名称例如arkui_image。
- 请代码仓的管理员邀请这些小组账号加入组织。
- 使用托管平台的codeowner能力,在/代码仓/.gitxxx/CODEOWNERS中将每个目录或文件划分到不同的小组下,这样提交PR就会自动分配小组账号为该笔PR的审查人了。
添加组员
- 在/代码仓/.gitxxx/下新建owner_config.json,层级如下
{
"groups": {
"$小组账户1主页账户名": [
"$小组1成员1的主页账户名",
"$小组1成员2的主页账户名"
],
"$小组账户2的g主页账户名": [
"$小组2成员1的主页账户名",
"$小组2成员2的主页账户名"
]
},
"userInfos": {
"$成员1的主页账户名": {
"info": "$ta的个人信息,可自行发挥,比如他负责的模块+姓名,如[图片类组件 zhangsan]"
},
"$成员2的g主页账户名": {
"info": "$ta的个人信息"
}
}
}
克隆仓库
git clone https://gitcode.com/liyujie43/CodeSpectra.git
创建数据库(重要)
- 建议安装mysql 8.0+ (必做)
- 数据库配置也在app.toml中,详情见下文
mysql -u root -p -e "CREATE DATABASE pr_management"
配置说明
database.toml
打开database.toml修改以下必填配置:
[database]
user = "你的mysql用户"
password = "你的mysql密码"
host = "localhost"
db_name = "你的mysql数据库名称"
config.toml
其他配置在config/[平台]/config.toml中可自行添加和修改:
[accounts.groups]
# 填写你的组账号信息,如
# "https://gitxxx.com/xxx" = "xxx的token"
[accounts.admin_user]
# 填写仓库管理员信息,如
# "https://gitxxx.com/xxx" = "xxx的token"
[accounts.notifier]
# 填写特性管理员账号,用来推送评论,如
# "https://gitxxx.com/xxx" = "xxx的token"
-
check_tdd.force_accounts则是可以强制通过测试用例检查的人员名单
-
check_mod.force_accounts是可以强制通过侵入式修改检查的的人员名单
详情可以查看config.toml配置文件
配置完成后需要将config.toml拷贝到config目录下的具体托管平台中。
manifest.json
我们提前定义好所有的check_events,方便在后续的event中直接使用。
{
"check_events": {
"$check_type": {
// true为后台运行,false为同步运行,不填默认为false
"run_in_background": false,
"event_class": "$sub_events目录下某个event的类名",
// 不填默认对所有分支生效
"branches": [
"$该子事件生效的代码分支"
],
// 是否可被force事件强制通过,对应的force事件为"force $check_type",例如check_type为tdd,那对应的force事件就是"force tdd"
"can_force": true
},
}
}
打开code_spectra/manifest.json,进行个性化配置(选择开启的各种子事件和评论事件)
当前主要包含两类hook:merge_request_hooks(pr的创建,更新),note_hooks(pr的评论)
如果hook_name是note_hooks,action是comment,层级如下:
{
"note_hooks": {
"comment": {
"$评论关键字": {
// 是否对外暴露本关键字,false则不会在list commands命令中返回
"internal": true,
"event_name_zh": "$事件中文名",
"event_name_en": "$事件英文名",
// hook触发的检查类事件
"check_events": {},
// hook触发的行动类事件,需check_events全检查通过才会执行
"action_events": [],
// hook触发的行动类事件,无需check_events检查通过也会执行
"non_check_action_events": [],
// hook处理完是否需要发生评论给PR
"send_comment": true
}
}
}
}
如果hook_name不是note_hooks,层级如下:
{
"$hook_name": {
"$hook的action": {
"event_name_zh": "$事件中文名",
"event_name_en": "$事件英文名",
// hook触发的检查类事件
"check_events": {},
// hook触发的行动类事件,需check_events全检查通过才会执行
"action_events": [],
// hook触发的行动类事件,无需check_events检查通过也会执行
"non_check_action_events": [],
// hook处理完是否需要发生评论给PR
"send_comment": true
}
}
}
check_events内的事件配置字段如下:
{
// check_events是一个map,key为前面提前定义好的check_events的check_type,value表示是否启用
"$check_type": true
}
action_events/non_check_action_events内的事件配置字段如下:
[
{
// true为启用,false为禁用,不填默认为true
"enable": true,
// true为后台运行,false为同步运行,不填默认为false
"run_in_background": false,
"event_class": "$sub_events目录下某个event的类名",
// 不填默认对所有分支生效
"branches": [
"$该子事件生效的代码分支"
]
}
]
运行
sudo ./start.sh
📜 开发新的子事件
每个event必须重写以下字段:
- event_name_zh:事件中文名
- event_name_en:事件英文名
必须重写以下函数:
- def execute:具体执行事件逻辑,若执行完需要评论回复则返回True,否则返回False,需要在逻辑内对failed进行赋值,表示执行成功或者失败
可选重写以下函数:
- def pre_execute:校验事件是否应该执行,不重写默认为True
- def get_check_type:检查类型,如果该event会被用作check_event,必须返回check_type。 须保证check_type填写为对应check和force关键字后的值。例如check和force的关键字为check tdd和force tdd,则check_type填写tdd。
check事件和force事件的关联关系
- check事件可由评论"check xxx"触发,force事件可由评论"force xxx"触发,二者的xxx必须保持一致。
- force xxx可以强制通过该PR的xxx检查,后续再触发check xxx都会pass。
📧 联系方式
项目维护者:
🙏 致谢
Flask开发团队
MySQL社区
所有贡献者