mcpField
S
ship

ship

github.com/borkweb开发846 次安装2 天前更新
代码仓库

关于 ship

ship 是一套自动化工作流,可将功能分支变更依次送审、测试、提交,更新发布元数据并创建拉取请求。它会把变更整理成便于二分定位的提交,并在测试失败或需要人工判断时暂停。

主要功能

  1. 01测试前合并基准分支
  2. 02运行项目测试与合并前审查
  3. 03自动修复符合条件的审查问题
  4. 04将变更整理为便于二分的提交
  5. 05按需更新版本与变更日志
  6. 06准备拉取请求

适用场景

  1. 01将功能分支变更发布为拉取请求
  2. 02在合并前运行检查和代码审查
  3. 03把大型变更拆分为逻辑提交

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/borkweb/skills --skill ship

安装后在 Claude Code 中输入/ship确认已加载。

详细介绍

步骤 0:检测基础分支

确定此 PR 的目标分支。后续所有步骤中都将其称为“基础分支”。

运行共享辅助程序:

BASE=$(bash "$CLAUDE_PLUGIN_ROOT/scripts/detect-base-branch.sh")

该辅助程序依次检查当前 PR 的 baseRefName、仓库的默认分支,然后回退到 main。它始终会输出一个可用的分支名称。


Ship:全自动 Ship 工作流

你正在运行 /ship 工作流。这是一个非交互式、全自动工作流。任何步骤都不要请求确认。用户输入了 /ship,这就意味着立即执行。直接运行完整流程,并在最后输出 PR URL。

仅在以下情况停止:

  • 当前处于基础分支(中止)
  • 存在无法自动解决的合并冲突(停止并显示冲突)
  • 测试失败(停止并显示失败情况)
  • 合并前审查发现需要用户判断的 ASK 项
  • 需要进行 MINOR 或 MAJOR 版本升级(询问 — 参见步骤 5)

绝不要因以下情况停止:

  • 存在未提交的更改(始终包含这些更改)
  • 选择版本升级类型(自动选择 MICRO 或 PATCH — 参见步骤 5)
  • CHANGELOG 内容(根据提交自动生成)
  • 提交消息审批(自动提交)
  • 多文件变更集(自动拆分为可二分排查的提交)
  • 检测到 TODOS.md 中已完成的条目(自动标记)
  • 可自动修复的审查结果(死代码、N+1、过时注释 — 自动修复)

