主题

PR label release

PR label release 是逐 PR 的产品发布协议:PR labels 只提供经过 gate 验证的发布操作与发布阶段;最高的合格 final vX.Y.Z Git release tag 是唯一数字版本基线,VERSION 只锁定 trusted preparation 已决定的精确产品版本。label 不能计算、覆盖或为版本提供 fallback。

  • 运维
  • 工具

目录

Definition

PR label release 是逐 PR 的产品发布协议:PR labels 只提供经过 gate 验证的发布操作与发布阶段;最高的合格 final vX.Y.Z Git release tag 是唯一数字版本基线,VERSION 只锁定 trusted preparation 已决定的精确产品版本。label 不能计算、覆盖或为版本提供 fallback。type:* 选择产品数字操作或显式 non-product skip;channel:* 只选择产品发布形态。本 Topic 负责 version/tag identity 与 label 的选择和校验,不从代码 diff、API 或 state 自行推导兼容性结论。

本 Topic 只适用于 owner 明确选择 PR labels 作为 release intent 的项目。采用单一 release-target 字段并由 trusted final baseline 解析版本的项目不应安装、路由或调用本 Topic;本项目的 Manual version release contract 属于后一类,旧 Label Gate check name 只是 branch-protection compatibility surface,不改变该边界。

本次合同收敛只修改通用文档、ADR、Topic 与 JSON 模板,不创建、发布、恢复或重写真实 tag、Release、镜像、GitHub label、ruleset 或 workflow。下文的 preparation、reservation、Release 与 recovery 是后续产品实施必须满足的合同,不是本次已执行的远端操作。

正常产品 PR 的源提交先完成完整 PR CI 和 label gate。随后控制器只在同一产品 PR 分支追加一个 VERSION-only preparation commit;Release completion 核验来源、意图和源提交 CI,产品 PR 再以正常 merge 进入 main。发布从合并后的 main 读取已锁定的 identity,构建、tag、资产、部署和 recovery 都绑定同一个 merge SHA/version/channel。

TelevyBackup 是本 Topic 的 primary/reference evidence:它已在 .github/release-contract.json、docs/specs/product-version-release-chain/SPEC.md 与 docs/adr/0010-release-identity-reservation.md 中落地 final-tag-first、四种 channel grammar、append-only identity refs、same-SHA recovery 和显式 version-only-release-pr。这些仓库专属文档只作为已验证实现证据;可复用的模式仍归入本通用 Topic,不创建 repo-specific Topic。

当该 commit 由 GitHub Actions 写入且受 GitHub signed-commit 规则保护时,GitHub-native createCommitOnBranch 是该实现变体的默认写入面:它使用 job 的 GITHUB_TOKEN,将写入权限限定为 contents: write,并按 PR/check metadata 验证需要声明 pull-requests: read、checks: read,创建远端 child commit,不要求仓库保存 GPG 私钥或口令。它仍是同一条 PR-local、VERSION-only preparation 链路,不是允许 workflow 直接写 main 的例外。

它不是“merge 后由 label 计算 bump”的流程,也不是 release snapshot、queue、train 或 backfill 在多个 PR 之间重新分配版本的流程。一次产品 PR 对应一次 preparation、一次 merge、一个 tag、一个资产集合和一个可回滚边界。唯一的补救例外是下文定义的独立 VERSION-only release PR:它创建新的发布 PR 和新的 merge identity,不能伪装成旧 merge 的 recovery 或历史 backfill。该补救模式是本 Topic 基于只读回验新增的 proposal;项目必须先实现并验证对应的 Release completion mode,不能把它误称为已由现有参考实现覆盖。

Label and version contract

  • type 只能是 type:major、type:minor、type:patch、type:docs 或 type:skip。前三者是产品版本数字操作;后两者是 non-product skip,成功时不写 VERSION、不创建 tag、不发布且不触发失败通知。
  • 产品 type 必须且只能带一个 channel:prod、channel:rc、channel:beta 或 channel:dev。channel:prod 发布 final base;其余三个发布同一 base 的精确 prerelease。type:docs 与 type:skip 禁止任何 channel。
  • Label Gate 必须拒绝未知、缺失、重复、互斥和 legacy release labels;模板中的 allowed 集合是新合同的完整接受集合。
  • 迁移只允许以下映射:type:none -> type:skip、channel:stable -> channel:prod、channel:canary -> channel:dev。映射完成后,legacy 值不得再通过新 gate。

