[code-review] 文件过滤逻辑 | 范围管理器

第5章:文件过滤逻辑(范围管理器)

欢迎回来

第4章:AI聊天接口(语言模型通信器)中,我们探索了机器人如何与ChatGPT等强大的AI模型智能通信

它知道如何提出正确的问题并理解答案(by json)。

但想象一下,我们正在审查一个庞大的编码项目

一个拉取请求可能涉及数百个文件,从核心应用程序逻辑到临时构建文件、图像资源,甚至是来自外部库(如node_modules)的文件。

我们真的想把所有这些都发送给AI审查吗?可能不需要

这就是文件过滤逻辑(范围管理器)发挥作用的地方

负责智能决定拉取请求中哪些 文件应该实际发送给AI审查的组件。它就像一个高效的独家俱乐部保镖,确保只有相关且可管理的代码变更能够进入AI审查环节。

它解决了什么问题?

ChatGPT-CodeReview机器人在决定审查哪些文件时面临两个主要挑战:

  1. AI成本和性能:向AI发送过多代码会增加成本并延长处理时间。AI模型还有"令牌限制",意味着它们一次只能处理一定量的文本。发送不相关或非常大的文件可能会触及这些限制,导致审查失败或不完整。
  2. 相关性 :并非所有文件对代码审查都同等重要。我们可能不需要AI对以下内容的反馈:
    • 配置文件(如.envpackage-lock.json)。
    • 生成的代码(如dist文件夹中的编译JavaScript)。
    • 大型第三方库(node_modules)。
    • 文档或图像文件。

范围管理器 通过提供清晰的规则来解决这些问题,规定包含什么、忽略什么以及哪些内容对AI来说太大而无法高效处理 。它确保AI将其宝贵的注意力(和我们的预算)集中在真正重要的代码上。

范围管理器的规则(保镖的检查清单)

我们机器人的保镖(范围管理器)有几个关键规则来决定哪些文件可以进入:

