shipit-skill — 开发者工具的一键发布流水线 是做什么的?
将现有仓库从「能用」推进到已发布 + 已收录 + 可推广。 四个阶段,每个都有严格的退出标准。允许跳过已满足退出标准的阶段。
理念:先侦察后构建。 先检查现有工具和生态要求——就像你建议任何用户不要重复造轮子一样。
阶段 0 — 侦察(30 秒,始终执行)
在动手前运行这些检查:
- 现有仓库状态 —
git status、git remote -v、最近的git log。 - 包注册状态 — 包名是否已被占用?(
pip index versions <name>、npm view <name>、registry CDN)。命名冲突很常见;对于 npm,使用作用域名(@org/pkg)可以规避抢注规则。 - 类似项目 — 在 GitHub 上搜索直接竞争对手。如果存在,明确说明差异点;不要构建一个复制品。
- 退出标准差距 — CI?Dockerfile?GitHub Release?已在 Glama / awesome 目录中列出?推广材料最新?构建一个缺失项的检查清单。该清单驱动其余阶段。
输出:一份简短的差距报告 + 计划。如果差距很大,请在阶段 1 之前获得确认。
阶段 1 — 工程基线
退出标准:默认分支上 CI 绿色通过,包元数据正确,Dockerfile 存在(如果是 MCP/CLI 服务器)。
- CI:添加 GitHub Actions。Python:在支持的版本上运行矩阵测试,但注意需要较新解释器的额外依赖(例如
mcp>=2.0需要 py3.10+——基础版本在 3.9 上运行,额外依赖在 3.12 上运行)。如果提供了服务器,始终包含 lint + 测试 + 容器 MCP 握手作业。 - Dockerfile:为 Glama 和容器用户准备。对于 stdio MCP 服务器:基础镜像 + 安装包 +
CMD [the-server-command]。从源码构建(COPY src),除非已发布的包经验证是好的——过时的 PyPI/npm 版本会静默破坏内省。 .dockerignore:保持镜像最小(无.git、测试、推广材料、文档)。- 从元数据获取版本:MCP
serverInfo.version和 CLI--version必须读取包版本,而不是硬编码字符串。 - 依赖下限:如果你的代码使用了新的 SDK API,请设置依赖下限(如
mcp>=2.0),不要保留>=1.0——pip/npm 会解析到最新版本并破坏新的安装。
验证:在临时虚拟环境中执行干净的 pip install .[extras] / npm install,然后针对容器运行 MCP 握手(initialize + tools/list)。
阶段 2 — 发布
退出标准:包已在注册表上,带有标签+说明的 GitHub Release,干净环境安装已验证。
- 版本提升 → 构建产物(
python -m build/npm pack)。 - 标签 + GitHub Release:标题为
vX.Y.Z,说明包含变更 / 安装 / 修复内容。使用gh release create从标签创建。 - 注册表发布:
- PyPI:需要令牌(粒度化,限定给该包,上传权限)。如果令牌格式错误,PyPI 返回
403 Invalid or non-existent authentication information——UUID 风格的字符串是错误的;真正的 PyPI 令牌以pypi-开头。twine upload使用--username __token__。 - npm:作用域名需要先存在该组织;自动化需要粒度化令牌并且绕过 2FA;
--//registry.npmjs.org/:_authToken内联方式避免将凭据写入磁盘。
- PyPI:需要令牌(粒度化,限定给该包,上传权限)。如果令牌格式错误,PyPI 返回
- 新装验证(不可协商):创建一个虚拟环境 / 干净目录,从注册表安装,导入模块 / 运行 CLI / 执行 MCP 握手。这能捕获“在我机器上能跑”的打包错误。
- 注意事项:
- npm CDN 在首次发布后几分钟内提供缓存的 404——不要惊慌,使用查询参数缓存清除。
- 重试时出现
File already exists通常意味着第一次尝试已成功。 - 锁文件漂移:重命名包 → 始终运行
npm install重新生成锁文件,否则npm ci会在 CI 中失败。
阶段 3 — 目录收录
退出标准:已在 Glama 上列出并带有评分徽章,且 awesome 的 PR 已打开(或已合并)。
- Glama(
glama.ai/mcp/servers):用户通过浏览器提交(GitHub OAuth——无法自动化)。提交前:Dockerfile 必须存在并通过内省(参见阶段 1)。提交后:页面需要数分钟到数小时才能出现——轮询https://glama.ai/mcp/servers/<owner>/<repo>和/badges/score.svg。上线后,将徽章添加到仓库的 README 中:[](https://glama.ai/mcp/servers/owner/repo) - awesome-mcp-servers(以及类似的精选列表):PR 由机器人审核。按照列表当前的格式约定(徽章 + 语言 + 范围 + 操作系统 + 安装命令)。维护者现在要求条目中包含 Glama 徽章——先提交 Glama。在 PR 标题中添加
🤖🤖🤖以选择加入代理快速通道。Fork → 基于最新的上游主分支创建分支 → 添加条目 → 发起 PR。如果之前的 PR 因不活跃而被关闭,请 force-push 该分支或重新创建它。 - 其他目录(Smithery、PulseMCP、mcp.so 等):Smithery 会在仓库根目录读取
smithery.yaml(stdio 启动命令 + 可选的 env 模式)。
阶段 4 — 推广材料
退出标准:推广文档的版本/链接/PR 编号与现实一致;各平台的帖子已准备好粘贴(用户手动发布——不要虚假自动化)。
- 维护
promo/目录,其中包含针对每个平台的文件(V2EX、知乎、Reddit、X、社区)。 - 新鲜度检查(每当版本/PR 变化时运行):在推广文件中搜索旧的版本号、失效的 PR 链接、过时的发布 URL。更新或标记为过时。
- 事实纪律:在发布前验证每一个数字/声明——重新运行工具并比较输出。错误的声明会在评论区被撕碎(例如,一个“没有 LICENSE”的声明实际上只是 GitHub 元数据的一个小问题)。
- 保持安装命令不锁定版本(
pip install pkg),这样推广材料不会过时。
CLI 快速参考(shipit-skill)
运行这些命令来推动仓库通过各个阶段。默认情况下所有操作都是仅打印;有副作用的变体通过 --execute 选择加入。
| 命令 | 作用 | 自动 / 打印 |
|---|---|---|
doctor [--json] | 环境自检:gh 已认证、令牌已设置、主分支干净 | 打印;有差距时退出码为 1 |
preflight [--dir .] [--version X.Y.Z] [--json] | 发布就绪差距报告 | 打印 |
init <dir> --server <srv> --pkg <pkg> [--force] [--dry-run] | 搭建 CI/Dockerfile/smithery.yaml/推广材料 | 写入文件 |
ci --lang python [--server srv] [--write path] [--release] | 生成 ci.yml;--release 生成 release.yml | 打印 / 写入 |
| `bump patch | minor | major |
release --lang python --pkg <pkg> [--repo o/r] [--execute] | doctor 门控 → 提升→构建→发布→标签→gh release→推广检查。标签/发布仅在发布成功后创建;发布失败会回滚提交;重跑会跳过已存在的标签/发布;说明来自 CHANGELOG | 打印 / 执行 |
publish --lang python --pkg <pkg> [--server srv] [--execute] | 注册表上传(令牌来自 PYPI_TOKEN/NPM_TOKEN 环境变量)+ 新装验证 | 打印 / 执行 |
check-promo --dir promo --version X.Y.Z [--prs id=state,...] [--no-links] [--report] [--fix] | 检查过期版本 / 未知 PR / 失效链接;--report 输出 JSON;--fix 重写过期版本并标记未知 PR | 打印 / JSON / 修复 |
check-glama --repo o/r [--poll N] [--add-badge] [--json] | 等待 Glama 列出;--add-badge 在上线时将徽章写入 README;--json 结构输出 | 打印 / 写入 |
awesome-pr --upstream o/r --repo o/r --fork o/r --branch b [--execute --category C --description D --install I] | 打印 PR 配方,或实际进行 fork→编辑→push→gh pr create | 打印 / 执行 |
令牌:永不存储到磁盘。publish/release --execute 从环境变量读取 PYPI_TOKEN 或 NPM_TOKEN;提示用户提供并内联传递。
自动化边界
| 步骤 | 谁执行 |
|---|---|
| CI 文件、Dockerfile、元数据、代码修复 | 代理 |
| 构建产物、新装验证 | 代理 |
| 注册表发布(PyPI/npm) | 代理,使用用户提供的令牌 |
| Glama 浏览器提交 | 用户(OAuth) |
| awesome/其他 PR 创建 | 代理 |
| 在平台上发布 | 用户 |
绝不伪造凭据;明确要求令牌并内联使用,绝不写入文件。
实战经验(来自 wheel-hub + zspace-cli 的发布)
mcp>=1.0在额外依赖中 + 新 SDK → 新安装崩溃。设置下限。- Python 3.9 无法安装
mcp>=2.0;CI 矩阵必须将基础版本与额外依赖分开。 - YAML 块标量 + 内联 python heredoc = 损坏的工作流。使用脚本文件。
- MCP 2.x 的
Server对象没有list_tools——使用@server.tool()装饰器。 - Glama 内省需要在冒烟测试中保持 stdin 打开一瞬(
sleep 1)。 - PyPI 令牌格式:
pypi-...是真的,UUID 格式是错误的。 - npm 抢注阻止了
wheel-hub与wheelhub并存;作用域名有效。 .dockerignore缺失 → 镜像过大 / 构建上下文中包含敏感信息。