版本格式与身份规则如下:

  • 合格 final tag 必须是受保护 release automation 创建、且指向 main 可达提交的 vX.Y.Z;最高合格 final tag 是唯一数字基线,无 tag 时以 0.0.0 为虚拟基线。
  • type:major、type:minor、type:patch 分别把 X.Y.Z final 基线推进为 (X+1).0.0、X.(Y+1).0、X.Y.(Z+1);channel:prod 的 VERSION 为该 <base>,channel:beta、channel:rc、channel:dev 的 VERSION 分别为 <base>-beta.N、<base>-rc.N、<base>-dev.N。N 从 1 开始,只按同一 base/channel 的已发布 tag 递增,prerelease 不推进 final baseline。
  • VERSION 是 trusted preparation 写入的最终 identity。Release completion、tag ownership、签名 provenance、构建、发布和 recovery 必须复核同一 SHA/version/channel;不得重新分配 successor。派生 tag 与 release identity 必须以原子 reservation/identity claim 绑定,claim key 在 merge 前由 pull_request_number + source_sha + type + channel 组成;Release completion 冻结 boundary token,合并后的 mainline Release 才在 token 匹配时绑定最终 merge SHA。并发 contender 只能复用同一 claim 或 fail closed,不能静默递增序号。
  • reservation 必须持久化 reservation_id、reservation_owner、pre-merge reservation_claim_key、pre_merge_boundary_token、版本/channel、reservation_merge_commit_sha 与 reservation_state(claimed、bound、consumed 或 released)。claimed 时 reservation_merge_commit_sha 必须为空;Release completion 只验证并冻结 boundary token;合并后的 mainline Release 才以 CAS 在 token 匹配时写入最终 merge SHA 到 reservation_merge_commit_sha,将 claimed 转为 bound,发布完成后再转为 consumed。PR 关闭、label 改变或 preparation 失败只能在 reservation_merge_commit_sha 为空且 boundary token 尚未进入 merge 时原子转为 released,不能释放已合并的合法 identity。当 recovery 选择 reservation 路径时,只有 owner、claim key、版本/channel、reservation_merge_commit_sha 与 state 均匹配且 state 为 bound 才能使用;tag 路径不要求 reservation。
  • preparation 或发布构建前发现 tag 被其他 SHA 占用、tag owner 未被验证、provenance 不完整、labels 与 identity 不匹配或签名未验证时必须 fail closed。same-SHA recovery 需要同一 SHA 且 owner 已验证的 tag,或仍由该 identity 持有且 state 为 bound、claim key/version/channel 均匹配的 reservation;recovery 可完成缺失的发布步骤,但不写 VERSION、不重新分配序号、不改 tag 指向、不改变 channel。

Release identity modes

以下五种能力名称相近,但输入、输出和禁止事项必须分离;实现和 review 都不得依据名称相似互相替代。

能力输入输出禁止事项
正常产品 PR 的 VERSION-only preparation commit尚未合并的产品 PR;源提交已通过完整 PR CI 与 Label Gate同一 PR 分支上、以源提交为唯一父提交、只改 VERSION 的 preparation commit;随后正常 merge不得用于已经合并的产品代码,不得直接写 main,不得夹带产品代码或多个父提交
VERSION-only release PRmain 上恰有一个尚未取得 preparation/release identity 的产品发布边界;可忽略其后的明确 type:skip/non-product merge;目标版本尚无 release identity一个显式、非空、只改 VERSION 的新 PR;其自身完成 PR CI、Label Gate、tag reservation 与 Release completion 后正常 merge,该新 merge SHA/version/channel 成为 release identity不得把旧产品 PR 的 merge SHA 当作输出,不得为空 PR、直接写 main、覆盖既有 tag/release,或把多个待发布产品 PR 合入同一 PR
same-SHA recovery已经有不可变 merged SHA/version/channel identity,但 publish/deploy/receipt 失败或不完整对完全相同 SHA/version/channel 的一次重试;不产生新 PR 或新 release identity不得修改 VERSION、计算 successor、重建 preparation、改变 tag 指向或 channel,或顺带合并其他 PR
历史 backfill旧 merge 缺少 required preparation/provenance,且需要补充审计记录或导入历史事实非发布性的历史说明、审计或 snapshot;不改变现有 Git identity不得分配版本、写 VERSION、创建 tag/资产,或把它作为 workflow_dispatch 发布入口;确需发布时只可在满足上行条件后走新的 VERSION-only release PR
release queue/train两个及以上产品 PR 等待发布、重排或合并版本本 Topic 不提供该能力;实现应在选择版本前 fail closed不得选取“next pending”、合并/跳过产品 PR、为旧 PR 回算版本,或将 queue/train 叫作 release PR

