跳到正文
本页目录

发布流程

Verso 会先计算一份准确的文件计划,再记录一系列明确的本地阶段和最后一次远端事务。持久化计划让中断的 发布可以检查和恢复,无需重新计算原本要写入的内容。

写入之前

Verso 会加载一个发布组配置、发现成员、确认成员版本一致、确定一个目标版本,并计算每个文件实际的 before 和 after 内容。完整发布还会计算 changelog、commit message、tag、hook 和原子推送;bump 计划 只包含版本文件修改和版本 hook。

Shell
verso --group core --version 2.0.0 --dry-run
verso bump minor --group core --dry-run

Dry-run 会输出这份准确计划,包括完整文件的 before/after diff,但不会写文件、运行 hook、创建事务日志 或执行会修改 Git 的命令。

真实执行时,Verso 会检查工作区策略和计划路径、拒绝已有目标 tag,并获取仓库事务锁。每个 Git 仓库 同时只能有一个 Verso 事务。

持久化阶段

第一次文件修改确认后,Verso 会把计划和进度存入 Git metadata,并用原子文件替换写入。完整发布阶段为:

text
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_versionafter_version 后清除事务。它不会 修改 changelog、暂存文件、创建 commit 或 tag,也不会 push。

完整发布在文件、commit、tag 和 push 之前的确认默认都是“是”。目标版本不大于当前版本时,会更早出现 一个默认“否”的确认。--yes 会接受所有确认。

Status、resume 与 abort

Shell
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 尚未开始时可选择 resumeabort。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:

text
<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 事务。

开启自动化前,在目标仓库保留下面两项检查结果:

Shell
verso doctor --group core --json
verso --group core --version <next-version> --dry-run --json
Copyright © 2026 白熱.