步骤 1:起飞前检查

  1. 检查当前分支。如果处于基础分支,中止:“你当前处于基础分支。请从功能分支执行 Ship。”

  2. 运行 git status(绝不要使用 -uall)。始终包含未提交的更改 — 无需询问。

  3. 运行 git diff <base>...HEAD --stat 和 git log <base>..HEAD --oneline,了解即将发布的内容。

  4. 检测关联的问题。 扫描以下位置中的问题引用:

    • 分支名称(例如,fix/123-broken-login、feature/GH-45)
    • 提交消息(Fixes #123、Closes #45、Relates to #78)
    • 引用了问题的 TODOS.md 条目 收集所有问题编号 — 在步骤 9 中将其写入 PR 正文。

故障恢复: 如果 git status 或 git log 失败(例如,索引损坏),运行 git fsck 并报告结果。不要继续。


步骤 2:合并基础分支(在测试之前)

获取基础分支并将其合并到功能分支,以便针对合并后的状态运行测试:

git fetch origin <base> && git merge origin/<base> --no-edit

如果存在合并冲突: 如果冲突简单(VERSION、schema、CHANGELOG 排序),尝试自动解决。如果冲突复杂或含糊不清,停止并显示冲突。

如果已是最新状态: 静默继续。

故障恢复: 如果 git fetch 失败(网络、身份验证),报告错误并停止。如果 git merge 因冲突以外的原因失败(例如,历史记录不相关),报告错误并停止。


步骤 3:运行测试(针对合并后的代码)

根据代码库检测项目的测试命令(package.json 脚本、Makefile、Gemfile 等),并运行该命令。

如果有任何测试失败: 显示失败情况并停止。不要继续。

如果全部通过: 静默继续 — 简要记录测试数量即可。

故障恢复: 如果测试运行器本身无法执行(缺少依赖、配置错误),清楚地报告错误。不要将“运行器崩溃”视为“测试通过”。


步骤 3.5:合并前审查(委托给审查技能)

根据 /review 技能的检查清单进行审查,不要重复实现其逻辑。

  1. 从审查技能目录中读取 checklist.md(skills/gstack/review/checklist.md)。如果未找到,则停止并报告。

  2. 从审查技能目录中读取 design-checklist.md(skills/gstack/review/design-checklist.md)。留待步骤 3.5.4 使用。

  3. 运行 git diff origin/<base> 获取完整差异。

  4. 按照检查清单分两轮审查:

    • 第 1 轮(严重问题): SQL 与数据安全、迁移与架构安全、竞态条件与并发、身份验证与权限缺陷、大模型输出信任边界、枚举与值完整性、API 契约破坏性变更
    • 第 2 轮(提示性问题): 错误处理反模式、条件副作用、魔法数字与字符串耦合、无用代码与一致性、大模型提示词问题、测试缺口、加密与熵、时间窗口安全、边界处的类型强制转换、视图/前端、性能与打包影响
  5. 检查前端变更:

    bash "$CLAUDE_PLUGIN_ROOT/scripts/detect-frontend-files.sh" "$BASE"
    

    如果有文件输出,则应用设计检查清单(在步骤 2 中加载)。先检查仓库根目录中的 DESIGN.md——其中认可的模式不会被标记。

  6. 根据检查清单中的 Fix-First 启发式,将每项发现归类为 AUTO-FIX 或 ASK。严重问题倾向于 ASK;提示性问题倾向于 AUTO-FIX。

  7. 自动修复所有 AUTO-FIX 项。 每项修复输出一行: [AUTO-FIXED] [file:line] 问题 → 采取的措施

  8. 如果仍有 ASK 项, 则在一个 AskUserQuestion 中列出:

    • 每项注明编号、严重程度、问题和建议修复方案
    • 每项提供选项:A) 修复 B) 跳过
    • 总体建议
  9. 所有修复(自动修复和用户批准的修复)完成后:

    • 如果应用了任何修复:提交已修复的文件,然后在继续前重新运行测试。
    • 如果没有应用任何修复:继续步骤 4。
  10. 输出摘要:合并前审查:N 个问题 — M 个自动修复,K 个待询问(J 个已修复,L 个已跳过)

保存审查输出——该内容将在步骤 9 中写入 PR 正文。


步骤 3.7:对抗性审查

当差异符合以下任一条件时,通过 Agent 工具派遣一名对抗性审查员:

  • 更改超过 200 行
  • 涉及身份验证、支付或安全相关文件
  • 引入新的外部服务集成
  • 包含新的加密操作或机密信息处理

对于少于 200 行且不涉及敏感文件的差异,跳过此步骤。

子代理提示词: “使用 git diff origin/<base> 阅读此分支的差异。像攻击者和混沌工程师一样思考。你的任务是找出这段代码在生产环境中可能发生故障的方式。检查:边缘情况、竞态条件、安全漏洞、资源泄漏、故障模式、静默数据损坏、会静默地产生错误结果的逻辑错误、吞掉故障的错误处理,以及信任边界违规。采取对抗性视角。务必全面。不要称赞——只指出问题。对于每项发现,将其归类为 FIXABLE(你知道如何修复)或 INVESTIGATE(需要人工判断)。”

呈现审查发现。FIXABLE 发现进入 Fix-First 流程(自动修复;如果代码有更改,则重新运行测试)。INVESTIGATE 发现仅作提示。

保存对抗性审查输出——该内容将在步骤 9 中写入 PR 正文。


第 4 步:提交(可二分定位的代码块)

目标: 创建小型、逻辑清晰的提交,让 git bisect 能够顺利工作。

  1. 将更改分组为逻辑提交。每个提交应包含一项连贯的更改。

  2. 提交顺序——默认采用以下顺序,并根据项目结构调整:

    • **先提交基础更改:**迁移、配置、架构、路由、依赖项
    • **接着提交核心逻辑:**模型、服务、库(及其测试)
    • **最后提交表层更改:**控制器、视图、CLI 命令(及其测试)
    • **元数据始终最后提交:**在最后一次提交中包含 VERSION + CHANGELOG + TODOS.md

    对于库或 CLI 工具,可调整顺序:核心 API → 内部模块 → 公共接口 → 元数据。 对于 monorepo,按软件包而不是按层分组。

  3. 规则:

    • 模块/服务及其测试应放在同一次提交中
    • 如果总 diff 较小(跨 < 4 个文件且少于 50 行),可以只创建一次提交
    • 每次提交都必须独立有效——不能有损坏的导入
  4. 撰写提交消息:<type>: <summary>(feat/fix/chore/refactor/docs)


