发布流程
Verso 会先计算一份准确的文件计划,再记录一系列明确的本地阶段和最后一次远端事务。持久化计划让中断的 发布可以检查和恢复,无需重新计算原本要写入的内容。
写入之前
Verso 会加载一个发布组配置、发现成员、确认成员版本一致、确定一个目标版本,并计算每个文件实际的 before 和 after 内容。完整发布还会计算 changelog、commit message、tag、hook 和原子推送;bump 计划 只包含版本文件修改和版本 hook。
verso --group core --version 2.0.0 --dry-run
verso bump minor --group core --dry-runDry-run 会输出这份准确计划,包括完整文件的 before/after diff,但不会写文件、运行 hook、创建事务日志 或执行会修改 Git 的命令。
真实执行时,Verso 会检查工作区策略和计划路径、拒绝已有目标 tag,并获取仓库事务锁。每个 Git 仓库 同时只能有一个 Verso 事务。
持久化阶段
第一次文件修改确认后,Verso 会把计划和进度存入 Git metadata,并用原子文件替换写入。完整发布阶段为:
planned
-> before_version -> 应用准确文件 -> files-applied -> after_version
-> before_commit -> git add/commit -> committed -> after_commit
-> before_tag -> annotated tag -> tagged -> after_tag
-> before_push -> git push --atomic -> pushed -> after_push
-> 清除事务verso bump 只经过 planned -> files-applied,运行 before_version 和 after_version 后清除事务。它不会
修改 changelog、暂存文件、创建 commit 或 tag,也不会 push。
完整发布在文件、commit、tag 和 push 之前的确认默认都是“是”。目标版本不大于当前版本时,会更早出现
一个默认“否”的确认。--yes 会接受所有确认。
Status、resume 与 abort
verso status [--json]
verso resume [--retry-hook | --skip-hook]
verso abort [--force]status 是只读命令,会输出操作、发布组、阶段、版本对、修改文件数、中断的 hook,以及当前是否仍可
abort。
resume 会先用准确文件内容、HEAD 和 tag 对事务日志进行校准,跳过已完成的 hook 和确认,再从记录的
阶段继续。进程停止时正在运行的 hook 结果未知;应先检查副作用,再明确使用 --retry-hook 或
--skip-hook。
有事务时再次执行会修改仓库的 release 或 bump,Verso 会显示其发布组、版本对和阶段,再提示 resume 或 abort。恢复操作会结束本次调用,不会接着开始用户刚请求的新发布。
abort 很保守:只通过 compare-and-delete 删除 Verso 创建的准确 tag object,只对预期 release commit
做 soft reset,只取消计划路径的暂存,并且只在文件仍等于计划 after 内容时恢复。遇到意外 HEAD、移动
过的 tag 或后来编辑的文件时,它会拒绝覆盖无关工作。release commit 创建后,abort 还会检查固定远端;
若目标 tag 不属于事务,或 branch 已包含 release commit,则拒绝自动回滚。
事务进入 pushed 阶段后禁止 abort,因为无法安全回滚远端 ref。此时应运行 verso resume,完成
after_push 并清除日志。push 一旦开始,即使报告失败也不能 abort。准确的 tag object 与 peeled tag
匹配且固定的远端 branch 等于或包含 release commit 时,resume 会确认成功;tag 缺失且 branch 不是
release commit 时会重试相同的原子推送;ref 不完整或不匹配时会停止并要求手工恢复。resume 始终使用
事务开始时持久化的 push URL;push 开始后即使本地 HEAD 前进,也仍使用持久化 commit 和 tag。
如果用户已经手工修改 ref,或日志已损坏,导致精确恢复不再可行,应先检查仓库和远端,再执行
verso abort --force。该命令只丢弃活动日志,刻意保留文件、commit、tag 与远端 ref 原样,避免自动
回滚掩盖部分发布状态。
错误与取消行为
推送前可明确处理的文件、hook、commit 和 tag 错误会触发 best-effort 本地 abort。release hook 失败时
会先检查固定远端;若无法检查,Verso 会保留事务,而不会假设 hook 没有发布。进程崩溃、用户在后续确认
中取消或状态不明确时会保留事务日志;push 尚未开始时可选择 resume 或 abort。push 失败只允许
resume。
| 停止位置 | 持久化状态与下一步 |
|---|---|
| 第一次文件确认之前 | 没有事务,也没有文件修改 |
| 已写文件 / commit 之前 | 文件保持未暂存;resume 会提交,abort 会恢复 |
| 已有 commit / tag 之前 | 保留预期 release commit;resume 会加 tag,abort 会 soft reset 并恢复 |
| 已有 tag / push 之前 | 保留本地 commit 和 tag;resume 会推送,abort 会删除预期的本地修改 |
| 原子推送失败 | 保留本地 commit、tag 和日志;修复或检查远端后 resume |
推送成功 / after_push 失败 | 保留本地和远端 ref;只允许 resume |
清理绝不会使用 hard reset。恢复、取消暂存、reset、删除 tag、日志或远端验证错误都会明确报告,而不会被隐藏。
原子推送细节
Verso 会解析当前分支配置的 remote 和 merge ref,只推送下面两个 ref:
<release-commit-oid>:refs/heads/<upstream-branch>
<tag-object-oid>:refs/tags/<release-tag>命令使用 git push --atomic,不会包含其他本地 tag。远端必须支持原子推送,因此会同时接受两个 ref 或
全部拒绝。Registry 发布、GitHub Release、二进制构建和部署仍应交给 tag 触发的 CI。
Hook 与信任边界
Hook 是任意项目 shell 命令。Dry-run 会输出名称和命令,但不会执行。Secret 应通过环境传入,不要存进
配置;hook 应当可以安全重试;破坏性操作或需要凭据的发布行为应优先放在 CI。after_push 是后续处理
边界:可以 resume,但无法撤销远端 ref。hook 中断后,应先确认旧进程已经停止,再重试、跳过或 abort
事务。
开启自动化前,在目标仓库保留下面两项检查结果:
verso doctor --group core --json
verso --group core --version <next-version> --dry-run --json