关于 ship
ship 是用于编码 Agent 的自动化发布工作流技能,可从分支检查、测试和审查一路执行到提交、推送及创建 PR。遇到测试失败、无法解决的合并冲突或指定的重大问题时会停止。
主要功能
- 01合并 origin/main 并运行测试
- 02按需执行提示词评测
- 03进行发布前代码审查
- 04自动更新版本与 CHANGELOG
- 05拆分提交并推送、创建 PR
适用场景
- 01将功能分支整理并发布为 PR
- 02在发布前运行测试和代码审查
- 03根据变更更新版本与 CHANGELOG
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ topshark-jim/ gstack --skill ship安装后在 Claude Code 中输入/ship确认已加载。
附带文件references/review-checklist.md
详细介绍
运行时注意事项
- 当工作流要求暂停并等待输入时,直接询问用户。
- 将
AGENTS.md、TODO.md和TODOS.md视为仓库本地说明的可能来源。 - 保持工作流意图不变,但将任何特定于环境的措辞调整为适用于当前工具集的表述。
Ship:全自动 Ship 工作流
你正在运行 ship 工作流。这是一个非交互式、全自动工作流。任何步骤都不要请求确认。用户说了 ship,就意味着立即执行。直接运行到底,并在最后输出 PR URL。
仅在以下情况下暂停:
- 当前位于
main分支(中止) - 出现无法自动解决的合并冲突(暂停并显示冲突)
- 测试失败(暂停并显示失败)
- 上线前审查发现 CRITICAL 问题,且用户选择修复(而非确认或跳过)
- 需要提升 MINOR 或 MAJOR 版本号(询问——见第 4 步)
绝不因以下情况暂停:
- 存在未提交的更改(始终包含这些更改)
- 版本号提升选择(自动选择 MICRO 或 PATCH——见第 4 步)
- CHANGELOG 内容(根据差异自动生成)
- 提交消息审批(自动提交)
- 多文件变更集(自动拆分为可二分排查的提交)
第 1 步:预检
-
检查当前分支。如果位于
main,则中止:“你当前位于 main 分支。请从功能分支进行 Ship。” -
运行
git status(不要使用-uall)。未提交的更改始终包含在内——无需询问。 -
运行
git diff main...HEAD --stat和git log main..HEAD --oneline,了解即将发布的内容。
第 2 步:合并 origin/main(测试前)
获取 origin/main 并将其合并到功能分支,以便测试针对合并后的状态运行:
git fetch origin main && git merge origin/main --no-edit
如果存在合并冲突: 如果冲突简单(VERSION、schema.rb、CHANGELOG 顺序),尝试自动解决。如果冲突复杂或存在歧义,则暂停并显示冲突。
如果已是最新: 静默继续。
第 3 步:运行测试(针对合并后的代码)
不要运行 RAILS_ENV=test bin/rails db:migrate——bin/test-lane 内部已调用
db:test:prepare,它会将架构加载到正确的 lane 数据库中。
在没有 INSTANCE 的情况下直接运行测试迁移会命中孤立数据库并破坏 structure.sql。
并行运行两个测试套件:
bin/test-lane 2>&1 | tee /tmp/ship_tests.txt &
npm run test 2>&1 | tee /tmp/ship_vitest.txt &
wait
两者完成后,读取输出文件并检查通过或失败情况。
如果任何测试失败: 显示失败信息并暂停。不要继续。
如果全部通过: 静默继续——只简要记录数量。
步骤 3.25:评估套件(有条件)
更改提示词相关文件时,必须运行评估。如果差异中没有提示词文件,请完全跳过此步骤。
1. 检查差异是否涉及提示词相关文件:
git diff origin/main --name-only
匹配以下模式(来自 AGENTS.md 或仓库附近的说明):
app/services/*_prompt_builder.rbapp/services/*_generation_service.rb、*_writer_service.rb、*_designer_service.rbapp/services/*_evaluator.rb、*_scorer.rb、*_classifier_service.rb、*_analyzer.rbapp/services/concerns/*voice*.rb、*writing*.rb、*prompt*.rb、*token*.rbapp/services/chat_tools/*.rb、app/services/x_thread_tools/*.rbconfig/system_prompts/*.txttest/evals/**/*(评估基础设施的变更会影响所有套件)
**如果没有匹配项:**打印 "No prompt-related files changed — skipping evals.",然后继续执行步骤 3.5。
2. 确定受影响的评估套件:
每个评估运行器(test/evals/*_eval_runner.rb)都会声明 PROMPT_SOURCE_FILES,列出会影响该运行器的源文件。使用 grep 搜索这些文件,找出与变更文件匹配的套件:
grep -l "changed_file_basename" test/evals/*_eval_runner.rb
运行器到测试文件的映射:post_generation_eval_runner.rb → post_generation_eval_test.rb。
特殊情况:
- 更改
test/evals/judges/*.rb、test/evals/support/*.rb或test/evals/fixtures/会影响所有使用这些判断器或支持文件的套件。检查评估测试文件中的导入,确定受影响的套件。 - 更改
config/system_prompts/*.txt时,使用 grep 搜索评估运行器中的提示词文件名,找出受影响的套件。 - 如果无法确定哪些套件会受影响,请运行所有可能受影响的套件。多测总比漏掉回归问题好。
3. 使用 EVAL_JUDGE_TIER=full 运行受影响的套件:
ship 是合并前的门禁,因此始终使用 full tier(Sonnet 结构判断器 + Opus 人设判断器)。
EVAL_JUDGE_TIER=full EVAL_VERBOSE=1 bin/test-lane --eval test/evals/<suite>_eval_test.rb 2>&1 | tee /tmp/ship_evals.txt
如果需要运行多个套件,请依次运行(每个套件都需要一个测试通道)。如果第一个套件失败,请立即停止,不要为剩余套件继续消耗 API 费用。
4. 检查结果:
- 如果任何评估失败:展示失败信息和费用仪表板,然后停止。不要继续执行。
- **如果全部通过:**记录通过数量和费用,然后继续执行步骤 3.5。
5. 保存评估输出——在 PR 正文(步骤 8)中包含评估结果和费用仪表板。
层级参考(供参考——/ship 始终使用 full):
| 层级 | 适用场景 | 速度(缓存后) | 费用 |
|---|---|---|---|
fast(Haiku) | 开发迭代、冒烟测试 | ~5s(快 14 倍) | ~$0.07/次运行 |
standard(Sonnet) | 默认开发、bin/test-lane --eval | ~17s(快 4 倍) | ~$0.37/次运行 |
full(Opus 人设) | ship 和合并前 | ~72s(基准) | ~$1.27/次运行 |
步骤 3.5:合并前审查
检查差异中测试未能发现的结构性问题。
-
阅读
references/review-checklist.md。如果无法读取该文件,停止并报告错误。 -
运行
git diff origin/main,获取完整差异(范围限定为相对于刚刚获取的远程 main 的功能变更)。 -
分两轮应用审查清单:
- 第 1 轮(严重):SQL 与数据安全、LLM 输出信任边界
- 第 2 轮(提示性):所有其余类别
-
始终输出所有发现——包括严重问题和提示性问题。用户必须看到发现的每个问题。
-
输出摘要标题:
Pre-Landing Review: N issues (X critical, Y informational) -
如果发现严重问题: 对每个严重问题,分别直接向用户提问,并包含:
- 问题(
file:line+ 描述) - 建议的修复方案
- 选项:A)现在修复(推荐),B)确认并仍然发布,C)这是误报——跳过
处理完所有严重问题后:如果用户对任何问题选择了 A(修复),应用建议的修复,然后仅按名称提交已修复的文件(
git add <fixed-files> && git commit -m "fix: apply pre-landing review fixes"),接着停止并告知用户再次运行ship,以便使用已应用的修复重新测试。如果用户对所有问题都只选择了 B(确认)或 C(误报),则继续步骤 4。
- 问题(
-
如果只发现非严重问题: 输出这些问题并继续。它们将纳入步骤 8 的 PR 正文。
-
如果没有发现问题: 输出
Pre-Landing Review: No issues found.并继续。
保存审查输出——它将写入步骤 8 的 PR 正文。
步骤 4:版本递增(自动决定)
-
读取当前的
VERSION文件(4 位格式:MAJOR.MINOR.PATCH.MICRO) -
根据差异自动决定递增级别:
- 统计变更行数(
git diff origin/main...HEAD --stat | tail -1) - MICRO(第 4 位):变更少于 50 行,包括微小调整、拼写错误、配置变更
- PATCH(第 3 位):变更 50 行或以上,包括错误修复、小型至中型功能
- MINOR(第 2 位):询问用户——仅用于主要功能或重大架构变更
- MAJOR(第 1 位):询问用户——仅用于里程碑或破坏性变更
- 统计变更行数(
-
计算新版本:
- 递增某一位时,将其右侧的所有位重置为 0
- 示例:
0.19.1.0+ PATCH →0.19.2.0
-
将新版本写入
VERSION文件。
步骤 5:CHANGELOG(自动生成)
-
阅读
CHANGELOG.md的文件头,了解格式。 -
根据分支上的所有提交(不只是近期提交)自动生成条目:
- 使用
git log main..HEAD --oneline查看本次发布的每个提交 - 使用
git diff main...HEAD查看相对于 main 的完整差异 - CHANGELOG 条目必须完整涵盖所有将纳入 PR 的变更
- 如果分支上现有的 CHANGELOG 条目已涵盖部分提交,则将其替换为新版本的一个统一条目
- 将变更归入适用的章节:
### Added— 新功能### Changed— 现有功能的变更### Fixed— 错误修复### Removed— 已移除的功能
- 编写简洁、明确的项目符号
- 插入到文件头之后(第 5 行),日期使用今天
- 格式:
## [X.Y.Z.W] - YYYY-MM-DD
- 使用
不要询问用户描述变更。 根据差异和提交历史进行推断。
步骤 6:提交(可二分定位的提交块)
目标: 创建小型、逻辑清晰的提交,使其适用于 git bisect,并帮助大模型理解更改内容。
-
分析差异并将更改分组成逻辑清晰的提交。每个提交都应代表一项连贯的更改——不是一个文件,而是一个逻辑单元。
-
提交顺序(较早的提交排在前面):
- 基础设施: 迁移、配置更改、路由添加
- 模型和服务: 新模型、服务、关注点(及其测试)
- 控制器和视图: 控制器、视图、JS/React 组件(及其测试)
- VERSION + CHANGELOG: 始终放在最后一次提交中
-
拆分规则:
- 模型及其测试文件放在同一次提交中
- 服务及其测试文件放在同一次提交中
- 控制器、其视图及其测试放在同一次提交中
- 迁移单独提交(或与其支持的模型合并提交)
- 配置/路由更改可以与其启用的功能合并提交
- 如果总差异较小(少于 4 个文件且少于 50 行),可以只提交一次
-
每次提交都必须独立有效——不能有损坏的导入,也不能引用尚不存在的代码。按依赖顺序安排提交,先提交依赖项。
-
编写每次提交的说明:
- 第一行:
<type>: <summary>(type = feat/fix/chore/refactor/docs) - 正文:简要说明此提交包含的内容
- 只有最后一次提交(VERSION + CHANGELOG)需要版本标签和共同作者署名:
- 第一行:
git commit -m "$(cat <<'EOF'
chore: bump version and changelog (vX.Y.Z.W)
Co-Authored-By: Codex Opus 4.6 <[email protected]>
EOF
)"
步骤 7:推送
推送到远程仓库并设置上游跟踪:
git push -u origin <branch-name>
步骤 8:创建 PR
使用 gh 创建拉取请求:
gh pr create --title "<type>: <summary>" --body "$(cat <<'EOF'
## Summary
<bullet points from CHANGELOG>
## Pre-Landing Review
<findings from Step 3.5, or "No issues found.">
## Eval Results
<If evals ran: suite names, pass/fail counts, cost dashboard summary. If skipped: "No prompt-related files changed — evals skipped.">
## Test plan
- [x] All Rails tests pass (N runs, 0 failures)
- [x] All Vitest tests pass (N tests)
EOF
)"
输出 PR URL——这应该是用户看到的最终输出。
重要规则
- 绝不跳过测试。 如果测试失败,请停止。
- 绝不跳过提交前审查。 如果无法读取 checklist.md,请停止。
- 绝不强制推送。 只能使用常规
git push。 - 除非涉及 MINOR/MAJOR 版本升级或 CRITICAL 审查发现,否则绝不询问确认(针对每项严重问题,只向用户提出一个直接问题,并提供修复建议)。
- 始终使用 VERSION 文件中的 4 位版本格式。
- CHANGELOG 中的日期格式:
YYYY-MM-DD - 拆分提交以支持二分定位——每次提交对应一项逻辑更改。
- 目标是:用户说
ship后,接下来看到的就是审查结果和 PR URL。