[code-review] Probot应用核心 | 审查协调器 - 教程

第2章:Probot应用核心(审查协调器)

欢迎回来

第1章:GitHub Actions运行器(工作流集成)中,我们学习了ChatGPT-CodeReview机器人如何在拉取请求打开或更新时被GitHub激活。这就像打开了机器人的电源开关。

现在,是时候深入了解机器人启动后发生了什么。它如何知道该做什么?如何管理整个审查过程

这正是Probot应用核心的功能——它是中央大脑,是"审查协调器",负责做出所有决策并协调任务

它解决了什么问题?

想象我们有一个管理团队的项目经理

当新任务到来时,这个经理不只是传递任务;他们会分解任务,将部分分配给不同的团队成员,跟踪进度,并确保一切顺利交付最终结果。

Probot应用核心为我们的代码审查机器人扮演了完全相同的角色。它解决的问题是协调和决策。当GitHub告诉机器人"嘿,刚刚发生了拉取请求!"时,Probot应用核心立即行动:

  • 判断发生了什么类型的事件(例如新PR或现有PR被更新)。
  • 获取有关代码变更的所有必要细节
  • 决定哪些文件需要审查,哪些应该忽略
  • 将相关代码片段发送给AI
  • 最后,将AI的反馈整理并发布回拉取请求

没有这个"协调器",我们的机器人将只是一个坐在那里的程序,对接收到的GitHub事件不知所措

认识Probot:我们的GitHub应用工具包

机器人大脑的核心是一个名为Probot的特殊工具包

Probot是一个框架,可以非常轻松地构建与GitHub交互的应用

可以将其视为GitHub应用的专用操作系统

  • 它处理所有复杂的事情,如接收来自GitHub的事件身份验证和进行API调用,因此我们可以专注于机器人的独特逻辑。

1. 监听事件(机器人的耳朵)

在这里插入图片描述

Probot应用核心最基本的工作是监听来自GitHub的特定事件

就像我们可能监听电话铃声一样,机器人监听GitHub事件,如pull_request.opened(创建了新PR)或pull_request.synchronize(向现有PR推送了新变更)。

以下是机器人"告诉"Probot它关心哪些事件的方式

// 文件: src/bot.ts (简化)
import { Probot
} from 'probot';
// Probot工具包
// ... 其他导入 ...
export const robot = (app: Probot) =>
{
// 这告诉Probot在特定PR事件发生时运行我们的代码
app.on(
['pull_request.opened', 'pull_request.synchronize'],
async (context) =>
{
// ... 我们机器人的主要审查逻辑将放在这里 ...
}
);
};

在这个片段中,app.on()是关键。就像设置通知规则。我们告诉Probot:“当pull_request.opened事件或pull_request.synchronize事件发生时,运行这个async (context) => { ... }函数中的代码。”

2. context对象(事件的细节)

当事件触发我们的机器人时,Probot不只是说"发生了PR!"它提供了一个丰富的信息包,称为context对象。这个context对象包含机器人需要了解的关于事件的所有内容,例如:

  • 事件来自哪个仓库。
  • 谁触发了事件(例如谁打开了PR)。
  • 关于拉取请求本身的所有细节(标题、正文、更改的文件等)。
  • 与GitHub交互的工具(如context.octokit)(例如获取更多数据或发布评论)。

可以将context视为随每个新任务一起到达的项目经理的说明书和工具箱。

// 在我们的app.on处理程序中(简化)
app.on(
['pull_request.opened', 'pull_request.synchronize'],
async (context) =>
{
const repo = context.repo();
// 获取仓库详情(所有者、名称)
const pull_request = context.payload.pull_request;
// 从事件中获取所有PR详情
// ... 我们使用这些细节来决定下一步做什么 ...
}
);

在这里,context.repo()快速提供有关仓库的信息,context.payload.pull_request提供触发事件的拉取请求的许多直接细节。

审查协调流程

现在机器人已经接收到事件并拥有所有context细节,审查代码的分步计划是什么?

以下是协调的简化视图:

在这里插入图片描述

深入代码(计划在行动中)

在这里插入图片描述

