发布 simctlhouse
发布此仓库的 X.Y.Z 版本:包含已公证的 tarball 的 GitHub Release,以及 tap 中的公式。
scripts/release.sh 负责构建、签名、公证和打包;此技能负责围绕它的所有操作。
docs/how-to.md(“制作一个发布”)和 docs/decisions.md 中的 D27 解释了设计。
固定名称:
| 什么 | 值 |
|---|---|
| GitHub 仓库 | juraj-blahunka/simctlhouse(远程 origin) |
| Tap 检出 | ../homebrew-tap,GitHub juraj-blahunka/homebrew-tap,用作 juraj-blahunka/tap |
| Tap 中的公式 | Formula/simctlhouse.rb |
| 标签 | vX.Y.Z |
| Tarball | dist/simctlhouse-X.Y.Z-macos.tar.gz |
| 发布说明 | dist/release-notes-X.Y.Z.md(dist/ 被 git 忽略) |
除非步骤另有说明,否则从仓库根目录运行每条命令。
在第一次失败时停止,报告失败的内容及其输出,不要绕过去(不要使用 --skip-notarize、--allow-dirty、--force 或 --no-verify)。
1. 选择版本
使用用户给出的版本。
否则,提出一个版本并询问:用 git log --oneline $(git describe --tags --abbrev=0 2>/dev/null)..HEAD(如果没有标签,则列出所有提交)列出自上一个标签以来的变更,然后为 feat: 提交增加次要版本,只为修复增加补丁版本。
2. 检查前置条件
在更改任何内容之前检查所有这些,并一次性报告所有失败:
git rev-parse --abbrev-ref HEAD # main
git status --porcelain --untracked-files=no # 空
git fetch origin && git status -sb | head -1 # 不落后于 origin/main
git ls-remote --tags origin "refs/tags/vX.Y.Z" # 空:版本尚未发布
gh auth status # 已登录
git -C ../homebrew-tap status --porcelain # tap 存在且干净
git -C ../homebrew-tap pull --ff-only # tap 是最新的
如果 origin 或 tap 缺失,请停下来告诉用户要创建什么;永远不要自己创建 GitHub 仓库。
一个新的 tap 需要 GitHub 仓库 juraj-blahunka/homebrew-tap,克隆到 ../homebrew-tap,并包含一个 Formula/ 目录。
3. 提升版本号
如果 Sources/simctlhouse/SimctlHouse.swift 中的 version: 不是 X.Y.Z,在那里更改它,运行 swift build 和 swift test,并只提交该文件:
git commit -m "chore: release X.Y.Z" Sources/simctlhouse/SimctlHouse.swift
4. 与用户一起编写发布说明
根据自上一个版本以来的变更起草说明:
git log --format='%h %s%n%b' $(git describe --tags --abbrev=0 2>/dev/null)..HEAD
git diff --stat $(git describe --tags --abbrev=0 2>/dev/null)..HEAD
阅读提交,并在主题不明确时阅读 diff 本身;说明描述的是 CLI 和技能的用户会注意到什么,而不是代码如何变化。
-
以一两条句子开头,说明发布是关于什么的。
-
然后是章节,留出空章节:
## 新增,## 变更,## 修复,以及如果有任何破坏脚本或代理的内容(重命名的命令或标志、改变的输出、改变的退出码),首先写## 破坏性变更。 -
每个变更一个要点,命令或标志用反引号括起来,例如
simctlhouse skill install。 -
除非用户会注意到,否则省略
chore:、refactor:、test:和仅文档的提交。 -
以如何获取它结束,完全像这样:
## 安装 ```sh brew install juraj-blahunka/tap/simctlhouse # 或:brew upgrade simctlhouse simctlhouse skill install # 一次,链接代理技能 ```
将草稿写入 dist/release-notes-X.Y.Z.md 并向用户显示全文。
要求他们接受或说出要更改的内容;将他们的更改应用到文件并再次显示整个文本。
重复直到他们明确接受,并且在构建之前不要继续。
该文件是按原样发布的,因此它不得包含任何针对用户的内容,例如问题或待办事项。
5. 构建发布版本
scripts/release.sh X.Y.Z
这需要几分钟,大部分时间是在等待 Apple 的公证;允许最多 10 分钟。
如果版本不匹配、源未提交或标签指向其他地方,它会拒绝运行,运行测试和 lint,通过 scripts/build.sh 构建,检查 Apple 是否发布了公证票据,并验证自己的 tarball。
它结束时打印 tarball 路径、其 sha256 以及 dist/simctlhouse.rb。
6. 冒烟测试 tarball
针对真实模拟器运行您即将发布的精确字节:
scripts/smoke-test.sh dist/simctlhouse-X.Y.Z-macos.tar.gz
它将 tarball 解压到临时目录,在那里链接技能,在临时 SIMCTLHOUSE_HOME 中获取一个设备,检查守护进程是否已启动并且可以停止并重新启动,释放设备并等待守护进程关闭它并自行退出,删除它,并检查之前存在的每个模拟器是否仍然存在。
首次启动大约需要 30 秒;在负载较重的机器上允许最多 5 分钟。
如果报告缺少模拟器,则向用户显示列表:其他代理可能同时删除了它们自己的设备,只有用户能判断。
7. 发布前确认
从这里开始,一切都是公开的,很难撤销。
向用户显示版本、提交(git log --oneline -1)、sha256、冒烟测试结果、已接受的发布说明文件以及以下步骤,并等待明确的批准。
8. 发布
按此顺序,以便每个已发布的步骤都指向已经存在的内容:
git push origin main
git tag -a vX.Y.Z -m "simctlhouse X.Y.Z"
git push origin vX.Y.Z
gh release create vX.Y.Z dist/simctlhouse-X.Y.Z-macos.tar.gz \
--repo juraj-blahunka/simctlhouse --verify-tag --title "simctlhouse X.Y.Z" --notes-file dist/release-notes-X.Y.Z.md
检查上传的 tarball 是否是公式所描述的;不匹配意味着 scripts/release.sh 在上传之后再次运行:
gh release download vX.Y.Z --repo juraj-blahunka/simctlhouse --pattern '*.tar.gz' --output - | shasum -a 256
grep sha256 dist/simctlhouse.rb
然后发布公式:
mkdir -p ../homebrew-tap/Formula
cp dist/simctlhouse.rb ../homebrew-tap/Formula/simctlhouse.rb
git -C ../homebrew-tap add Formula/simctlhouse.rb
git -C ../homebrew-tap commit -m "simctlhouse X.Y.Z"
git -C ../homebrew-tap push
9. 通过 Homebrew 验证
推送会启动 tap 的 tests 工作流,该工作流审核公式,在干净的 macOS 15 和 26 机器上安装它,并运行其 test 块。
这是用户获取之前对已发布公式的唯一真正安装,因此请等待它通过:
commit="$(git -C ../homebrew-tap rev-parse HEAD)"
gh run list --repo juraj-blahunka/homebrew-tap --commit "$commit" --json databaseId,url # 推送后几秒钟内为空
gh run watch <databaseId> --repo juraj-blahunka/homebrew-tap --exit-status
然后从这台机器检查公式。
Homebrew 拒绝从未被信任的 tap 加载公式,即使对于 brew info 也是如此,所以首先信任这一个公式;这会更改用户的 Homebrew 配置,就像 brew install juraj-blahunka/tap/simctlhouse 会做的那样。
其余操作只读取和下载;它不安装任何内容:
brew tap juraj-blahunka/tap 2>/dev/null; brew update
brew trust --formula juraj-blahunka/tap/simctlhouse
brew info juraj-blahunka/tap/simctlhouse # 显示 X.Y.Z
brew fetch --force juraj-blahunka/tap/simctlhouse # 下载并检查 sha256
brew audit --strict --online juraj-blahunka/tap/simctlhouse
如果用户已经安装了来自 tap 的 simctlhouse,则提供 brew upgrade simctlhouse,然后执行 simctlhouse --version 和 simctlhouse skill status。
10. 报告
向用户提供发布 URL(gh release view vX.Y.Z --repo juraj-blahunka/simctlhouse --json url -q .url)、tap 提交、其通过的 tests 运行的 URL 以及安装命令 brew install juraj-blahunka/tap/simctlhouse。
从失败的发布中恢复
- 步骤 8 之前的失败:没有公开任何内容。修复原因并重新开始;重新运行
scripts/release.sh没问题。 - 标签已推送,Release 缺失:重新运行
gh release create步骤。 - Release 已创建,tap 未更新:重新运行 tap 步骤。
- tap 的
tests运行失败:向用户显示失败步骤的日志(gh run view <databaseId> --repo juraj-blahunka/homebrew-tap --log-failed),因为现在安装的用户会遇到相同的失败。 通过一个新的 tap 提交向前修复;永远不要强制推送 tap,因为用户的brew update会拉取它。 - 发布后需要修复说明:与用户一起编辑
dist/release-notes-X.Y.Z.md,然后执行gh release edit vX.Y.Z --repo juraj-blahunka/simctlhouse --notes-file dist/release-notes-X.Y.Z.md。 - 永远不要为已上传 tarball 的版本重新运行
scripts/release.sh,因为每次构建都有一个新的 sha256。 要替换一个损坏的上传,首先询问用户,然后使用gh release upload vX.Y.Z <tarball> --clobber上传新构建的 tarball 并发布匹配的公式。 - 未经用户明确批准,永远不要删除或移动已推送的标签或已发布的 Release。