关于 release
面向 Paperclip 维护者的发布技能,协调 Canary 检查和稳定版发布,涵盖验证、发布与后续事项;启用 Cases 时还会组织发布内容案例。
主要功能
- 01Canary 验证与冒烟测试
- 02稳定版日志与晋级
- 03验证和发布步骤
- 04创建 GitHub Release
- 05网站与公告后续事项
- 06发布内容 Cases
适用场景
- 01稳定版晋级前检查 Canary
- 02将已测试的源引用晋级为稳定版
- 03协调发布公告和网站更新
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ paperclipai/ paperclip --skill release安装后在 Claude Code 中输入/release确认已加载。
详细介绍
发布协调技能
运行完整的 Paperclip 维护者发布工作流,而不只是发布到 npm。
此技能协调以下事项:
- 通过
release-changelog起草稳定版变更日志 - 验证来自
master的 Canary 版本并确认其发布状态 - 通过
scripts/docker-onboard-smoke.sh执行 Docker 冒烟测试 - 从指定的源引用手动晋级到稳定版
- 创建 GitHub Release
- 后续处理网站和公告任务
- 对发布内容进行 Cases 实测:创建一个顶层
releasecase,并包含子级blog_post和tweet_stormcases,全部关联到发布 issue/run
触发条件
当负责人提出以下要求时使用此技能:
- “进行一次发布”
- “发布这个版本”
- “将此 Canary 晋级为稳定版”
- “发布稳定版”
前置条件
开始前,验证以下所有条件:
.agents/skills/release-changelog/SKILL.md存在且可用。- 仓库工作树干净,包括未跟踪文件。
- 自上一个稳定版标签以来,至少有一个 Canary 或候选提交。
- 候选 SHA 已通过验证门槛,或即将通过。
- 如果清单有变更,由 CI 负责更新的
pnpm-lock.yaml已合并到master。 - 可通过 GitHub 可信发布获得 npm 发布权限,或通过本地 npm 身份验证用于紧急/手动发布。
- 如果通过 Paperclip 运行,需具备 issue 上下文,以便更新状态和创建后续任务。
如果任何前置条件未满足,请停止并报告阻碍事项。
输入
开始时收集以下输入:
- 目标是 Canary 检查还是稳定版晋级
- 稳定版候选
source_ref - 稳定版运行是试运行还是正式运行
- 用于网站和公告后续跟进的发布 issue / 公司上下文
步骤 0 — 发布模式
Paperclip 现在采用由提交驱动的发布模式:
- 每次推送到
master都会自动发布 Canary 版本 - Canary 版本使用
YYYY.MDD.P-canary.N - 稳定版使用
YYYY.MDD.P - 中间部分为
MDD,其中M是 UTC 月份,DD是补零的 UTC 日期 - 如果同一个 UTC 日期发布多个稳定版,则递增稳定版补丁号
- 稳定版从指定的、已测试的提交或 Canary 源提交手动晋级
- 只有稳定版才会生成
releases/vYYYY.MDD.P.md、git 标签vYYYY.MDD.P和 GitHub Release
重要影响:
- 不要将发布分支作为默认路径
- 不要推导主版本号/次版本号/补丁版本号的升级
- 不要创建 Canary 变更日志文件
- 不要创建 Canary GitHub Release
步骤 1 — 选择候选版本
进行 Canary 验证时:
- 检查
master上最新一次成功的 Canary 运行 - 记录 Canary 版本和源 SHA
晋级到稳定版时:
- 选择已测试的源引用
- 确认它正是要晋级的 SHA
- 使用
./scripts/release.sh stable --date YYYY-MM-DD --print-version确定目标稳定版
实用命令:
git tag --list 'v*' --sort=-version:refname | head -1
git log --oneline --no-merges
npm view paperclipai@canary version
步骤 2 — 起草稳定版变更日志
稳定版变更日志文件位于:
releases/vYYYY.MDD.P.md
调用 release-changelog,仅生成或更新稳定版说明。
规则:
- 发布前由人工审核草稿
- 如果文件已存在,则保留手动编辑内容
- 文件名仅用于稳定版
- 不要创建 Canary 变更日志文件
步骤 3 — 验证候选 SHA
运行标准门槛:
pnpm -r typecheck
pnpm test:run
pnpm build
如果 GitHub release 工作流将负责发布,可以由它重新运行此门槛。即便如此,如果你已检查本地状态,仍需报告该状态。
对于涉及发布逻辑的 PR,仓库还会在 CI 中运行 Canary 发布试运行。这是发布专用的防护措施,不能替代标准门槛。
步骤 4 — 验证 Canary
常规 Canary 流程会通过以下工作流从 master 自动运行:
.github/workflows/release.yml
确认:
- 验证已通过
- npm Canary 发布成功
- git 标签
canary/vYYYY.MDD.P-canary.N存在
实用检查:
npm view paperclipai@canary version
git tag --list 'canary/v*' --sort=-version:refname | head -5
步骤 5 — 对 Canary 进行冒烟测试
运行:
PAPERCLIPAI_VERSION=canary ./scripts/docker-onboard-smoke.sh
适用于隔离环境的变体:
HOST_PORT=3232 DATA_DIR=./data/release-smoke-canary PAPERCLIPAI_VERSION=canary ./scripts/docker-onboard-smoke.sh
确认:
- 安装成功
- 入门流程完成且未发生崩溃
- 服务启动
- UI 加载
- 公司创建和仪表板加载等基本功能正常
如果冒烟测试失败:
- 停止稳定版发布
- 在
master上修复问题 - 等待下一个自动 Canary
- 重新运行冒烟测试
步骤 6 — 预览或发布稳定版
常规稳定版发布流程是在以下工作流上手动执行 workflow_dispatch:
.github/workflows/release.yml
输入项:
source_refstable_datedry_run
正式发布稳定版之前:
- 使用
./scripts/release.sh stable --date YYYY-MM-DD --print-version确定目标稳定版版本 - 确保源引用上存在
releases/vYYYY.MDD.P.md - 实际可行时,先以 dry-run 模式运行稳定版工作流
- 然后执行正式的稳定版发布
稳定版工作流会:
- 重新验证确切的源引用
- 计算所选 UTC 日期对应的下一个稳定版补丁版本
- 将
YYYY.MDD.P发布到 dist-taglatest - 创建 git 标签
vYYYY.MDD.P - 根据
releases/vYYYY.MDD.P.md创建或更新 GitHub Release
本地紧急/手动命令:
./scripts/release.sh stable --dry-run
./scripts/release.sh stable
git push public-gh refs/tags/vYYYY.MDD.P
./scripts/create-github-release.sh YYYY.MDD.P
步骤 7 — 完成其他渠道的后续工作
为以下事项创建或确认后续工作:
- 发布网站更新日志
- 发布上线公告/社交媒体公告
- 在 Paperclip issue 上下文中添加发布摘要
这些内容应引用稳定版,而非 Canary。
步骤 8 — 生成发布内容 Cases
启用 Cases 后,每次稳定版发布内容运行都必须生成确定性的 case 树。这是发布 dogfood 流程的一部分,不是可选产物。如果 API 返回 403 Cases are disabled,请停止并报告操作员必须启用 experimental.enableCases。
使用当前发布 issue 中的 PAPERCLIP_COMPANY_ID、PAPERCLIP_API_URL、PAPERCLIP_API_KEY 和 PAPERCLIP_RUN_ID。所有写入请求都要包含 X-Paperclip-Run-Id,以便 case 活动动态将运行归属到该 issue。
先创建或更新父级 release case:
POST /api/companies/:companyId/cases
{
"caseType": "release",
"key": "paperclip-release:vYYYY.MDD.P",
"title": "Paperclip vYYYY.MDD.P release",
"summary": "Stable release content package for Paperclip vYYYY.MDD.P.",
"status": "in_progress",
"fields": {
"schema_version": 1,
"version": "vYYYY.MDD.P",
"release_date": "YYYY-MM-DD",
"source_ref": "git-sha-or-ref",
"stable": true,
"channels": ["changelog", "blog_post", "tweet_storm"],
"artifacts": {
"changelog_path": "releases/vYYYY.MDD.P.md",
"github_release_url": null
},
"verification": {
"typecheck": "unknown",
"tests": "unknown",
"build": "unknown",
"smoke": "unknown"
},
"notes": null
}
}
fields schema 有意使用所有通用 JSON 值类型:字符串、数字、布尔值、数组、对象和 null。每次 upsert 时都要发送完整的 fields 对象,因为 case 字段会作为一个整体对象替换。
upsert 后立即写入父级正文文档:
PUT /api/cases/:releaseCaseId/documents/body
{
"title": "Paperclip vYYYY.MDD.P release body",
"format": "markdown",
"body": "# Paperclip vYYYY.MDD.P\n\nRelease summary and links...",
"changeSummary": "Initial release case body"
}
然后创建或更新以下子 case,并将 parentCaseId 设为 release case 的 ID:
blog_post,key 为paperclip-release:vYYYY.MDD.P:blog-post,状态为in_progress,正文文档 key 为bodytweet_storm,key 为paperclip-release:vYYYY.MDD.P:tweet-storm,状态为in_progress,正文文档 key 为body
必须使用完全一致的确定性 key,这样重新运行发布内容流程时会更新相同的三个 case,而不是重复创建。写入子级正文文档后,在发布 issue 以及存在时的父级验收 issue 中列出生成的 case 标识符和链接。
故障处理
如果 Canary 有问题:
- 再发布一个 Canary,不要发布稳定版
如果 npm 稳定版发布成功,但推送标签或创建 GitHub Release 失败:
- 立即基于同一发布结果修复 git/GitHub 问题
- 不要重新发布相同版本
如果稳定版发布后 latest 有问题:
./scripts/rollback-latest.sh <last-good-version>
然后发布新的稳定版以向前修复。
输出
技能完成后,请提供:
- 候选 SHA 和经过测试的 Canary 版本(如相关)
- 稳定版版本(如已升级发布)
- 验证状态
- npm 状态
- 冒烟测试状态
- git 标签/GitHub Release 状态
- 网站/公告后续工作状态
- 发布内容 case 树链接:父级
releasecase,以及blog_post和tweet_storm子级 - 如果仍有任何事项未完全完成,提供回滚建议