When to use

当可部署产品需要把一次 PR 的版本、构建产物、tag 和回滚距离固定为同一条可审计链路时使用。所有产品 consumer 读取同一 VERSION,本 Topic 管理 label intent、preparation、merge 和发布次序。

若 labels 只用于 issue 分类、review routing、priority 或 changelog 备注,不能提升为 release contract。若项目只发布独立库且 package manifest 已是唯一公开版本 contract,也不应套用本 Topic 的 PR-local preparation 链路。

Habits / defaults

  • PR 必须在 merge-ready 前通过 Label Gate。合法 type:* 是 type:major、type:minor、type:patch、type:docs 与 type:skip:前三者为产品数字操作,后两者为 non-product。产品 PR 必须且只能有一个 channel:*,其合法选项是 channel:prod、channel:rc、channel:beta 与 channel:dev;type:docs 与 type:skip 不得携带 channel:*。未知、缺失、重复或互斥的 release labels 必须失败。
  • 合格 final tag 必须匹配 vX.Y.Z、指向 main 可达的提交,并由受保护 tag namespace 中的 release automation 创建;历史为空时以 0.0.0 为虚拟基线。type:major、type:minor 与 type:patch 从该基线选择 final base。channel:prod 写入该 base;channel:beta、channel:rc 与 channel:dev 分别写入 <base>-beta.N、<base>-rc.N 与 <base>-dev.N,其中 N 从 1 开始并按同一 base/channel 已发布 prerelease tag 的最大序号递增。prerelease 不推进 final baseline。type:docs 与 type:skip 成功跳过,不写 VERSION、不发布且不触发失败通知。VERSION、package manifest、label、snapshot 和环境变量都不能作为 successor 的基线或 fallback。
  • VERSION 是已决定 identity 的受控记录,而不是版本计数器。trusted preparation 只在产品 PR 中写入完整 final 或 prerelease version;它与冻结的 type:*、channel:*、tag baseline、signed trailers、branch head 和 tag reservation 一起验证。一个已发布的产品版本只对应一个 SHA/version/channel identity。
  • 正常产品 PR 的源提交必须先完成完整 PR CI。控制器随后从合格 tag baseline 解析候选版本、reserve v<version>,并在同一 PR 分支追加唯一的 preparation commit:它只有源提交一个父提交、diff 只修改 VERSION,并携带 source SHA、产品版本和冻结 intent trailers。该 commit 不是独立 release PR,也不能在 merge 后补写。
  • 若 GitHub Actions 要为受 signed-commit 规则保护的 PR branch 创建 preparation,将写入权限限定为 contents: write,并为 PR/check metadata 验证声明 pull-requests: read、checks: read,以 GITHUB_TOKEN 调用 GraphQL createCommitOnBranch。mutation 必须将当前 source SHA 传入 expectedHeadOid,只添加 VERSION,并在调用前后核对 branch head;不得通过配置 GPG 私钥/口令、移除 signed-commit 规则或放宽 VERSION-only 约束来绕过签名。
  • 无论 preparation 状态为 created 还是 existing,都必须验证 branch head、单父/仅 VERSION/trailers provenance,并在有界重试后要求 GitHub API 返回 commit.verification.verified: true。GraphQL error、缺失 OID、head 漂移、结构不合法或签名未验证均必须 fail closed。
  • preparation 前和发布构建前都要验证派生 tag ownership。若 tag 已被其他提交占用或 owner 未验证,必须在写入版本或构建资产前失败;只有已验证 owner 的同 SHA tag 或同 SHA 未消费 reservation 才可走 same-SHA recovery,不能改写 tag、回退到其他版本或继续发布。
  • Release completion 是 required merge gate,复核 preparation 的父提交、diff、trailers、base、label contract 和源提交 CI。preparation commit 只做结构校验,不能递归触发完整 CI、发布或部署。
  • 当已经合并的单一产品发布边界缺少 preparation identity 时,创建一个显式、非空的 VERSION-only release PR 是允许且推荐的补救路径。该 PR 的 branch diff 必须只改 VERSION,并记录被覆盖的产品 merge SHA、冻结 intent、目标版本和 release-mode: version-only-release-pr provenance;它自己仍须通过完整 PR CI、Label Gate、tag reservation 与允许该模式的 Release completion,然后以正常 PR merge 创建新的 identity。
  • 产品 PR 经通过 Release completion 后以正常 merge 进入 main。Release 只读取这个 merged main commit 的 VERSION,复核其 preparation provenance 和 tag ownership,再一次构建、校验、tag、发布资产并从同一归档部署;它不得重新分配 successor。
  • 发布失败后版本保持锁定。same-SHA recovery 只可复用已有的 merged SHA/version/channel 及其已验证 tag 或 reservation;不得再写 VERSION、计算 successor、合并其他 PR 或压缩多个版本边界。缺少 identity 的旧 merge 不满足这个 recovery 输入。
  • 每个产品 PR 必须独立发布,不建立 release queue、release train 或历史 backfill 来合并或重排多个 PR 的版本。VERSION-only release PR 只补救一个已合并、未准备的产品边界,不能变成 queue/train 或多 PR aggregate。
  • type:* 决定是否为产品分配版本及其 final numeric base;channel:* 不改变该 base。channel:prod 创建 final GitHub Release、发布到 prod/default surface、可更新稳定 latest;channel:rc、channel:beta 与 channel:dev 各自创建 prerelease GitHub Release 并发布到独立 rc/beta/dev surface,只使用精确版本 image tag,不更新 default surface 或稳定 latest。same-SHA recovery 保留完整 SHA/version/channel identity。
  • Draft Release 按 API resource ID 定位,不把 tag lookup 当成唯一入口。 产品 Release identity 仍由 merged SHA/version/channel 和已验证 tag 或 reservation 定义;GitHub Release 的 release.id(API 路径参数 release_id)及各资产的 assets[].id 只是对应 REST 资源的操作句柄,不替代产品 identity。创建 Draft 时保存 release_id;上传资产使用该 release 的 assets endpoint,并保存响应中的 asset id 供后续校验、更新或删除。恢复时若未持有 release_id,通过认证后的 release list 按预期名称、版本及项目自己的 provenance/目标 identity 查找,并要求唯一匹配且 draft: true;单凭 tag endpoint 未命中不能推断 Draft 不存在,某些 Draft lookup surface 还可能显示 untagged-* 占位。发布前对同一 release_id 显式提交预期 tag_name 和 draft: false,随后按 ID 重新读取并核验 tag、draft 状态以及资产 ID/名称/摘要;无唯一匹配或回读不符时 fail closed,不创建重复 Release、不改分配版本或既有 tag(GitHub Releases REST API、release assets REST API)。
  • 发布成功后,由实际拥有 release 的 agent 向主人确认版本/tag、merge SHA、已发布 artifact 或 deployment surface 及 run URL;不得把 source PR 的 version、status 或 receipt 评论作为发布结果回写。
  • 上述边界只针对 post-release source-PR result comment;pre-release intent/provenance comment、PR preview comment 与非 PR artifact receipt 不在全局禁止范围内。
  • Release failure notification 应携带 PR intent、source SHA、merged SHA、产品版本、tag、资产、run URL 和同 SHA recovery 指令。
  • PR label release 只提供 failure payload 的 release identity,不选择 transport。接入通知前必须通过 Release failure notification 的 transport selection gate;没有项目合同或主人明确选择时,阻断 rollout,不得默认新增外部 notifier、secret 或渠道。

