思路分享
-
通过token获取最新的pr
-
使用脚本获取变动,缓存修改文件
-
使用skills 读取缓存文件进行pr
使用skills示例
- "用 fetch-todos 做一次 codeview"
- "帮我 codeview 一下当前的 PR"
- "按 gitlab-pr-codeview 流程审查一下"
效果展示

一、获取token

二、写获取变动的代码, 设置token
目录结构
ini
.env
GITLAB_TOKEN = 复制的token
fetch-todos.js
下面是代码和skills
获取变动的脚本代码 fetch-todos.js
javascript
/**
* Node 脚本:请求 GitLab 待办事项 + 所有关联 MR 的变动,并写入临时文件
* 使用方式:node fetch-todos.js
* 会从同目录 .env 读取 GITLAB_TOKEN(可选),或使用环境变量
*/
const fs = require('fs');
const path = require('path');
const os = require('os');
// 从 .env 加载(简单解析,不引入 dotenv)
try {
const envPath = path.join(__dirname, '.env');
if (fs.existsSync(envPath)) {
const content = fs.readFileSync(envPath, 'utf8');
for (const line of content.split('\n')) {
const m = line.match(/^\s*([^#=]+)=(.*)$/);
if (m) {
const key = m[1].trim();
const val = m[2].trim().replace(/^["']|["']$/g, '');
if (!process.env[key]) process.env[key] = val;
}
}
}
} catch (_) {}
const GITLAB_BASE = process.env.GITLAB_BASE || 'https://gitlab.kuaizitech.cn';
const GITLAB_TOKEN = process.env.GITLAB_TOKEN;
if (!GITLAB_TOKEN) {
console.error('请设置环境变量 GITLAB_TOKEN 或在 .env 中配置');
process.exit(1);
}
const headers = {
'PRIVATE-TOKEN': GITLAB_TOKEN,
'Content-Type': 'application/json',
};
async function fetchTodos() {
const url = `${GITLAB_BASE}/api/v4/todos`;
const res = await fetch(url, { headers });
if (!res.ok) {
console.error('请求 todos 失败:', res.status, res.statusText);
console.error(await res.text());
process.exit(1);
}
return res.json();
}
async function fetchMrChanges(projectId, mergeRequestIid) {
const url = `${GITLAB_BASE}/api/v4/projects/${encodeURIComponent(projectId)}/merge_requests/${mergeRequestIid}/changes`;
const res = await fetch(url, { headers });
if (!res.ok) return null;
return res.json();
}
function deletePreviousTempFiles() {
const tempDir = os.tmpdir();
try {
const files = fs.readdirSync(tempDir);
for (const name of files) {
if (name.startsWith('gitlab-todos-changes-') && name.endsWith('.json')) {
fs.unlinkSync(path.join(tempDir, name));
}
}
} catch (_) {}
}
async function main() {
deletePreviousTempFiles();
const todos = await fetchTodos();
const output = {
fetchedAt: new Date().toISOString(),
todosCount: todos.length,
todos: [],
allChanges: [],
};
for (const todo of todos) {
const target = todo.target || {};
const targetType = todo.target_type || target.target_type;
const line = {
id: todo.id,
action: todo.action?.name,
body: todo.body,
target_type: targetType,
target_url: todo.target_url,
author: todo.author?.username,
};
if (targetType === 'MergeRequest' && target.project_id != null && target.iid != null) {
const changes = await fetchMrChanges(target.project_id, target.iid);
if (changes && changes.changes) {
line.merge_request = {
id: changes.id,
iid: changes.iid,
title: changes.title,
source_branch: changes.source_branch,
target_branch: changes.target_branch,
};
line.diffs = changes.changes.map((c) => ({
old_path: c.old_path,
new_path: c.new_path,
new_file: c.new_file,
deleted_file: c.deleted_file,
diff: c.diff,
}));
output.allChanges.push(...(line.diffs || []));
}
}
output.todos.push(line);
}
const tempDir = os.tmpdir();
const tempName = `gitlab-todos-changes-${Date.now()}.json`;
const tempPath = path.join(tempDir, tempName);
fs.writeFileSync(tempPath, JSON.stringify(output, null, 2), 'utf8');
console.log('临时文件已生成:', tempPath);
console.log('待办数量:', output.todosCount, '| 变动条目:', output.allChanges.length);
return tempPath;
}
main().catch((err) => {
console.error(err);
process.exit(1);
});
运行脚本后会生成临时文件 然后使用 skills进行codeview就行了 需要替换自己的脚本路径

yaml
---
name: gitlab-pr-codeview
description: 使用 fetch-todos.js 拉取 GitLab 待办 MR 的变动,并执行 Code Review:识别敏感修改、未删除的 log、过大改动并总结。在用户要求 codeview、PR 审查、或使用 fetch-todos 做代码审查时使用。
---
# GitLab PR Code Review(基于 fetch-todos)
基于项目脚本 `fetch-todos.js` 获取 GitLab 待办 MR 的文件变动,然后对变动做系统性审查。
## 前置条件
- 已配置 `GITLAB_TOKEN`(环境变量或项目 `git-reivew` 下的 `.env`)。
- 脚本路径:`这里是脚本路径,如果出现这个提示需要设置脚本路径`,需在**该目录下**执行以便读取 `.env`。
## 流程概览
1. **拉取 MR 变动**:运行 `fetch-todos.js`,得到包含所有待办 MR 及 diff 的临时 JSON。
2. **读取变动**:从临时文件中读取 `todos`、`allChanges` 及每个 todo 的 `diffs`。
3. **逐项审查**:对每个 MR 的每条 diff 做敏感项、log、规模、总结等检查。
4. **输出报告**:按下方模板给出每个 MR 的结论与总体总结。
---
## Step 1:拉取数据
在脚本所在目录执行:
```bash
cd 这里是脚本路径,如果出现这个提示需要设置脚本路径 && node fetch-todos.js
```
终端会打印临时文件路径,形如:`/var/folders/.../gitlab-todos-changes-<timestamp>.json`。若需在别处复用,可记下该路径;也可在系统临时目录下查找最新生成的 `gitlab-todos-changes-*.json`。
---
## Step 2:解析并遍历变动
从临时 JSON 中读取:
- `output.todos`:每个待办(含 `merge_request`、`diffs`)。
- 每个 `diff` 含:`old_path`、`new_path`、`new_file`、`deleted_file`、`diff`(原始 diff 文本)。
对每个 MR,逐条 `diff` 进行审查。
---
## Step 3:审查清单
对**每条文件变动**检查以下项,并在报告中标注「有 / 无」及具体位置或片段。
### 3.1 敏感修改(必须逐项列出)
- **密钥与凭证**:密码、API Key、Token、私钥、`.env` 中敏感项被提交或硬编码。
- **内部/敏感信息**:内网地址、未脱敏的账号/手机/邮箱、内部系统名称等。
- **权限与开关**:不应暴露的 feature flag、调试开关、降级开关被误开或写死。
若发现任一项,在报告中**明确写出文件路径、行号或 diff 片段**,并标记为「敏感,需修复」。
### 3.2 未删除的 Log / 调试代码
- **前端/Node**:`console.log`、`console.debug`、`console.info` 等未删除或未改为可配置日志。
- **其他语言**:`print`、`debugger`、`var_dump`、`System.out.println` 等调试输出。
- **日志库**:仅用于开发调试的 `logger.debug`/`logger.trace` 等,若上线不应保留则标出。
在报告中列出:文件路径 + 行号或 diff 中的对应行,并建议删除或改为可配置级别。
### 3.3 过大改动
- **单文件**:单条 diff 行数过多(例如新增/删除合计超过 300 行),提示「建议拆分为更小 MR 或分多次提交」。
- **单次 MR**:总变更文件数或总行数异常多,提示「改动范围大,建议重点核对逻辑与回归范围」。
阈值可按团队习惯调整(如 200/500 行),在技能中保持统一即可。
### 3.4 总结
- 用 2--4 句话概括本 MR:主要改了什么、影响范围、是否有风险点。
- 汇总:敏感问题数、未删除 log 数、是否属于「大改动」及建议。
---
## Step 4:输出报告模板
对每个 MR 使用下面结构输出;若有多个 MR,先按 MR 分节,最后加「总体总结」。
```markdown
## MR: [标题] (!iid / 分支)
- **目标分支**: target_branch ← source_branch
- **变更文件数**: N
### 敏感修改
- [ ] 无
- [ ] 有:(列出文件:行或 diff 片段,并说明风险)
### 未删除的 Log / 调试代码
- [ ] 无
- [ ] 有:(文件:行或片段,建议删除或降级)
### 过大改动
- [ ] 无
- [ ] 有:(说明单文件/总变更规模,建议拆分或重点回归)
### 总结
(2--4 句:改了什么、影响、风险与建议)
---
```
**总体总结**(多个 MR 时):
- 共几个 MR、共多少处敏感问题、多少处 log 需处理、是否有大改动及建议。
---
## 执行顺序小结
1. `cd 这里是脚本路径,如果出现这个提示需要设置脚本路径 && node fetch-todos.js`
2. 读取输出的临时 JSON(控制台打印的路径或 tmp 下最新 `gitlab-todos-changes-*.json`)
3. 遍历 `todos` → 每个 MR 的 `diffs` → 按审查清单检查
4. 按模板填写「敏感修改」「未删除 log」「过大改动」「总结」
5. 多 MR 时补充「总体总结」
---
## 可选:仅审查指定 MR
若用户只关心某个 MR,可在解析后只对对应 `todo` 的 `diffs` 执行 Step 3--4,并在报告中注明「仅审查 MR: xxx」。