ci(release): 让发布完整性守卫真的能触发,并把镜像也纳入它守的不变量 (#4900) - #4901
Merged
Conversation
…t guard the image too (#4900) Two defects in the guard #4899 added, both exposed by the very next release (89d2a4e). npm published all of 17.0.0-rc.2 and pushed its tags, then creating the @objectstack/spec GitHub Release failed on the API's 125k body limit — the spec changelog section for that version is 342,911 characters (#4900). The step went red, `published` stayed false, and the runtime image was silently lost. 1. The guard could not fire. GitHub wraps an `if:` naming no status function in an implicit success(), so `if: steps.changesets.outputs.published != 'true'` was really `success() && …` — skipped for any changesets-step failure, which is one of the two cases it exists for. Now `!cancelled() && …`. 2. Its contract was wrong. "Publish whatever is missing" does not cover a release that published and then died before reporting it: rc.2 was already on npm, so a publish-only step would have no-opped and lost the image anyway. It now guards the invariant the release actually owes — this repo's version must be on npm AND must have a matching runtime image — and reports the second half through the job outputs so `docker` builds it. `docker` gains the same `!cancelled()` treatment. A dependent job under the default implicit success() is skipped for any upstream failure, so the image was lost to a fault that happened after the packages were already public. The `published` output is the real gate; the release job's exit status is not, and the run stays red either way because the GitHub Release genuinely failed. A failed ghcr probe counts as MISSING on purpose: a redundant rebuild costs a few minutes, a wrongly-skipped one leaves a published npm version with no image and nothing to say so. Verified against stubbed npm/pnpm/git/curl — npm present + image present (full no-op, no outputs), npm present + image missing (requests docker, does NOT republish), npm missing (publishes, then requests docker), and ghcr unreachable (treated as missing). The ghcr probe itself was checked against the live registry: it resolves an anonymous pull token and correctly reports 17.0.0-rc.1 present and 17.0.0-rc.2 absent. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BbNVKv6KgPzuQ5p76nMgnf
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
os-zhuang
marked this pull request as ready for review
August 3, 2026 15:07
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
修 #4899 引入的那个守卫的两处缺陷 —— 紧接着的下一次发布(
89d2a4e)就把它们全暴露了。那一轮:npm 成功发布了全部 17.0.0-rc.2 并推了 tag,然后创建
@objectstack/spec的 GitHub Release 时撞上 API 的 125k body 上限失败(该版本的 changelog 段落 342,911 字符,详见 #4900)。步骤标红 →published没置真 → 运行时镜像被静默丢掉。缺陷 1:守卫根本触发不了
GitHub 会给不带状态函数的
if:隐式包一层success()。所以实际是
success() && (...)—— changesets 步骤一失败它就被 skipped,而那正是它存在的两个理由之一。改为!cancelled() && ...。缺陷 2:它守的契约错了
原来写的是「缺失就补发」。这覆盖不了「发布成功但在上报前挂了」:rc.2 当时已经在 npm 上,即使它执行了也是 no-op,镜像照样丢。
现在它守的是发布真正欠下的不变量 —— 本仓库的当前版本必须在 npm 上,且必须有对应的运行时镜像 —— 并把后半句通过 job output 上报,让
dockerjob 去建。dockerjob 同样加!cancelled()默认隐式
success()下,上游 job 一失败依赖 job 就被跳过 —— 于是镜像丢在了一个发生在包已经公开之后的故障上。真正的闸门是published输出,不是 release job 的退出码。run 仍然会红(GitHub Release 确实失败了),但镜像不再陪葬。一个刻意的取舍
ghcr 探测失败按「镜像缺失」处理:多建一次镜像只是几分钟,而错误地跳过会留下一个「npm 上有包、没有镜像、且没有任何信号」的发布 —— 正是今天这个坑。
验证
四条路径都用打桩的
npm/pnpm/git/curl实跑过:ghcr 探测本身是对线上真实注册表验证的:能正常换到匿名 pull token(长度 68),并正确报告
17.0.0-rc.1存在、17.0.0-rc.2不存在。YAML 解析通过,新步骤 shell 过
bash -n,两个 job output 表达式取值已核对。关联
docker-publish.yml的workflow_dispatch手动补发。只动
release.yml,不涉及任何运行时代码。🤖 Generated with Claude Code
https://claude.ai/code/session_01BbNVKv6KgPzuQ5p76nMgnf
Generated by Claude Code