首页
/ Description

Description

2026-09-05 15:08:38作者:吴年前Myrtle

Description

<what breaks, what the user experiences>

Steps to reproduce

  1. <step 1>
  2. <step 2>

Expected behavior

Affected versions

```

Enhancement 模板:

### Description

<what the user can now do that they couldn't before>

### Use case

<why this is useful, who benefits>

### Affected versions

<version>

模板之外还有一条容易被忽视的排版规则(原文特别注明同样适用于 PR 正文):正文段落不要软换行——每个段落在源码中只占一行,换行只保留给结构性断行(章节头、列表项、代码块围栏、空行分隔),列表项每项一行。这样 GitHub 渲染正常,且每次小改措辞时 diff 不会变得噪声满屏。

6. 创建、设置 Issue Type、验证与清理:完整命令链

6.1 创建 Issue

cat > /tmp/issue-body.md << 'ISSUE_BODY'
<body content here>
ISSUE_BODY

gh issue create \
  --repo penpot/penpot \
  --title "<Derived title>" \
  --label "<label>" \
  --project "Main" \
  --body-file /tmp/issue-body.md

输出为 https://github.com/penpot/penpot/issues/<NUMBER>

6.2 用 GraphQL 设置 Issue Type

gh issue create 不能直接设 Issue Type,需要创建后调用 GraphQL mutation。规范记忆为 penpot/penpot 仓库固化了六个 Issue Type ID 及映射规则:

Type ID
Bug IT_kwDOAcyBPM4AX5Nb
Enhancement IT_kwDOAcyBPM4B_IQN
Feature IT_kwDOAcyBPM4AX5Nf
Task IT_kwDOAcyBPM4AX5NY
Question IT_kwDOAcyBPM4B_IQj
Docs IT_kwDOAcyBPM4B_IQz

映射规则:有复现步骤、期望/实际行为对比的 bug 报告 → Bug;增强/新功能 → Enhancement;feature/epic → Feature;文档 → Docs;以上都不是 → Task

设置命令分两步:先按 issue number 查节点 ID,再发起 updateIssue mutation:

ISSUE_ID=$(gh api graphql -f query='
query { repository(owner: "penpot", name: "penpot") {
  issue(number: <NUMBER>) { id }
}}' --jq '.data.repository.issue.id')

gh api graphql -f query='
mutation {
  updateIssue(input: {
    id: "'"$ISSUE_ID"'"
    issueTypeId: "<TYPE_ID>"
  }) {
    issue { number issueType { name } }
  }
}'

6.3 验证与清理

gh issue view <NUMBER> --repo penpot/penpot \
  --json title,labels,milestone,projectItems \
  --jq '{title, milestone: .milestone.title, labels: [.labels[].name], projects: [.projectItems[].title]}'

gh api graphql -f query='
query { repository(owner: "penpot", name: "penpot") {
  issue(number: <NUMBER>) { issueType { name } }
}}' --jq '.data.repository.issue.issueType.name'

rm -f /tmp/issue-body.md

第一条命令核对标题、里程碑、标签与 Project 归属,第二条核对 Issue Type 是否生效,最后删除临时正文文件。

7. 流程一:从 PR 创建 Issue

该流程用于项目看板需要 Issue 作为主要 changelog/release 单元、而 PR 只描述实现的场合。步骤如下:

1) 拉取 PR 信息:

gh pr view <PR_NUMBER> --repo penpot/penpot \
  --json title,body,author,labels,baseRefName,mergedAt,state,milestone

从中分离出 WHAT(用户可见的问题或功能,进入 Issue,只描述症状与影响,不写内部机制)和 HOW(实现细节,留在 PR)。

2) 确定元数据:

  • 标题:用第 3 节的规则从用户视角重写,剥离 :bug::sparkles::tada: 前缀,聚焦可观察行为;
  • 标签:PR 上有 community contribution 就复制过来;
  • 里程碑:一律复制 PR 的(gh pr view <PR_NUMBER> --json milestone --jq '.milestone.title');PR 没有里程碑则创建时不带;
  • ProjectMain
  • 正文:只提取用户可见部分(复现步骤或功能描述),用第 5 节的模板;
  • Issue Type:按映射表处理(gh.py 输出中的 issue_type 与标题前缀如 :bug: / :sparkles: / :tada: 一并考虑)。

3) 创建 Issue(命令同上,附条件标签与里程碑):

cat > /tmp/issue-body.md << 'ISSUE_BODY'
<body content here>
ISSUE_BODY

gh issue create \
  --repo penpot/penpot \
  --title "<Title>" \
  --label "community contribution" \   # only if PR has this label
  --milestone "<milestone>" \
  --project "Main" \
  --body-file /tmp/issue-body.md

4) 指派给 PR 作者:

AUTHOR=$(gh pr view <PR_NUMBER> --repo penpot/penpot --json author --jq '.author.login')
gh issue edit <ISSUE_NUMBER> --repo penpot/penpot --add-assignee "$AUTHOR"

5) 设置 Issue Type 并验证——直接复用第 6.2 / 6.3 节的命令,"无论 Issue 来源如何,GraphQL mutation 与 gh issue view 调用完全相同"。

6) 把 PR 关联到 Issue:向 PR 正文追加 Closes #<ISSUE_NUMBER>

gh pr view <PR_NUMBER> --repo penpot/penpot --json body --jq '.body' > /tmp/pr-body.md
printf "\n\nCloses #<ISSUE_NUMBER>\n" >> /tmp/pr-body.md
gh pr edit <PR_NUMBER> --repo penpot/penpot --body-file /tmp/pr-body.md

# Verify
gh pr view <PR_NUMBER> --repo penpot/penpot --json body \
  --jq '.body | test("Closes #<ISSUE_NUMBER>")'

规范记忆特别注明:如果 PR 已经合并,Closes 不会自动关闭 Issue——它只创建 Development 侧边栏链接。这是期望行为,因为 Issue 的定位是追踪工件(tracking artifact),而不是等待自动关闭的工单。

7) 清理临时文件: rm -f /tmp/issue-body.md /tmp/pr-body.md

流程规则(Rules for this flow):

  • 一个 PR 只对应一个 Issue——即使 PR 修了多个问题,也创建一个概括整体变更的单一 Issue;
  • 社区贡献归属——PR 带 community contribution 标签或作者非核心团队成员时,Issue 加该标签;
  • Issue 正文不写实现细节——Issue 面向用户、QA 和 changelog 读者。

8. 流程二:从草稿正文创建

适用于用户提供来自别处的草稿正文(Taiga story、用户报告、讨论记录)且尚无 PR 的场合。

  1. 获取正文:从用户提供的来源读取草稿;如果用户只给了一句含糊描述,先要求展开(复现步骤、期望/实际、使用场景)再继续;
  2. 推导标题:套用第 3 节规则,并根据正文内容区分 bug 与 feature——"复现步骤 + 期望/实际" → bug;"would be nice"、"add support for"、"allow users to" → feature / enhancement;
  3. 选正文模板:用 Bug 或 Enhancement 模板并填入用户提供的细节;两者都不贴合时,问用户用哪个;
  4. 确定元数据:Project 固定 Main;Milestone 不明显时问用户,否则省略;新报的用户问题通常不带标签,非团队成员贡献者加 community contribution;Issue Type 按映射表(bug 描述 → Bug,功能请求 → Enhancement 或 Feature);
  5. 创建 Issue(命令同第 6.1 节,条件性带标签与里程碑)→ 6) GraphQL 设置 Issue Type 并验证(同第 6.2 / 6.3 节)→ 7) 清理rm -f /tmp/issue-body.md

Penpot 仓库还提供配套的 Taiga 数据获取能力:taiga Skill 包装的 scripts/taiga.py 可以免认证拉取 Penpot 项目(id 345963)的 issue / user story / task,例如 python3 scripts/taiga.py https://tree.taiga.io/project/penpot/issue/13714——这正是"从草稿正文创建"流程中 Taiga story 这类素材的取数入口。

9. 流程三:重命名现有 Issue

适用于 Issue 现标题含糊、带前缀(如 [PENPOT FEEDBACK]: ...feature: ...)或已与正文脱节。

1) 拉取 Issue:

gh issue view <NUMBER> --repo penpot/penpot --json title,body

2) 推导新标题:读正文(而不是现标题),应用第 3 节标题规则。

3) 应用新标题:

gh issue edit <NUMBER> --repo penpot/penpot --title "<NEW TITLE>"

4) 确认:

gh issue view <NUMBER> --repo penpot/penpot --json title
登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.83 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
987
506
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384