(类似于bot的.ignore)

  1. 直接忽略列表(IGNORE :"这些特定文件永远不允许进入。"
  2. 忽略模式(IGNORE_PATTERNS :"任何匹配这些常见模式的文件不允许进入。"
  3. 包含模式(INCLUDE_PATTERNS :"只有匹配这些模式的文件允许进入。其他所有文件都排除在外!"(此规则优先级最高)。
  4. 最大变更大小(MAX_PATCH_LENGTH:"即使文件被允许,如果其变更太大,AI无法一次性处理,则跳过它。"

让我们看看如何在.github/workflows/cr.yml文件中配置这些规则。

配置范围管理器(设置保镖的规则)

我们使用GitHub Actions工作流中的环境变量来配置范围管理器,就像在第1章:GitHub Actions运行器(工作流集成)中看到的那样

以下是设置这些规则的示例

yaml 复制代码
# 文件: .github/workflows/cr.yml (片段)
      - uses: anc95/ChatGPT-CodeReview@main
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          # ... 其他设置 ...

          # 规则1: 要忽略的特定文件
          IGNORE: |
            package-lock.json
            yarn.lock
            .env

          # 规则2: 要忽略的文件模式(逗号分隔)
          IGNORE_PATTERNS: "*.md, .github/**, public/*, dist/**, *.test.js"

          # 规则3: *仅*包含匹配这些模式的文件(逗号分隔)
          # 如果设置,IGNORE和IGNORE_PATTERNS将被忽略!
          INCLUDE_PATTERNS: "src/**/*.js, src/**/*.ts, scripts/**"

          # 规则4: 每个文件的变更最大大小(字符数)
          MAX_PATCH_LENGTH: 1000 # 示例:仅审查最多1000个字符的变更

让我们分解每条规则:

1. IGNORE:要排除的特定文件

此变量是一个以换行符分隔的精确文件名列表。如果文件的名称匹配此列表中的任何条目,它将被立即过滤掉。

示例

yaml 复制代码
          IGNORE: |
            package-lock.json
            yarn.lock
            .env

结果 :如果拉取请求更改了package-lock.jsonyarn.lock.env,机器人将直接忽略这些变更,不会将它们发送给AI。

2. IGNORE_PATTERNS:要排除的文件模式

此变量是一个以逗号分隔的"glob模式"列表。Glob模式类似于通配符(*匹配任何内容,**匹配任何目录)。任何匹配任何这些模式的文件将被排除。

示例

yaml 复制代码
          IGNORE_PATTERNS: "*.md, .github/**, public/*, dist/**, *.test.js"

结果

  • *.md:忽略所有Markdown文件(例如README.mdCONTRIBUTING.md)。
  • .github/**:忽略.github目录中的任何内容(例如工作流文件、问题模板)。
  • public/*:忽略public文件夹中的直接文件(例如public/index.html)。
  • dist/**:忽略dist目录或其子目录中的任何内容(常见于编译代码)。
  • *.test.js:忽略JavaScript测试文件。

3. INCLUDE_PATTERNS包含匹配这些模式的文件

这是最强大的过滤规则。如果设置了INCLUDE_PATTERNS,机器人将 考虑匹配至少一个 这些模式的文件。所有其他文件,无论IGNOREIGNORE_PATTERNS如何,都将被排除。这相当于一个"允许列表"。

示例

yaml 复制代码
          INCLUDE_PATTERNS: "src/**/*.js, src/**/*.ts, scripts/**"

结果

  • src/**/*.js:仅包含src文件夹中的任何位置的JavaScript文件。
  • src/**/*.ts:仅包含src文件夹中的任何位置的TypeScript文件。
  • scripts/**:仅包含scripts文件夹中的任何位置的文件。
  • 重要 :如果还有README.mdpublic/index.html的变更,它们将被忽略 ,因为它们不匹配任何INCLUDE_PATTERNS

4. MAX_PATCH_LENGTH:限制变更大小

即使文件通过了IGNOREINCLUDE_PATTERNS规则的检查,其变更的总大小("补丁"或"差异")可能对AI来说太大而无法有效处理。此变量设置单个文件补丁的字符限制。

示例

yaml 复制代码
          MAX_PATCH_LENGTH: 1000 # 仅审查最多1000个字符的变更

结果 :如果文件src/big-feature.js有2000个字符的变更,而MAX_PATCH_LENGTH为1000,机器人将跳过审查此文件,即使它匹配INCLUDE_PATTERNS。这可以避免触及AI令牌限制并节省成本。

幕后:范围管理器的工作原理

让我们追踪ChatGPT-CodeReview机器人如何应用这些规则。这发生在Probot应用核心(审查协调器)从GitHub获取变更文件列表之后。

解析:保镖的决策过程

  1. 获取所有变更 :机器人首先向GitHub请求拉取请求中所有更改的文件。
  2. 加载规则 :然后从环境变量中读取IGNOREIGNORE_PATTERNSINCLUDE_PATTERNS
  3. 优先检查INCLUDE_PATTERNS :如果设置了INCLUDE_PATTERNS,保镖会立即过滤列表,仅保留匹配至少一个这些模式的文件。任何不匹配的文件将被丢弃。
  4. 检查IGNORE列表 :对于剩余的文件,保镖检查文件的精确名称是否在IGNORE列表中。如果是,文件将被丢弃。
  5. 检查IGNORE_PATTERNS :对于仍然剩余的文件,保镖检查文件是否匹配任何IGNORE_PATTERNS。如果匹配,文件将被丢弃。
  6. 最终列表:通过所有这些检查的文件被视为"相关"。
  7. 大小检查 :在将每个"相关"文件发送给AI之前,机器人提取其特定变更(patch)。如果patch长度超过MAX_PATCH_LENGTH,则跳过该文件的审查,但其他文件仍可能被审查。

序列图

代码

核心过滤逻辑位于src/bot.ts中的app.on处理程序内。

  1. 加载配置

    首先,机器人从环境变量加载过滤偏好。

    typescript 复制代码
    // 文件: src/bot.ts (摘录)
    // ... 在app.on处理程序中 ...
    
    const ignoreList = (process.env.IGNORE || process.env.ignore || '')
        .split('\n')
        .filter((v) => v !== ''); // 按换行符分割,移除空条目
    const ignorePatterns = (process.env.IGNORE_PATTERNS || '').split(',').filter((v) => Boolean(v.trim())); // 按逗号分割
    const includePatterns = (process.env.INCLUDE_PATTERNS || '').split(',').filter((v) => Boolean(v.trim())); // 按逗号分割
    
    log.debug('ignoreList:', ignoreList);
    log.debug('ignorePatterns:', ignorePatterns);
    log.debug('includePatterns:', includePatterns);
    
    // ... 其余代码 ...

    此片段将IGNOREIGNORE_PATTERNSINCLUDE_PATTERNS字符串转换为干净的数组,便于检查。

  2. changedFiles应用过滤器

    接下来,机器人遍历每个变更文件,并使用filter方法应用规则。

    typescript 复制代码
    // 文件: src/bot.ts (摘录)
    // ... 加载配置后 ...
    
    changedFiles = changedFiles?.filter(
        (file) => 
        {
          const filePath = file.filename; // 被检查文件的路径
    
          // 规则3: INCLUDE_PATTERNS(优先级最高)
          if (includePatterns.length) {
            return matchPatterns(includePatterns, filePath); // 仅包含匹配的文件
          }
    
          // 规则1: IGNORE列表(次优先级)
          if (ignoreList.includes(filePath)) {
            return false; // 如果在忽略列表中,排除
          }
    
          // 规则2: IGNORE_PATTERNS(排除的最后优先级)
          if (ignorePatterns.length) {
            return !matchPatterns(ignorePatterns, filePath); // 如果匹配忽略模式,排除
          }
    
          return true; // 如果没有规则适用,默认包含文件
      });
    
    if (!changedFiles?.length) {
      log.info('过滤后未发现变更');
      return 'no change';
    }
    // ... 其余代码 ...

    filter函数逐个处理每个文件。注意includePatterns首先被检查。如果使用了它,其他忽略规则对该文件将被跳过。

  3. matchPatterns辅助函数
    matchPatterns函数是一个辅助函数,使用minimatch库检查文件路径是否匹配任何glob模式。它还支持回退到正则表达式。

    typescript 复制代码
    // 文件: src/bot.ts (摘录 - 文件底部)
    const matchPatterns = (patterns: string[], path: string) => 
    {
      return patterns.some((pattern) => { // 检查是否有任何模式匹配
        try 
        {
          // 使用minimatch处理glob模式(例如"*.js"、"src/**")
          return minimatch(path, pattern.startsWith('/') ? "**" + pattern : pattern.startsWith("**") ? pattern : "**/" + pattern);
        } 
          catch 
        {
          // 如果不是glob,尝试作为正则表达式匹配
          try 
          {
            return new RegExp(pattern).test(path);
          } 
            catch (e) 
          {
            return false; // 无效模式
          }
        }
      })
    }

    此函数使模式匹配功能强大且灵活。patterns.some()意味着如果列表中至少一个 模式匹配path,则返回true

  4. MAX_PATCH_LENGTH检查

    在初始过滤后,机器人遍历剩余 文件。对于每个文件,在将其patch发送给AI之前,检查MAX_PATCH_LENGTH

    typescript 复制代码
    // 文件: src/bot.ts (摘录)
    // ... 在发送文件给AI的循环中 ...
    const MAX_PATCH_COUNT = process.env.MAX_PATCH_LENGTH
      ? +process.env.MAX_PATCH_LENGTH
      : Infinity; // 默认为无限制
    
    for (let i = 0; i < changedFiles.length; i++) {
        const file = changedFiles[i];
        const patch = file.patch || ''; // 获取实际代码变更
    
        if (!patch || patch.length > MAX_PATCH_COUNT) {
          log.info(
            `${file.filename} 因差异过大而被跳过`
          );
          continue; // 跳过此文件,继续下一个
        }
        // ... 调用chat?.codeReview(patch)在此处发生 ...
    }

    此检查确保即使大文件通过了名称/模式过滤,其单个变更也不会压倒AI或消耗过多令牌。

