Deno Issue Triage 技能实战:从分类、复现到打标签的完整 Issue 分诊工作流
【免费下载链接】denoA modern runtime for JavaScript and TypeScript.项目地址: https://gitcode.com/GitHub_Trending/de/deno
Deno 仓库在.claude/skills/目录下维护了一套面向 AI Agent 的技能(Skill)文件,其中 issue-triage/SKILL.md 定义了一套标准化的 GitHub Issue 分诊流程:读取 issue、判断类型、校验信息完整性、在隔离环境中复现 bug、按规则打标签、发布结构化的分诊评论。读完本文,你将掌握这套六步工作流的每一步操作细节、ghCLI 命令用法、Docker 复现方案,以及标签体系如何与 Deno 仓库的目录结构一一对应。
技能定义:frontmatter 与工具白名单
SKILL.md是一个带 YAML frontmatter 的 Markdown 文件,其头部元数据声明了技能的名称、触发条件、参数提示和工具白名单:
name: issue-triage description: Triage a Deno GitHub issue — reproduce bugs, classify, label, and comment with findings. Use when asked to triage an issue or when an issue number/URL is provided for triage. argument-hint: <issue-number-or-url> allowed-tools: Bash(gh *) Bash(deno *) Bash(git *) Bash(mktemp *) Bash(rm *) Bash(cat *) Read Write Glob Grep Agent几个设计要点值得注意:
- 触发条件:当用户要求 triage 某个 issue,或提供了 issue 编号/URL 时,Agent 应加载该技能,把参数作为
$ARGUMENTS贯穿整个流程(正文第一行即声明Triage issue $ARGUMENTS on the denoland/deno repository)。 - 工具白名单:
allowed-tools字段把 Agent 的权限收敛到gh、deno、git、mktemp、rm、cat等最小命令集合,以及文件读写类工具。这是一种"最小权限"模式——分诊只需读 issue、跑复现代码、改标签和评论,不需要构建仓库或执行任意命令。 - 内联命令标记:正文中用
```!围栏包裹的命令(如gh issue view)表示技能被调用时应自动执行的命令,与普通说明性代码块区分开。
同一目录下还有若干姊妹技能,各自承担不同的分诊/审查场景:review-pr/SKILL.md(PR 审查)、node-compat/SKILL.md(Node 兼容性问题)、fmt/SKILL.md、lint-all/SKILL.md、lint-js/SKILL.md。issue-triage 是其中唯一面向"入站 issue"的技能,与 review-pr 面向"入站 PR"形成互补。
Step 1:读取 Issue
流程的第一步是通过ghCLI 拉取 issue 的完整元数据:
gh issue view $ARGUMENTS --repo denoland/deno --json number,title,body,author,labels,state,comments,createdAt,url这条命令以 JSON 形式返回 issue 的编号、标题、正文、作者、已有标签、状态、评论、创建时间和 URL。其中body是后续所有判断(分类、提取复现代码、检查信息完整性)的输入来源,labels用于识别 issue 是否还挂着needs triage/triage required 👀这类待分诊标记(Step 5 会移除它们)。
Step 2:五分类判断
技能把每个 issue 归入以下五类之一:
Bug report—— 行为不符合预期;
Feature request / suggestion—— 新能力或增强请求;
Question—— 使用问题,不是 bug;
Duplicate—— 已有同类报告。查找方式是用关键词搜索全部状态的 issue:
gh issue list --search "keywords" --state all--state all同时覆盖 open 和 closed,避免重复报告只与已关闭 issue 重复却被漏判的情况;Invalid—— 无法处理、不属于 Deno 的问题、或信息不足。
这里有一个重要的**快速路径(fast-path)**设计:如果 issue 明显属于 question、duplicate 或 invalid,跳过复现环节,直接跳到 Step 5 打标签。这与仓库的 CI 设计哲学一致——doc/ci.md 描述的pre-build门禁同样是先用廉价判断决定下游任务是否执行,避免为不需要构建的 PR 跑完整流水线。分诊中的"先分类再复现"就是 issue 层面的 docs-only 快速路径。
Step 3:校验信息完整性
一个合格的 bug report 必须同时包含四项信息:
- Deno 版本(
deno --version的输出); - 操作系统;
- 复现步骤或最小复现代码;
- 预期行为 vs 实际行为。
任一项缺失时,技能给出的处理是:打上needs info标签,并评论请求作者补充缺失细节。明确禁止在没有清晰复现用例时尝试复现——这与 CLAUDE.md 中"遇到构建/测试失败先看具体输出再排查"的排障风格一脉相承:先确认证据,再做推断。
版本号在 Deno 中是一等公民:构建时通过编译期环境变量DENO_VERSION、DENO_CANARY、DENO_RC注入版本信息,并缓存到denover段中供deno --version读取,见 cli/lib/version.rs 与 cli/lib/version.txt(当前仓库记录的版本号为 2.9.6)。因此 issue 中的版本号能精确定位到一次构建,是"版本对比复现"策略的前提。
Step 4:复现 Bug
只有携带清晰复现用例的 bug report 才进入这一步。
隔离环境:优先 Docker
技能要求在 Docker 容器内运行复现代码以保证隔离,仅在 Docker 不可用时退回到本地临时目录:
# Run repro with latest canary docker run --rm -v "$REPRO_DIR":/repro -w /repro denoland/deno:canary deno run repro.ts # Run repro with a specific version (e.g., 2.1.4) docker run --rm -v "$REPRO_DIR":/repro -w /repro denoland/deno:2.1.4 deno run repro.ts要点:docker run --rm保证容器用完即删;复现文件通过-v挂载进容器的/repro工作目录。本地回退方案则用mktemp -d建临时目录:
REPRO_DIR=$(mktemp -d) deno run "$REPRO_DIR/repro.ts"双版本对比策略
复现时尽量跑两个版本:
- issue 中报告的版本(若指定)——确认 bug 确实存在;
- 最新 canary——检查是否已被修复。
两个版本分别对应不同的 Docker 镜像 tag(如denoland/deno:2.1.4、denoland/deno:canary)。如果指定版本能复现而 canary 上不复现,应记录"可能已修复",并进一步检查 git log 中寻找相关修复提交。
复现执行与清理
- 从 issue 正文中提取复现代码,写入本地临时目录;
- 用 issue 中描述的
deno子命令和 flag 在容器(或本地)中运行; - 同时捕获 stdout 和 stderr,再与 issue 描述的预期行为对比;
- 如果复现涉及特定 npm 包、
deno.json配置或多文件工程,按描述完整重建该环境; - 完成后清理:
rm -rf "$REPRO_DIR"。
记录复现结论
技能要求最终记录三个问题:
- bug 在报告的版本上是否复现?
- bug 在 canary 上是否复现?
- 有无额外观察(不同的报错信息、部分修复、关联 issue 等)?
这套"报告版本 × canary"的二维结论矩阵,正是后面 Step 5/Step 6 打regression标签和撰写评论模板的直接输入。
Step 5:打标签
技能强调标签要从简——通常一个 area 标签就够,不要过度打标。标签分三层:
类型标签(最多一个)
| Label | 使用场景 |
|---|---|
bug | 已确认的 bug——凡是验证过的 bug report 必加 |
feat | 已被接受的新特性 |
suggestion | 尚未接受的功能请求 |
question | 使用问题 |
duplicate | 与另一个 issue 重复 |
invalid | 无法处理 |
panic | Deno panic / 崩溃 |
regression | 以前可用现在坏掉 |
bug与suggestion的边界是"是否已被接受":尚未决策的功能请求只能先标suggestion,而不是feat。regression的判定依据正是 Step 4 的双版本对比——旧版本可用、新版本坏掉,才配得上这个标签。
区域标签(选一个最匹配的)
| Label | Area |
|---|---|
node compat | 通用 Node.js 兼容性 |
node API | 特定node:*模块 API |
ext/node,ext/fs,ext/net,ext/http,ext/fetch,ext/web,ext/crypto,ext/console,ext/url,ext/websocket,ext/kv | 具体扩展 |
cli | CLI 行为、flag、子命令 |
lsp | 语言服务器 |
runtime | Runtime crate |
permissions | 权限系统 |
compile | deno compile |
testing | deno test与覆盖率 |
task runner | deno task |
install | deno install/deno add |
tsc | TypeScript 编译器 |
types | TypeScript 类型问题 |
config | deno.json配置 |
node resolution | Node/npm 模块解析 |
publish | deno publish |
lint | deno lint |
wasm | WebAssembly |
这些标签并非凭空命名,而是与仓库目录结构高度对齐,这让"区域标签"实际上承担了分诊路由的职责:
ext/*系列标签对应 ext/ 下的同名扩展 crate,如 ext/fetch/、ext/net/、ext/kv/、ext/web/、ext/crypto/、ext/console/、ext/url/、ext/websocket/;Node 兼容性问题落在 ext/node/(含 ext/node/polyfills/ 下的内置模块 polyfill);cli对应 cli/ crate:flag 解析在 cli/args/flags.rs,每个子命令在 cli/tools/ 下一个模块(如 cli/tools/compile.rs、cli/tools/test/、cli/tools/lint/、cli/tools/publish/、cli/tools/pm/ 对应deno install/deno add的包管理工具链);lsp对应 cli/lsp/;runtime对应 runtime/(deno_runtimecrate);permissions对应 runtime/permissions.rs 及 runtime/permissions/ 目录下的权限系统;config的解析实现位于 libs/config/ crate。
这个映射与 doc/codebase-map.md 的目录导览一致:ext/下每个子目录就是一个扩展(Rust crate 加带数字前缀的 JS 文件,如 ext/fs/30_fs.js),所以拿到一个带区域标签的 issue,基本就能直接定位到应读的源码目录。
优先级标签(仅在明显必要时添加)
| Label | 使用场景 |
|---|---|
high priority | 影响严重、阻塞用户、安全问题 |
quick fix | 显然简单的修复 |
添加与清理标签
gh issue edit $ARGUMENTS --repo denoland/deno --add-label "bug"并移除待分诊标记(若存在):
gh issue edit $ARGUMENTS --repo denoland/deno --remove-label "needs triage" --remove-label "triage required 👀"移除needs triage/triage required 👀是"分诊完成"的标志性动作——与 CI 中pre-build决定任务去留类似,分诊结论决定 issue 的后续流向:带bug的 issue 进入开发流程,带duplicate/question/invalid的进入关闭流程。
Step 6:发布分诊评论
评论按 issue 类型使用固定模板,保证信息结构一致、可快速扫读:
确认的 bug:
Confirmed on [version]. [Brief description of what you observed.] [If tested on canary: "Also reproduces on canary." or "Does not reproduce on canary — may already be fixed."]需要补充信息:
Thanks for reporting. Could you provide [missing info]? This will help us investigate.重复 issue:
This looks like a duplicate of #XXXX. Closing in favor of that issue.使用问题:
This is a usage question rather than a bug. [Brief answer or pointer to docs.] Closing this — feel free to ask on https://discord.gg/deno if you have more questions.发布与关闭命令:
gh issue comment $ARGUMENTS --repo denoland/deno --body "comment text"gh issue close $ARGUMENTS --repo denoland/deno --reason "not planned"注意关闭的适用范围:只有 duplicate、question、invalid 三类可以关闭,bug report 一律不关——即使暂无人处理,needs info的 bug 也只评论不关闭,等待作者补充。
Rules:安全边界与行为守则
技能末尾的 Rules 一节划定了自动化分诊的安全边界,也是整套流程可信度的来源:
- 任何修改 GitHub 的操作(发评论、改标签)前必须与用户确认——Agent 拥有
gh权限但不应越权执行; - 不关闭 bug report,只关闭重复、问题类和无效 issue;
- 标签保持最小化:一个类型标签 + 一个区域标签通常足够;
- 对报告者保持善意,感谢报告者,尤其是首次贡献者;
- 无法复现就如实说明,不猜测原因——不确定的结论比没有结论更有危害;
- 复现所需权限或资源不可用时,记录该限制并跳过复现;
- 未经调查不得驳回任何 issue。
小结
issue-triage/SKILL.md 展示了一种可复制的"Agent 技能"写法:用 frontmatter 声明触发条件与最小工具集,用编号步骤固定工作流顺序,用快速路径避免无谓工作(question/duplicate 跳过复现),用模板化输出保证结论一致,用显式 Rules 划定自动化行为的边界。配合 Deno 仓库自身的分层结构(cli/、runtime/、ext/、libs/),区域标签实际上把每个 issue 路由到了正确的源码目录,让"分诊"从行政动作变成了有技术含义的分诊。同一目录下的 review-pr/SKILL.md 则把同样的方法论应用到了 PR 审查侧(门禁检查、逐文件审查、结构化 review),两者共同构成 Deno 仓库面向 AI Agent 的贡献者工作流。
【免费下载链接】denoA modern runtime for JavaScript and TypeScript.项目地址: https://gitcode.com/GitHub_Trending/de/deno
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考