Copyable release contract

  • 从 skills/policies/pr-label-release/assets/templates/pr-label-release.example.json 开始复制 label policy。模板把 normal preparation、补救性 VERSION-only release PR、same-SHA recovery、历史 backfill 和 queue/train 分成独立字段;默认 contract 是必须且仅能有一个 type:*,产品 type 必须且仅能有一个 channel:*,type:docs 与 type:skip 禁止 channel:*,可选 component:*;未知 release label、重复必选 label、缺少必选 label 都必须让 Label Gate 失败。
  • Label Gate 是 PR merge-readiness gate,不是 release workflow 的内部步骤。它应在 trusted workflow source 中读取当前 PR labels,验证 label groups、unknown labels、mutual exclusion、required groups,并把解析后的 intent 写入 job summary 或 artifact。
  • preparation controller 在源提交的完整 CI 与 label gate 成功后从最高合格 tag 解析候选版本,按冻结操作以原子 compare-and-claim 方式锁定 identity 与派生 tag reservation,再写入唯一 VERSION。reservation 必须记录 ID、owner、claim key、pre-merge boundary token、版本/channel、reservation_merge_commit_sha 和 claimed state;claimed 时该字段必须为 null。Release completion 冻结 token,合并后的 mainline Release 只在 token 匹配时以 CAS 将最终 merge SHA 写入 reservation_merge_commit_sha 并把 claimed 转为 bound;recovery 必须核对该字段与 recovery SHA 相等。并发重试只能复用同一 claim 或 fail closed,不能静默递增序号;若由 GitHub Actions 写入受签名保护的 branch,则用 job GITHUB_TOKEN、限定为 contents: write 的写入权限以及验证 PR/check metadata 所需的 pull-requests: read、checks: read,调用 createCommitOnBranch,并传入 source SHA expectedHeadOid 创建同 PR 的 VERSION-only preparation commit。它不得请求 GPG 私钥/口令,也不得用取消签名规则替代验证。
  • GitHub-native 写入在 created 与 existing 两条路径均复核 branch head 和 preparation provenance,并有界轮询 commit.verification.verified;只要签名未验证、mutation 没有返回 OID 或 branch 已漂移,就不允许进入 Release completion。
  • Release completion 必须把 preparation、其源父提交、PR base、label contract 与源提交 CI 绑定为同一个可验证的 SHA/version/channel 对象;或在显式 version-only-release-pr mode 中绑定该 PR 的单一产品边界、只改 VERSION 的 branch diff、provenance、完整 PR CI 与 label contract。它成功后 PR 仍使用正常 merge,不允许 workflow 直接写 main。
  • mainline Release 只从这两种允许 mode 的 merge 所提交的 VERSION 和 provenance 取得 identity;它不得从 label、package manifest、snapshot 或环境变量计算或替代版本,也不得重算 successor。VERSION-only release PR 的 identity 是它的新 merge SHA/version/channel,绝不是其覆盖的旧 merge SHA。
  • 发布前再次验证 tag ownership;完成一次资产构建、资产校验、tag、GitHub Release 和部署。任一失败都保留同一 main SHA/version/channel 及其已验证 tag 或 reservation,下一次只能 same-SHA recovery;workflow_dispatch 只能成为该 recovery 的显式入口,不能承担历史 backfill、版本分配或任意 SHA/PR 组合。
  • release owner 必须向主人提供成功发布确认,而不是向 source PR 写 version/status/receipt comment。该规则不禁止 pre-release intent/provenance comment、PR preview comment 或非 PR artifact receipt。
  • channel:prod 映射正式 release/default surface,可更新稳定 latest;channel:rc、channel:beta 与 channel:dev 分别映射 RC、beta、dev prerelease surface,GitHub Release 保持 prerelease,镜像只使用精确版本 tag,不更新 default surface 或稳定 latest。Release completion、merged identity、tag ownership、failure context/transport 与 same-SHA recovery 都必须保留同一 SHA/version/channel triple;recovery 不得重新解释或重新计算版本。
  • 不允许由 queue、train、snapshot 或历史 backfill 将多个产品 PR 合为一个 release;也不允许跳过某个已合并的产品 PR 以追赶更新的版本。对缺少 preparation 的单一历史边界,选择补救性 VERSION-only release PR 时仍只能覆盖该一条边界。
  • 与 Quality gates 同用时,.github/quality-gates.json 必须把 Label Gate 作为 workflow-backed required check,或记录明确 waiver。GitHub branch protection / ruleset 必须要求该 check,保护默认分支为 PR-only,并继续要求 signed commits;native review policy 只在仓库显式声明 policy.review_policy 时同步。
  • 失败通知要包含 release intent 与锁定 identity:PR 编号、source SHA、merge commit SHA、type:*、channel:*、目标版本、tag、tag target SHA、已验证 tag owner、reservation_id、reservation_owner、reservation_state、reservation_merge_commit_sha、provenance/signature verification、branch head、artifact names、run URL 和同 SHA recovery 指令。缺少这些字段时,通知不能支撑发版排障或证明 recovery ownership。
  • 通知接入要复制 skills/policies/release-failure-notification/assets/templates/release-failure-notification-transport-gate.example.json 的 gate。它要求记录 transport 选择证据、transport/configuration owner 和 required secrets;未选定时阻断 rollout,选定配置缺失时 fail closed。