第 5 步:版本升级(自动决定)

如果存在 VERSION 文件:

  1. 读取当前版本。

  2. 根据更改内容而非更改数量自动决定升级级别:

    MICRO(自动)——仅内部更改:

    • Bug 修复、拼写错误、注释更新、仅涉及测试的更改
    • 不改变公共 API 或行为的重构
    • 文档更新

    PATCH(自动)——面向用户但不具破坏性的更改:

    • 会改变可观察行为的 Bug 修复
    • 性能改进
    • 带默认值的新可选参数
    • 依赖项更新

    MINOR(询问)——新增能力:

    • 新端点、命令、功能或公共 API 方法
    • 新数据库表或重要的架构新增内容
    • 新的外部服务集成

    MAJOR(询问)——破坏性更改:

    • 删除或重命名公共 API 方法/端点
    • 更改响应格式或必需参数
    • 需要进行数据转换的数据库迁移
    • 停止支持某个运行时/平台
  3. 计算并写入新版本。

如果不存在 VERSION 文件,则跳过此步骤。


第 6 步:CHANGELOG(自动生成)

如果存在 CHANGELOG.md:

  1. 阅读文件头以了解格式。

  2. 使用第 4 步中的提交消息作为主要依据,自动生成条目:

    • 前缀为 feat: 的提交 → ### Added
    • 前缀为 fix: 的提交 → ### Fixed
    • 前缀为 refactor: / chore: 的提交 → ### Changed
    • 删除功能的提交 → ### Removed
    • 对未分类的更改,通过 diff 分析补充分类
    • 编写简洁、描述清晰的项目符号条目
    • 在文件头之后插入条目,日期使用今天

**不要询问用户描述更改内容。**根据提交和 diff 推断。

如果不存在 CHANGELOG.md,则跳过此步骤。


第 6.5 步:TODOS.md(自动更新)

如果存在 TODOS.md:

  1. 将 diff 与未完成的 TODO 逐项对照
  2. 自动标记已完成的项目——仅当 diff 明确表明工作已完成时才标记(谨慎判断)
  3. 将已完成项目移至 Completed 部分,并注明版本和日期
  4. 输出摘要:TODOS.md: N 项已标记为完成。M 项仍未完成。

如果不存在 TODOS.md,则静默跳过。


第 6.7 步:计划完成情况审查

如果此分支存在计划文件,请核实计划中的所有内容是否都已交付。如果未找到计划文件,则静默跳过。

计划文件发现
  1. 对话上下文(优先): 如果宿主 Agent 的系统消息中提到了计划文件路径,请直接使用该路径。
  2. 文件系统搜索(备用): 在 docs/plans/、docs/designs/、.claude/plans/ 和项目根目录中查找与当前分支名称匹配的 Markdown 文件。选择最近修改的匹配文件。如果有多个候选文件且没有明确匹配项,则视为“未找到计划文件”。
  3. 验证: 读取前 20 行。如果内容看起来与当前分支的工作无关,则视为“未找到计划文件”。

如果未找到计划文件: 跳过并输出“未检测到计划文件 — 跳过计划完成情况审查。”继续执行步骤 7。

作为子 Agent 分派

使用 Agent 工具,并将 subagent_type 设为 "general-purpose"。子 Agent 在全新上下文中读取计划和差异;父 Agent 获取结论。子 Agent 提示词:

审查当前分支的计划完成情况。基准分支:<base>。计划文件:<path>。

提取可执行项,包括复选框(- [ ] / - [x])、编号实现步骤、祈使句(“添加 X”“创建 Y”)、文件级规范和测试要求、数据模型变更。最多 50 项。忽略背景/概述/问题部分、开放问题(“TBD”“TODO: decide”)、明确推迟的事项(“Out of scope:”“Future:”“P2:”“P3:”)以及以往的审查报告。