总结

**文件过滤逻辑(范围管理器)**是ChatGPT-CodeReview的关键组件。

它作为一个智能保镖,使用用户定义的规则(IGNOREIGNORE_PATTERNSINCLUDE_PATTERNS)从拉取请求中选择最相关的文件。

强制执行MAX_PATCH_LENGTH,确保发送给AI的单个代码变更可控,避免昂贵的审查和触及AI令牌限制

通过有效管理审查范围,机器人提供了更集中、高效且经济高效的反馈。

现在我们了解了机器人如何决定审查什么,让我们学习如何窥探幕后,看看机器人在做什么。在下一章中,我们将探索第6章:日志机制(调试)

相关推荐
mwq3012312 小时前
Transformer : 深度神经网络中的残差连接 (Residual Connection)
人工智能
信田君952712 小时前
瑞莎星瑞(Radxa Orion O6) 基于 Android OS 使用 NPU的图片模糊查找APP 开发
android·人工智能·深度学习·神经网络
StarPrayers.12 小时前
卷积神经网络(CNN)入门实践及Sequential 容器封装
人工智能·pytorch·神经网络·cnn
周末程序猿12 小时前
谈谈上下文工程(Context Engineering)
人工智能
一水鉴天13 小时前
整体设计 逻辑系统程序 之29 拼语言+ CNN 框架核心定位、三阶段程序与三种交换模式配套的方案讨论 之2
人工智能·神经网络·cnn
海森大数据13 小时前
AI破解数学界遗忘谜题:GPT-5重新发现尘封二十年的埃尔德什问题解法
人工智能·gpt
望获linux13 小时前
【实时Linux实战系列】Linux 内核的实时组调度(Real-Time Group Scheduling)
java·linux·服务器·前端·数据库·人工智能·深度学习
Dev7z14 小时前
河南特色农产品识别系统:让AI守护“中原味道”
人工智能
万俟淋曦14 小时前
【论文速递】2025年第28周(Jul-06-12)(Robotics/Embodied AI/LLM)
人工智能·ai·机器人·大模型·论文·robotics·具身智能