Reference implementations

  • projects/televy-backup.md:当前完整 release identity chain 的 primary/reference sample,覆盖 final-tag-first、prod/beta/rc/dev grammar、reservation/decision/bound/consumed refs、same-SHA recovery、version-only-release-pr 与非权威 intent snapshot。
  • projects/codex-vibe-monitor.md:完整 PR/main/release/review policy topology。
  • projects/octo-rill.md:quality-gates + worktree bootstrap + label release。
  • projects/blog-26.md:component-aware release workflow。
  • projects/xp.md:distributed service release 与 Xray e2e 并存。
  • projects/flux-purr.md:设备 mono-repo 保留 label gate 作为 required intent contract,并以 VERSION 锁定产品 identity;适合检查 intent、版本基线与产品 identity 不被混淆。
  • projects/spotibind.md:只读回验样本,说明已有产品代码若先于 preparation 合并,必须由新 release PR 创建新的 identity;它不是已有 preparation/recovery 实现的证明。
  • projects/televy-backup.md 的 .github/release-contract.json、.github/scripts/release_chain.py、.github/scripts/release_reservation.py、.github/scripts/release_preparation.py 与 .github/scripts/release_completion.py:用于复核 identity claim、append-only state transition、same-SHA boundary 与新 PR identity 的实现证据。
  • skills/style-playbook/references/topics/release-failure-notification/TOPIC.md:与本 Topic 配对,用于把 release intent 带进失败告警,而不是只发一条无上下文失败消息。
  • skills/style-playbook/references/topics/semver-change-governance/TOPIC.md:负责跨 application artifacts、public/external API 与 persistent state 的兼容性分类;本 Topic 只接收其结论并管理 label、identity 与 tag。