对每项进行分类,判断如何验证:

  • DIFF-VERIFIABLE — 在此仓库的 git diff <base>...HEAD 中应能看到。
  • CROSS-REPO — 指向同级仓库中的文件。如果路径可访问,尝试执行 [ -f <path> ];如果不可访问,则标为 UNVERIFIABLE。
  • EXTERNAL-STATE — 指向外部系统中的状态(DNS、OAuth 允许列表、SaaS 配置)。始终标为 UNVERIFIABLE。
  • CONTENT-SHAPE — 文件必须符合特定规范。在标为 UNVERIFIABLE 之前,先运行项目验证工具(validate-*、lint-docs 等)。

路径具体性规则: 如果计划项指定了具体文件系统路径,则必须根据 [ -f <path> ] 标记为 DONE 或 NOT DONE。只有路径确实抽象或无法访问时,才可标为 UNVERIFIABLE。

每项的状态:

  • DONE — 差异或文件系统中有明确证据。注明文件。
  • PARTIAL — 已完成部分工作,但尚未完成。
  • NOT DONE — 验证已执行,且得到了否定证据。
  • CHANGED — 以不同方式实现,但达成了相同目标;注明差异。
  • UNVERIFIABLE — 无法证实或证伪。注明具体的人工检查项。

诚信规则: 处理某项交付内容的代码,并不等于交付内容本身。提供 Markdown 提取库,不等于提供 Markdown 文件。如无法确定是 DONE 还是 UNVERIFIABLE,优先选择 UNVERIFIABLE。

按类别(Implementation / Tests / Migrations / Cross-Repo / External)分组,输出 Markdown 检查清单,并为每项添加 [STATUS] 前缀。最后用一行总结:COMPLETION: X/Y DONE, A PARTIAL, B NOT DONE, C CHANGED, D UNVERIFIABLE。

门控逻辑

子 Agent 返回后,按优先级顺序评估:

  1. 任何 NOT DONE 项(已知尚未完成的工作)。使用 AskUserQuestion:

    • 显示完成检查清单。
    • “计划中有 {N} 项尚未完成(NOT DONE)。”
    • 选项:A) 停止 — 在发布前完成实现。B) 仍然发布 — 作为 P1 TODO 延后处理。C) 有意移除 — 从范围中删除。
    • 建议:核心功能缺失时选 A;文档/配置的小问题选 B。
    • 选 A:停止。选 B:继续,对每项将 Deferred from plan: {path} 追加到 TODOS.md。选 C:继续,在 PR 正文中注明。
  2. 任何 UNVERIFIABLE 项(仅在 NOT DONE 项已解决或不存在后处理)。必须逐项确认 — 不得一揽子确认。 逐项循环:

    • 对每项使用 AskUserQuestion,询问该项的具体手动检查(“确认:~/path/to/file 是否存在?”,而不是“是否已检查所有项目?”)。
    • 每项选项:Y) 确认已完成 — 引用你验证过的内容(自由文本)。N) 尚未完成 — 阻止发布,返回优先级 1。D) 有意移除。
    • 任何一项选 N:停止。全部选 Y 或 D:继续,在 PR 正文中加入 ## Plan Completion — Manual Verifications,列出每项选 Y 的证据,并将每项选 D 标记为已移除。
    • 上限: 如果 UNVERIFIABLE 项超过 5 项,先将它们列出并询问:(1) 逐项确认 [推荐];(2) 停止并缩小范围;(3) 明确接受一揽子确认(警告:这正是此门控要防止的失败模式)。
  3. 仅有 PARTIAL 项(没有 NOT DONE 或 UNVERIFIABLE): 继续,并在 PR 正文中注明。不阻止发布。

  4. 全部为 DONE 或 CHANGED: 通过。继续。

子 Agent 失败时默认拒绝通过

如果子 Agent 失败或返回格式错误的输出,不要默默放行。尝试在父上下文中直接运行提取一次。如果仍然失败,则通过 AskUserQuestion 呈现:

“无法运行计划完成情况审计({reason})。选项:A) 跳过审计并仍然发布 — 在 PR 正文中记录已跳过审计。B) 停止并修复审计。”

建议:B。默默地默认放行正是此门控要防止的失败模式。

PR 正文

在第 9 步的 PR 正文中添加 ## Plan Completion 部分,并附上检查清单摘要。如果通过逐项流程确认了 UNVERIFIABLE 项,还要添加 ## Plan Completion — Manual Verifications,列出每项确认。


Step 7: 验证门控

绝对原则:没有最新的验证证据,不得声称已完成。

