首页
/ Mole Release Notes Skill:精选双语 Release Notes 的撰写规范、校验清单与发布命令全流程

Mole Release Notes Skill:精选双语 Release Notes 的撰写规范、校验清单与发布命令全流程

2026-09-04 20:56:46作者:魏献源Searcher

本文以 Mole 仓库中的 release-notes Skill 文档 为主体,完整讲解在 release.yml 工作流完成之后,如何为既有 V<version> 标签撰写并手动补发精选 Release Notes:从六个前置输入项、五项 pre-flight 校验、严格的双语(English/中文)格式模板与十余条“踩坑后固化”的格式规则,到 gh release edit 发布命令与六枚 reaction 辅助脚本 post-reactions.sh 的逐行实现。读完本文,你可以按 Mole 项目自身的约定独立走完“草稿—用户确认—发布—发布后检查”的完整发布说明流程。

一、定位:为什么 Release Notes 是工作流之后的手动环节

release-notes/SKILL.md 的 description 字段把该 skill 的适用边界写得很明确:

  • 在明确要求“编辑或发布 Mole release notes”时使用;
  • 不负责 release readiness(发布就绪检查)、打 tag 或代码评审——这些属于姊妹文档 release-flow/SKILL.md 的职责。

它驱动的是精选 notes 环节,运行在 release.yml 结束之后。从 release.yml 源码可以确认这条流水线的事实依据:

  1. 工作流只监听大写 V 开头的 tag(release.yml#L5-L6tags: - 'V*')。小写 v1.38.0 这类 tag 不会触发工作流,往往意味着打 tag 环节出了问题。
  2. 工作流通过 softprops/action-gh-release 创建 GitHub Release,且显式设置了 generate_release_notes: falserelease.yml#L110-L118):
- name: Create Release
  uses: softprops/action-gh-release@... # v3.0.2
  if: startsWith(github.ref, 'refs/tags/')
  with:
    name: ${{ github.ref_name }}
    files: bin/*
    generate_release_notes: false
    draft: false
    prerelease: false

也就是说:工作流已经创建了带资产的 Release,但没有 notes。因此后续补发说明只能用 gh release edit绝不能用 gh release create——release 已存在,create 会直接冲突。这是该 skill 反复强调的第一原则。

二、动笔前必须收集的六个输入

SKILL.md 的 “Inputs to gather” 一节列出了动笔前必须逐项确认的输入,原文完整继承如下:

  1. 版本号(Version)。必须是大写 V,例如 V1.38.0。小写 v 不会触发工作流,并且通常说明 tag 打错了。
  2. 代号(CodeName)+ emoji。向用户索要。标题格式固定为 V<version> <CodeName> <emoji>,例如 release-flow/SKILL.md 中给出的仓库惯例示例 V1.45.0 Quiet 🤫
  3. Release 提交区间git log <previous-tag>..V<version> --oneline 提供原始素材。
  4. 用户可见的行为变化。扫描完整 commit message body(而不只是 subject 行),寻找收窄的检测范围、被移除的功能、受控的回归。这些即使不是 bug-fix 形态,也属于“用户在生产环境会撞上变化边界”的内容,必须写入 notes。
  5. 本周期的 Issue 报告者与 PR 贡献者。基于 release 区间内的 merged PRs 与 fixed issues。名单保持简短,格式如 Issue reporters and PR contributors this cycle: @a · @b.;排除 tw93 本人和 bot 账号。
  6. 确认 Release 已存在。执行 gh release view V<version> --repo tw93/Mole --json id,name,返回非空才算数。若为空,说明工作流还没跑完——等待,而不是手动 gh release create

其中第 6 点与 release-flow/SKILL.md 的 “Release-only pitfalls” 一节互相印证:工作流在 tag push 时就已创建 release,tag 之后的补发必须走 edit 通道。

三、Pre-flight:发布 notes 之前的五项交叉校验

SKILL.md 要求在发布前对照 AGENTS.md 的约定做交叉校验。正常情况下 tag 打得对,这些应该已经成立,但发布 notes 前仍要逐项确认:

校验项 命令/检查 当前仓库现状(佐证)
主脚本内版本号 grep '^VERSION=' mole<version> 一致 mole 第 57 行为 VERSION="1.53.0"
安全审计文档头部 SECURITY_AUDIT.md 首行反映新版本与日期 其第三行为 ... updated for V1.53.0 on 2026-08-30.
格式检查 ./scripts/check.sh --format 通过 scripts/check.sh
Shell 测试套件 MOLE_TEST_NO_AUTH=1 MOLE_TEST_JOBS=2 BATS_FORMATTER=tap ./scripts/test.sh 退出码 0 scripts/test.shtests/ 下的 bats 用例
Go 侧构建 go test ./cmd/...make build 均通过 Makefilebuild/release-* 目标

SKILL.md 对失败的处理只有一句话,但态度明确:“If any fail, stop. The notes can wait; a bad release tag cannot.”(任何一项失败就停下——notes 可以等,坏掉的 release tag 不行。)

四、格式规范:双语紧凑模板与“踩坑固化”的规则

4.1 唯一的格式基准:最近一次稳定 release 的正文

SKILL.md 要求动笔前先读取当前最新稳定 release 作为活的格式参考:

gh release view --repo tw93/Mole --json tagName,body

这对应 release-flow/SKILL.md 中 “Ritual anchors” 的说法:草稿前读取最近稳定 release 正文是“硬格式模板”(hard format template)。仓库中保留的 docs/release-notes/V1.42.0.md 是一份历史样本,可以看出格式的历史演变(它仍带 ### Thanks 💖 标题与尾部仓库链接,而现行 skill 明确规定这两者已不存在)。

4.2 结构模板(完整继承)

严格按当前紧凑形态组织:

<div align="center">
  <img src="https://cdn.tw93.fun/pic/cole.png" alt="Mole Logo" width="120" height="120" style="border-radius:50%" />
  <h1 style="margin: 12px 0 6px;">Mole</h1>
  <p><em>Deep clean and optimize your Mac.</em></p>
</div>

### Changelog

1. **<English headline>**: <one-sentence English elaboration>.
2. ...

### 更新日志

1. **<中文 headline>**:<一句中文说明>。
2. ...

### Thanks

Issue reporters and PR contributors this cycle: @handle1 · @handle2.

### Mole Mac App

Prefer a GUI? [Mole Mac App](https://mole.fit/) brings cleaning, app management, maintenance, disk analysis, and live system status into one native app, with review before deletion and a customizable menu bar HUD. It is $19 once, with lifetime updates and a 14-day refund. [Download and try it](https://mole.fit/download). The CLI stays free and open source.

两条全局约定:章节之间不使用 --- 分隔线文末不追加仓库链接——公开页面以 Mole Mac App 一段收尾。

4.3 格式规则:每一条都是“曾经真实出货过的 bug”

SKILL.md 特别强调,下列规则全部是曾经真实流出过的文档 bug,因此逐条固化:

  • 正文 h1 只能是 Mole。版本号、代号、emoji 只出现在 --title 参数里(V<version> <CodeName> <emoji>);在正文头部重复它们是冗余,之前曾被明确驳回。
  • 全文禁止 em dash(—)。用逗号、句号、冒号、分号或括号替代。
  • 默认不放赞助商列表。当前公开风格只感谢本周期的 Issue 报告者与 PR 贡献者。
  • 除 release 标题中的版本 emoji 外,正文禁止任何 emoji。章节标题保持朴素,包括 ### Thanks(旧版 Thanks 💖 标题已从公开页面移除)。
  • 正文不内联 PR 引用,不内联 @handle 感谢。PR 与人名只允许出现在专门的 Thanks 区块。
  • 英文块在前、中文块在后;两个块编号顺序一致、条目数量相同。
  • 按用户可感知影响排序,而非 commit 时间顺序。headline 级变化放最前,内部安全加固、性能与 bug 修复随后。
  • 不要描述已不存在的 overview 图标。Analyze 概览行是纯文本,因为 emoji 宽度与基线在不同终端表现不一;若日后图标回归,也不得暗示 iOS Backups、Xcode Archives、Old Downloads 这类用户数据可以安全删除。
  • notes 中提到的每条命令都必须在 HEAD 上真实存在。被删除的 mo check / mo doctor 命令曾在移除后险些作为“新特性”写进 notes——这正是做存在性验证的原因。
  • 事故/排障类说明 = 一句症状 + 一条命令。不做原因分类,不逐分支给命令;用户需要的只是让他“解套”的那一行。并且对齐上一次 release 的语言处理:若上次 release 只用一种语言写了该条说明,这次不要补第二种。
  • Mole Mac App 交叉链接保持为一个克制、事实可证的段落。发布前对照当前首页核验产品范围、价格、更新策略、退款窗口与下载 URL。

对照 docs/release-notes/V1.42.0.md 这份历史样本,可以更直观地理解规则演进:它的 ### Thanks 💖 标题、英文条目缺少一句话 elaboration、以及末尾的仓库链接,都恰好是现行规则要剔除的形态——现行模板要求每条 changelog 为“加粗 headline:一句话说明”,并移除了尾部链接与 emoji 标题。

五、发布:gh release edit 与六枚 reaction

5.1 编辑命令

用户批准草稿后,SKILL.md 给出的发布命令是:

gh release edit V<version> --repo tw93/Mole \
  --title "V<version> <CodeName> <emoji>" \
  --notes-file <path-to-draft>

再次强调:永远不要 gh release create,它会与工作流已创建的 release 冲突。

5.2 六枚 reaction 的辅助脚本

发布 notes 后,用该 skill 自带的辅助脚本补上标准六枚 reaction(+1laughhoorayheartrocketeyes)。注意脚本路径是相对 SKILL.md 自身scripts/post-reactions.sh,而不是仓库根目录的 scripts/

bash "$(dirname <this SKILL.md>)/scripts/post-reactions.sh" V<version>

post-reactions.sh 的完整实现如下,逻辑非常短平快,可逐行验证:

#!/bin/bash
# Add the standard six reactions (+1, laugh, hooray, heart, rocket, eyes) to a
# tw93/Mole release. Usage: post-reactions.sh V<version>

set -euo pipefail

TAG="${1:-}"
if [[ -z "$TAG" ]]; then
    echo "Usage: $0 V<version>" >&2
    exit 1
fi

if [[ "$TAG" != V* ]]; then
    echo "Tag must start with capital V (release.yml ignores lowercase v): $TAG" >&2
    exit 1
fi

if ! command -v gh > /dev/null 2>&1; then
    echo "gh CLI is required" >&2
    exit 1
fi

RELEASE_ID=$(gh api "repos/tw93/Mole/releases/tags/$TAG" --jq '.id')
if [[ -z "$RELEASE_ID" ]]; then
    echo "Release not found for tag: $TAG" >&2
    exit 1
fi

for r in +1 laugh hooray heart rocket eyes; do
    gh api "repos/tw93/Mole/releases/$RELEASE_ID/reactions" \
        -X POST -f content="$r" --silent
done

echo "Posted 6 reactions to $TAG (release id $RELEASE_ID)"

从源码看,脚本内置了三道护栏:

  1. set -euo pipefail:任何一步失败立即中止;
  2. tag 前缀大小写校验[[ "$TAG" != V* ]] 直接拒绝小写 tag,错误信息里还顺带解释了原因(release.yml 忽略小写 v)——与 release.yml'V*' 过滤条件严格一致;
  3. Release 存在性校验:先经 gh api .../releases/tags/$TAGid,取不到就报错退出,不会盲发。

拿到 RELEASE_ID 后循环向 releases/$RELEASE_ID/reactions 逐枚 POST,最后打印确认行 Posted 6 reactions to $TAG (release id $RELEASE_ID)release-flow/SKILL.md 还要求发布后重新读取 release 的 reactions 确认六枚全部落位

六、发布后动作

SKILL.md 的 “After publish” 两项:

  1. gh release view V<version> --repo tw93/Mole --web 在浏览器中打开,让用户肉眼检查渲染效果;
  2. 提醒用户:Homebrew Core 的版本 PR 由工作流驱动,此时应该已经在途;除非工作流日志显示失败,不要手动重跑。

这与 release.yml 中 build job 之后的 update-homebrew-core job 相印证:同一次 V* tag push 会串行触发构建、创建 Release 与 Homebrew PR,人工只需要在 notes 环节介入。

七、When NOT to act:调用边界与隐式调用禁用

该 skill 是纯用户可调用(user-invocable only)的,front matter 中 disable-model-invocation: true 声明了这一点,不允许被模型自行触发。具体行为边界:

  • 用户只是顺带提到 release notes 时:只出草稿,不要调用 gh release edit
  • gh release view 显示 release 尚不存在时:等待工作流,不要手动创建竞争的 release;
  • 用户没有给出明确的 “publish” / “提交” 信号时:草稿交付即止

在 Codex 一侧,release-flow/SKILL.md 提到 .agents/skills/release-notes 是指向 .claude/skills/release-notes符号链接(供 Codex 发现机制使用),其专属调用策略存放在 agents/openai.yaml,内容为一行 policy: allow_implicit_invocation: false。该文档同时叮嘱:不要把符号链接替换成拷贝副本,且以 release-notes skill 作为 notes 格式的唯一事实来源(single source of truth),不要在 release-flow 中重复其格式细节。

八、与 release-flow skill 的分工小结

结合 release-flow/SKILL.md,两个 skill 的职责切分可以归纳为:

环节 归属 关键点
打 tag、资产构建、SHA256SUMS、Homebrew PR release-flow 大写 V tag;安装校验是 fail-closed,缺 SHA256SUMS 即发布阻断项
发布前的脚本自更新冒烟 release-flow 用旧版脚本安装 → mo update → 确认 mo --version 输出候选版本
notes 草稿格式、Thanks 区块、gh release edit release-notes(本文主体) editcreate;双语同序同数量
六枚 reaction 与发布后检查 release-notes(本文主体) post-reactions.sh 位于 skill 目录内

对维护者而言,这套文档的价值不在单条命令,而在于把“哪些坑流出过货”固化成了可执行的清单:大写 V、只 edit 不 create、命令存在性核验、影响排序、Thanks 区块的排他性——每一条背后都是一次真实事故的复盘,这也是 Mole 这类以 Shell 为主、发布流程高度自动化的项目能够保持 release notes 风格长期一致的原因。

登录后查看全文
热门项目推荐
相关项目推荐