背景:什么是 CNB NPC?

先解释几个名词。

CNB(Cloud Native Build,腾讯云原生构建平台)是一个类似 GitHub 的代码托管平台,但它有一个很酷的功能:你可以在仓库里放一个 NPC

NPC 这个词来自游戏——Non-Player Character,非玩家角色。在 CNB 里,NPC 就是你仓库中的一个 AI 助手。你在 Issue 或 PR(Pull Request,合并请求)里 @它,它就会自动读取你的代码、跑测试、分析结果,然后回复你。

我的项目叫 lighthouse_audit,目标是让 NPC 自动对网站做 Lighthouse 审计(Google 的网页性能检测工具),然后把报告上传到 Issue 里。

听起来很酷对吧?实际做下来,我踩了一路坑。


坑一:NPC 镜像和插件镜像搞混了

镜像混淆经过

我的仓库里有两个 Dockerfile:

  • 根目录的 Dockerfile:NPC 运行时镜像(有 CNB CLI、skills 框架等)
  • plugin/Dockerfile:Lighthouse 插件镜像(只有 Chromium + Lighthouse)

我一开始搞混了,把 plugin/Dockerfile 构建推送上去当 NPC 镜像用。

坑一修复

PR #18 拆分了两个镜像的职责:

  • 根目录 Dockerfile:只管 NPC 运行时(接收评论、调用 skills、回复结果)
  • plugin/Dockerfile:只管 Lighthouse 测试(装 Chromium、跑审计、输出报告)

💡 教训:一个镜像只干一件事。NPC 镜像 ≠ 测试工具镜像。


坑二:AI “固执己见”,重复安装 Lighthouse

这是最贵的一个坑。

AI 重复安装经过

我的设计是分两步走:

  1. Stage 0(构建阶段):在容器里跑 Lighthouse,生成报告
  2. NPC 分析阶段:AI 读取已有的报告,分析后回复 Issue

但 AI 不知道报告已经生成好了。它收到”请分析性能”的指令后,自己又 npm install -g lighthouse 装了一遍,然后重新跑测试。

数据触目惊心

构建记录 AI 行为 耗时
cnb-j6o-… 安装 1 次 142 秒
cnb-moo-… 安装 1 次 324 秒
cnb-8pg-… 安装 lighthouse + puppeteer + chromium 304 秒
cnb-6ro-… 反复安装 5 次 ⚠️ 763 秒(12.7 分钟)
cnb-3jo-… puppeteer + lighthouse + apt chromium 237 秒

6 次构建里有重复安装,最离谱的一次装了 12 分钟

根因

NPC 的 prompt(提示词)没有明确告诉 AI:”报告已经在 lighthouse-report/ 目录里了,你只需要读取分析,不要重新运行测试。”

坑二修复

修改 NPC prompt,写死产物路径:

你只需要读取 lighthouse-report/ 目录下的报告文件,进行分析后回复。
严禁重新安装或运行 Lighthouse 测试——这一步已经在构建阶段完成了。

💡 教训:Prompt 是 NPC 的灵魂。你不说清楚,AI 就会”自由发挥”——而自由发挥是要烧钱的。


坑三:文件上传,10 次提交的血泪史

看 git log,main 分支上只有 10 个 commit,全部在同一天(06-02),全部围绕同一个功能:把 Lighthouse 报告上传到 Issue。

2026-06-02  2f9dbda3  fix: 更新上传逻辑以支持 Issue 和 PR 事件的文件上传
2026-06-02  2d4fe22b  feat: 重构上传测试报告逻辑,新增脚本处理文件上传
2026-06-02  0d828b33  refactor: 简化文件上传,移除冗余代码
2026-06-02  25de4b7a  fix: 修正上传测试报告脚本路径        ← 路径错了
2026-06-02  e5185292  chore: 优化上传测试报告脚本路径逻辑   ← 还是错
2026-06-02  1cee5b3e  feat: 新增上传报告脚本并优化上传逻辑  ← 换方案
2026-06-02  68ccba8a  feat: 更新上传脚本为 upload-report.sh
2026-06-02  9189ef95  feat: 替换为动态下载 upload-report.sh
2026-06-02  a818d8ac  feat: 移除脚本内联,添加 Dockerfile
2026-06-02  52879c2f  fix: 修正镜像路径为正确的仓库名称    ← 又错了