Application decision records

  • skills/policies/pr-label-release/assets/decision-memos/spotibind-version-only-release-pr.md:以当前只读事实应用本 Topic 的简短决策备忘;该备忘不是 reference implementation,也不把 owner-provided 事实伪装成已存在的通用规范。

Failure modes

  • label contract 不唯一会让 preparation 无法冻结发布意图;必须在写 VERSION 前失败。
  • 让 VERSION、label、package manifest、snapshot 或环境变量计算或回退 successor,或接受不合格 tag 作为基线,会让 preparation、merge、tag 与 manifest 表达不同 identity;必须从最高合格 tag 分配候选版本,并将 VERSION 只作为锁定后的 identity 读取。
  • 在源提交 CI 前 preparation、让 preparation 改动产品代码,或让它有多个父提交,会破坏来源证明;必须只允许同 PR 的单父 VERSION-only commit。
  • 把 merge 后补写 VERSION 的需求仍称作原产品 PR 的 preparation,会伪造已不存在的 PR-local provenance;若且仅若满足单一未准备边界的输入,应创建独立、非空的 VERSION-only release PR,并承认它产生新 merge identity。
  • 在 signed-commit 规则下让 Actions 本地签名并依赖未配置的 GPG 私钥/口令,会使 fresh preparation 不可验证;GitHub Actions 创建分支提交时应使用 GITHUB_TOKEN、contents: write、createCommitOnBranch 与 expectedHeadOid,再验证 GitHub 签名,而不是移除规则或伪造凭据。
  • 只验证刚创建的 preparation、相信 existing 状态,或在 mutation 返回后跳过签名轮询,会把无签名或并发漂移的提交带入发布;两个状态都必须复核结构、branch head 和 commit.verification.verified,未验证即失败。
  • preparation 后直接写 main、跳过 Release completion 或不经正常 merge,会绕开受保护分支和 PR 级回滚边界。
  • 将多个产品 PR 压缩到 queue/train、把 historical backfill 当作发布入口、对失败发布计算 successor,或从更新 tag 回算旧 PR 的版本,会丢失版本与回滚距离;same-SHA recovery 只能重用原 merge SHA/version/channel 及其 reservation。
  • tag 已被其他提交占用、由未授权 owner 持有,或 reservation/identity claim 发生竞争时继续构建、静默复用或强推 tag,会产生无法审计的发布;只有已验证 owner 的同 SHA tag 或同 SHA reservation 可以恢复,其他情况必须在 preparation 和构建前 fail closed。
  • Draft Release 的 tag lookup 未命中时直接创建新 Release,可能留下重复草稿或资产;应按已保存的 release_id 操作,丢失时从认证后的 release list 做唯一、带身份核验的匹配。
  • 以 Draft 阶段的 untagged-* 占位、资产文件名或 tag URL 代替 Release/asset resource ID,会使恢复操作指向错误对象;应记录 release_id 与 asset id,发布前显式设置并回读验证 tag_name。
  • 把 label gate 写在不可信 PR head、或未将它列为 required check,会让发布意图失去 merge gate 边界。
  • 让 beta、rc 或 dev 覆盖 default surface,或让部署分类重写锁定版本,会使发布身份不再可审计;部署系统只能消费已验证的 SHA/version/channel triple。
  • 把成功发布事实回写到 source PR,会把通知语义绑到 issue timeline 并制造不必要的订阅噪音;应由 release owner 直接向主人确认结果,同时保留失败通知。
  • 由 label release contract 或历史 reference 推断默认 transport,会让项目无证据地引入外部 notifier、secret 或渠道。label contract 只能提供 payload,transport 必须另行选择。
  • 让 Label Gate 从 diff 或 state migration 自动推断 major、minor 或 patch,会把发布意图与兼容性治理混在一起;必须由 SemVer change governance 先记录并在发布前验证分类,再由本 Topic 校验其 label projection。

Evidence index

  • projects/codex-vibe-monitor.md
  • projects/octo-rill.md
  • projects/blog-26.md
  • projects/xp.md
  • projects/flux-purr.md
  • projects/flux-purr.md 的 .github/workflows/release-preparation.yml、.github/scripts/test-release-workflows.sh 与 docs/solutions/release/github-native-verified-version-commit.md
  • projects/spotibind.md
  • projects/televy-backup.md
  • projects/televy-backup.md 的 .github/release-contract.json、.github/workflows/release-preparation.yml、.github/workflows/release-completion.yml、.github/workflows/release.yml、.github/scripts/release_chain.py、.github/scripts/release_reservation.py、.github/scripts/release_preparation.py 与 .github/scripts/release_completion.py
  • projects/televy-backup.md 的 docs/adr/0010-release-identity-reservation.md 与 docs/specs/product-version-release-chain/SPEC.md
  • skills/style-playbook/references/topics/release-failure-notification/TOPIC.md
  • skills/policies/release-failure-notification/assets/templates/release-failure-notification-transport-gate.example.json
  • skills/style-playbook/references/topics/semver-change-governance/TOPIC.md
  • https://docs.github.com/en/rest/releases/releases
  • https://docs.github.com/en/rest/releases/assets