让我们看看包含Probot应用核心核心逻辑的src/bot.ts文件。我们将把app.on处理程序分解为其主要步骤。

  1. 初始化AI通信器
    协调器首先需要一种与AI对话的方式。

    // 文件: src/bot.ts (摘录)
    export const robot = (app: Probot) =>
    {
    const loadChat = async (context: Context) =>
    {
    // 这个函数设置我们与AI对话的方式,
    // 使用GitHub的模型或像OpenAI这样的外部服务。
    // 我们将在第4章更详细地探讨这一点!
    // ... (为简洁省略细节) ...
    return new Chat(process.env.OPENAI_API_KEY || process.env.GITHUB_TOKEN);
    };
    app.on(
    ['pull_request.opened', 'pull_request.synchronize'],
    async (context) =>
    {
    const chat = await loadChat(context);
    // 获取我们的AI通信器
    if (!chat) {
    // 如果我们无法与AI对话,就无法审查。
    log.info('Chat初始化失败');
    return 'no chat';
    }
    // ... 审查逻辑的其余部分 ...
    }
    );
    };

    loadChat函数负责建立与AI的连接。它可能使用来自GitHub secrets的API密钥或GitHub自己的AI模型。我们将在第4章:AI聊天接口(语言模型通信器)中详细了解其工作原理。

  2. 获取代码变更
    现在我们有了AI通信器,协调器向GitHub请求拉取请求中的实际代码差异(“补丁”)。

    // 文件: src/bot.ts (摘录)
    // ... 在app.on处理程序中 ...
    const data = await context.octokit.repos.compareCommits({
    owner: repo.owner,
    repo: repo.repo,
    base: context.payload.pull_request.base.sha, // 起始点提交
    head: context.payload.pull_request.head.sha, // PR中的最新提交
    });
    let { files: changedFiles, commits
    } = data.data;
    // ... (获取仅最新变更的'synchronize'事件逻辑) ...

    context.octokit是Probot提供的一个强大工具,允许我们的机器人与GitHub API交互。在这里,context.octokit.repos.compareCommits要求GitHub比较两个提交,并给我们一个changedFiles列表和中间的commits

  3. 过滤文件
    并非拉取请求中的每个文件都需要审查。例如,我们可能希望忽略配置文件或图像变更。协调器应用过滤规则。

    // 文件: src/bot.ts (摘录)
    // ... 在app.on处理程序中 ...
    const ignoreList = (process.env.IGNORE || '').split('\n').filter(Boolean);
    const ignorePatterns = (process.env.IGNORE_PATTERNS || '').split(',').filter(Boolean);
    const includePatterns = (process.env.INCLUDE_PATTERNS || '').split(',').filter(Boolean);
    changedFiles = changedFiles?.filter((file) =>
    {
    // 这是过滤逻辑发生的地方。
    // 它根据模式检查文件是否应包含或忽略。
    // 我们将在第5章深入探讨这一点!
    return !ignoreList.includes(file.filename) &&
    /* 其他模式检查 */;
    });
    if (!changedFiles?.length) {
    log.info('过滤后未发现变更');
    return 'no change';
    }

    在这里,机器人从环境变量加载过滤设置(如IGNORE_PATTERNS),并使用它们缩小changedFiles的范围。我们将在第5章:文件过滤逻辑(范围管理器)中详细探讨这一点。

  4. 发送给AI审查
    有了过滤后的文件,协调器遍历它们,提取patch(每个文件的实际代码变更),并将其发送给AI以获取反馈。

    // 文件: src/bot.ts (摘录)
    // ... 在app.on处理程序中 ...
    const reviewComments = [];
    // 存储AI的建议
    for (let i = 0; i < changedFiles.length; i++) {
    const file = changedFiles[i];
    const patch = file.patch || '';
    // 实际代码变更
    if (!patch || patch.length >
    MAX_PATCH_COUNT) {
    // 跳过差异过大的文件
    continue;
    }
    try {
    const res = await chat?.codeReview(patch);
    // AI审查代码补丁!
    if (!res.lgtm &&
    !!res.review_comment) {
    reviewComments.push({
    path: file.filename,
    body: res.review_comment,
    position: patch.split('\n').length - 1, // 放置评论的位置
    });
    }
    } catch (e) {
    log.info(`审查 ${file.filename
    } 失败`, e);
    }
    }

    对于每个相关文件,chat?.codeReview(patch)是AI介入的时刻。它接收代码变更并返回其建议,这些建议随后被收集到reviewComments中。

  5. 发布审查评论
    最后,协调器收集所有AI的建议,并再次使用context.octokit将它们作为评论发布到拉取请求上。

    // 文件: src/bot.ts (摘录)
    // ... 在app.on处理程序中 ...
    try {
    await context.octokit.pulls.createReview({
    repo: repo.repo,
    owner: repo.owner,
    pull_number: context.pullRequest().pull_number,
    body: reviewComments.length ? "ChatGPT代码审查" : "LGTM ", // 总体摘要
    event: 'COMMENT', // 表示我们正在添加评论
    comments: reviewComments, // AI的所有具体评论
    commit_id: commits[commits.length - 1].sha, // 附加到最新提交
    });
    } catch (e) {
    log.info(`创建审查失败`, e);
    }
    log.info('成功审查', context.payload.pull_request.html_url);

这个context.octokit.pulls.createReview命令是机器人"回话"GitHub的方式,将AI的见解放在开发者可以看到的地方。

总结

Probot应用核心(审查协调器)是ChatGPT-CodeReview机器人的智能中心

它使用Probot框架监听GitHub事件,处理context信息,然后协调一系列操作:初始化AI通信器、获取代码变更、应用过滤规则、将代码发送给AI审查,最后将AI的反馈直接发布到拉取请求上。

它是一个项目经理,确保我们的自动化代码审查从头到尾顺利进行。

接下来,我们将了解这个协调器在现实世界中的位置和运行方式。深入第3章:部署配置(托管策略),了解如何将机器人提供给GitHub。

posted @ 2025-09-17 19:18  yfceshi  阅读(13)  评论(0)    收藏  举报