脚本放置方案变了 3 次

  1. 内联在构建脚本里 → 太长,不好维护
  2. 外部脚本文件 → 容器里找不到路径
  3. 运行时动态下载 → URL 也不对
  4. 放进 Dockerfile → 最终方案

路径错误 × 3

容器内的路径和仓库路径是不一样的。你在本地看是 ./scripts/upload.sh,在容器里可能变成 /workspace/.cnb/scripts/upload.sh。这个坑我踩了 3 次

还有一堆 [skip ci]

7 个 commit 加了 [skip ci]——因为我意识到每次 push 都会触发构建,光调路径就烧了好几次构建额度。

💡 教训:文件上传看似简单,但在 CI/CD 容器环境里,路径、权限、脚本位置每个都是坑。先在本地验证,再推到 CI。


坑四:Token 权限不够,白跑一趟

NPC 尝试读取构建日志来定位问题,结果返回:

当前 Token 缺少 repo-cnb-trigger:r 权限,无法通过 API 获取构建日志

NPC 瞎猜了一通,分析结果全错。

坑四修复

提前配齐 Token 权限:

  • repo-cnb-trigger:r:读取构建触发信息
  • repo-cnb-history:r:读取构建历史和日志

💡 教训:权限配置是基础设施,不是”到时候再说”的事。


坑五:Credits 爆炸 💸

来算一笔账:

事项 消耗
#21 第 1 次分析(读构建日志) 76.4 credits(¥3.8)
#21 第 2 次分析(读完整日志) 188.5 credits(¥9.4
#19 上传测试 × 13 次触发 26.6+ credits
#20 E2E 测试 34.4 credits

仅”AI 固执己见”这一个坑,两次分析就烧了 ¥13。原因是 CodeBuddy 读取了 120 万+ tokens 的构建日志。

省钱心得

  1. Prompt 写清楚:别让 AI 自己猜,猜就是烧钱
  2. [skip ci]:调试阶段的 commit 别触发构建
  3. 控制触发频率:别像我一样 Issue 里触发 13 次
  4. 精简日志输出:AI 读的日志越短,花的 tokens 越少

最终方案:PR #22 NPC 驱动重构

踩完所有坑后,我开了 PR #22 做了一次系统性重构:

  1. 镜像分离:NPC 镜像只管调度,Lighthouse 镜像只管测试
  2. Prompt 重写:明确告诉 AI 产物在哪、不要重复操作
  3. 上传逻辑封装:统一用 upload-report.sh,路径写死
  4. 权限预配置:Token 权限一次性配齐

时间线总览

05-27~29  基础搭建
  ├─ 镜像混淆 → Issue #17 对比 dockerfile 才发现
  ├─ 流水线重复执行 → Issue #14
  └─ AI 重复安装 Lighthouse → Issue #21(最贵的坑)

06-01    权限调整
  └─ Token 权限不足 → NPC 瞎分析

06-02    文件上传攻坚
  └─ 10 个 commit,路径错 × 3,方案改 × 3

06-04    系统重构
  └─ PR #22:把所有教训整合成新架构

06-05    开源上架
  └─ FunASR 插件注册到 CNB 插件市场 opensource 目录(PR #740)
  └─ 最终选择不带 mark 字段,留空即可

给后来者的建议

  1. 一个镜像干一件事:别把工具和运行时塞一起
  2. Prompt 是核心:NPC 的行为 90% 取决于你怎么写 prompt
  3. 路径!路径!路径!:容器内路径 ≠ 本地路径,提前验证
  4. 权限先配好:别等报错才发现 Token 权限不够
  5. [skip ci] 是你的好朋友:调试阶段别浪费构建额度
  6. 先本地验证,再推 CI:别在 CI 上调脚本路径

这个项目仓库在 xzzlwl/lighthouse_audit,欢迎围观。