推送前,如果代码在第 4 至 6.5 步期间发生过更改,请重新验证:

  1. 如果第 3 步运行测试后有任何代码更改(例如评审修复),请重新运行测试。粘贴最新输出。
  2. 如果项目有构建步骤,请运行构建。
  3. 如果测试失败: 停止。不要推送。

Step 8: 推送

git push -u origin <branch-name>

恢复处理: 如果推送失败:

  • 分支保护/pre-receive hook 拒绝: 报告错误。不要强制推送。说明用户需要解决的问题(例如所需的评审者、状态检查)。
  • 身份验证失败: 报告并停止。
  • 远程分支分叉(非快进): 报告并停止。不要强制推送。建议运行 git pull --rebase origin <branch-name>,然后重新验证。

Step 9: 创建 PR

Step 9.1: 检测 PR 元数据
  1. 标签: 检查仓库的标签惯例:

    gh label list --limit 20 --json name --jq '.[].name'
    

    自动应用与更改类型匹配的标签:

    • 修复类提交使用 bug / bugfix
    • 新功能类提交使用 enhancement / feature
    • 锁文件有更改时使用 dependencies
    • 如果仓库使用规模标签,则按差异行数应用(S/M/L) 如果没有匹配的标签,则跳过 — 不要创建新标签。
  2. 评审者: 检查 CODEOWNERS:

    cat .github/CODEOWNERS 2>/dev/null || cat CODEOWNERS 2>/dev/null
    

    如果存在 CODEOWNERS,让 GitHub 自动分配评审者。否则,跳过评审者分配。

  3. 草稿模式: 如果符合以下任一条件,则以草稿形式创建(--draft):

    • 分支名称以 wip/ 或 draft/ 开头
    • 任意提交消息包含 [WIP] 或 [DRAFT]
    • TODOS.md 中有与此分支工作相关且标记为进行中的项目
第 9.2 步:创建 PR
gh pr create --base <base> \
  --title "<type>: <summary>" \
  [--draft] \
  [--label "<label1>" --label "<label2>"] \
  --body "$(cat <<'EOF'
## Summary
<bullet points from CHANGELOG or diff summary>

<If linked issues were detected in Step 1:>
Closes #<issue>
<or>
Relates to #<issue>

## Pre-Landing Review
<findings from Step 3.5, or "No issues found.">

<If adversarial review was run in Step 3.7:>
## Adversarial Review
<INVESTIGATE findings, or "No issues found.">
<FIXABLE findings that were applied are noted as resolved.>

## TODOS
<completed items, or "No TODO items completed in this PR.">

<If Step 6.7 ran:>
## Plan Completion
<checklist summary from Step 6.7, or "No plan file detected.">

<If UNVERIFIABLE items were confirmed via per-item flow:>
## Plan Completion — Manual Verifications
<each Y'd item with user evidence; each D'd item marked "intentionally dropped">

## Test plan
- [x] All tests pass
- [x] Verification gate passed

🤖 Generated with [Claude Code](https://claude.com/claude-code)
EOF
)"

输出 PR URL。

**恢复方法:**如果 gh pr create 失败:

  • **PR 已存在:**运行 gh pr view --json url --jq .url,并输出现有 URL。主动提出更新现有 PR 正文。
  • **缺少权限:**报告情况并停止。
  • **网络错误:**重试一次。如果仍然失败,报告情况并停止。代码已推送——用户可以手动创建 PR。

重要规则

  • **绝不跳过测试。**如果测试失败,停止。
  • **绝不强制推送。**仅使用常规 git push。
  • 绝不询问无关紧要的确认事项(例如“准备好推送了吗?”“创建 PR 吗?”)。但以下情况必须停止:版本升级(MINOR/MAJOR)以及上线前审核中的 ASK 项。
  • 将提交拆分,以便进行二分排查——每个提交对应一项逻辑变更。
  • **必须保守地判断 TOD​​OS.md 中任务是否完成。**仅当差异明确显示任务已完成时,才将其标记为完成。
  • **没有最新的验证证据,绝不推送。**如果第 3 步之后代码有变更,推送前必须重新运行验证。
  • **优先恢复,而非放弃。**每个步骤都包含恢复指南。放弃前应遵循指南。
  • 目标是:用户输入 /ship 后,接下来看到的就是 PR URL。

评论

支持 Markdown