@@ -24,8 +24,9 @@ description: Use when releasing a new version of mcpp — bumps version, creates
2424
2525## Overview
2626
27- mcpp 的版本号存在于 ** 四个位置** ,但它们分属** 两组,在发布流程的两个不同时刻更新** 。
28- 把四处一起 bump 是一个会让全部 CI 变红的经典错误 —— 见下面第二组的解释。
27+ mcpp 有 ** 三个持久化版本位置** ,以及 ` ci-fresh-install ` 的一个运行时推导值。它们分属
28+ 两组,在不同时间更新;把"正在构建的版本"与 bootstrap pin 一起前移会让 CI 尝试安装
29+ 尚未发布的 mcpp。
2930
3031** 第一组:正在构建的版本** (发布时改,走 bump PR)
3132
@@ -35,31 +36,22 @@ mcpp 的版本号存在于 **四个位置**,但它们分属**两组,在发
3536这两处必须** 在同一个 commit 里** 一起改:` tests/e2e/01_help_and_version.sh ` 交叉比对
3637` mcpp.toml ` 与 ` mcpp --version ` ,只改一处 CI 立刻红。
3738
38- ** 第二组:bootstrap pin —— CI 用哪个 mcpp 来自举** (发布并进索引之后才改 )
39+ ** 第二组:bootstrap pin —— CI 用哪个 mcpp 来自举** (发布并进索引之后才可改 )
3940
40413 . ` .xlings.json ` → ` workspace.mcpp ` — CI bootstrap 装哪个 mcpp
41- 4 . ` .github/workflows/ci-fresh-install.yml ` → ` MCPP_PIN ` — 全新安装验证的目标版本
4242
43- 这两处指向的是一个** 已经发布、且已经进了索引** 的版本。在 bump PR 里把它们一起挪到新版,
44- 等于让每一个 CI job 去 ` xlings install ` 一个还不存在的 mcpp —— 全线红。
45- 所以它们在 bump PR 里保持** 上一个已发布版本** 不动,直到发布收尾那一步才前移
46- (见「发布后的收尾」第 3 步)。` check_version_pins.sh ` 正是按这个语义校验的:它只要求
47- 两处 pin ** 彼此相等** 、且** 不得新于** 正在构建的版本,并不要求等于它。
43+ ` .xlings.json ` 必须指向一个** 已经发布、镜像并进入索引** 的版本。因此它在 bump PR 中
44+ 保持已有的可安装版本,直到发布收尾时才可前移。
4845
49- 对照最近一次发布:` fd27314 ` (bump 到 2026.7.29.1)只动了第一组两个文件,第二组仍停在
50- 2026.7.28.2;` fde3b70 ` 才在发布、镜像、进索引之后把 pin 推到 2026.7.29.1。
46+ ` ci-fresh-install.yml ` 的 ` MCPP_PIN ` 不是持久化 pin:` wait-index ` 从最新 GitHub
47+ Release 推导一次,所有安装 job 消费同一个输出。绝不能手工编辑或恢复字面量
48+ ` MCPP_PIN ` ,否则 index guard 和实际安装版本会再次漂移。
5149
52- ** 版本不一致会导致 release smoke test 失败** (CI 检查 ` mcpp --version ` 是否匹配 tag)。
53- 第二组历史上多次漂移(` MCPP_PIN ` 曾落后五个版本),所以现在有机器校验:
54-
55- ``` bash
56- bash .github/tools/check_version_pins.sh
57- ```
58-
59- 它同时校验第二组不变量:** ` .github/ ` 下所有 xlings pin 必须等于 ` src/xlings.cppm ` 的
60- ` pinned::kXlingsVersion ` ** (当前 16 个 pin 点、7 个文件,含 release.yml 里三处硬编码的
61- aarch64 tarball 字面量)。` kXlingsVersion ` 是唯一真源,也是 release 打进
62- ` <install>/registry/bin/xlings ` 的那一份。改 xlings 版本只改常量,然后跑这个脚本找出其余落点。
50+ ` .github/tools/check_version_pins.sh ` 的目标是校验版本关系和 xlings pin;但当前版本在
51+ 第 95 行有 Bash 语法错误,不能把它的执行当成有效验证。修复该实现前,手工核对
52+ ` mcpp.toml ` 与 ` MCPP_VERSION ` 相等、` .xlings.json ` 不领先于正在构建的版本;也不要
53+ 通过修改文档或 workflow 绕开动态 ` MCPP_PIN ` 设计。` src/xlings.cppm ` 的
54+ ` pinned::kXlingsVersion ` 仍是 xlings 版本的唯一真源。
6355
6456## 发布步骤
6557
@@ -71,12 +63,15 @@ git checkout main && git pull origin main
7163gh run list --branch main --limit 3
7264```
7365
74- 所有 CI(ci / ci-macos / ci-windows)必须为 ` success ` 。不要在 CI 红的时候发版。
66+ 以分支保护和 ` gh pr checks <pr-number> ` 显示的 actual required checks 为准。
67+ 在 main 上监控当前运行时,检查 ` ci-linux ` 、` ci-linux-e2e ` 、` ci-macos ` 、
68+ ` ci-macos-e2e ` 、` ci-windows ` 、` ci-windows-e2e ` 与 ` cross-build-test ` 的结果;
69+ 跳过或非 required 的 workflow 不是合入 gate。不要在 required CI 红的时候发版。
7570
7671### 2. bump 版本号(第一组两处,单个 commit,走 PR)
7772
78- ** 只改第一组的两个文件** ,并且在同一个 commit 里。bootstrap pin( ` .xlings.json ` 、
79- ` MCPP_PIN ` ) ** 不要动** —— 它们指向上一个已发布版本 ,见 Overview。
73+ ** 只改第一组的两个文件** ,并且在同一个 commit 里。` .xlings.json ` bootstrap pin
74+ ** 不要动** ; ` MCPP_PIN ` 是 workflow 运行时推导值,绝不能手工编辑 ,见 Overview。
8075
8176``` bash
8277# 日期版本:当天序号从 .1 起;.0 仅用于正式/稳定版
@@ -87,8 +82,8 @@ git checkout -b "chore/bump-$NEW_VERSION"
8782sed -i " s/^version.*=.*/version = \" $NEW_VERSION \" /" mcpp.toml
8883sed -i " s/MCPP_VERSION = \" .*\" /MCPP_VERSION = \" $NEW_VERSION \" /" src/toolchain/fingerprint.cppm
8984
90- # 机器校验(building 是新版、bootstrap pin 仍是旧版,是预期状态)
91- bash .github/tools/check_version_pins.sh
85+ # 当前 check_version_pins.sh 有 Bash 语法错误;在它修复前手工确认:
86+ # mcpp.toml 与 MCPP_VERSION 相等,.xlings.json 仍是已发布的 bootstrap 版本。
9287
9388# 自查:构建产物真的报新版本。注意 target/ 目录名带指纹哈希,
9489# 版本一变就是新目录 —— 用 `ls -dt` 取最新的那个,`head -1` 会拿到旧二进制。
@@ -154,8 +149,8 @@ gh release view "v$NEW_VERSION"
154149- ` install.sh `
155150- ` SHA256SUMS `
156151
157- ** 顺带核对体积 ** (2026.7.29.1 起,见下方"载荷瘦身"):linux 两个 tarball 应在
158- ** 5MB 上下 ** 。如果又回到 30MB 量级,说明 strip 断言被绕过了,先查再发 。
152+ 同时比较 Linux 资产与最近一次成功 release 的体积。若出现明显回升,先确认
153+ strip 和打包步骤的断言仍然执行,再继续发布 。
159154
160155## Release CI 详解
161156
@@ -170,20 +165,18 @@ gh release view "v$NEW_VERSION"
1701655 . Linux: ` mcpp self env ` 中 MCPP_HOME 正确解析
1711666 . xlings 二进制已捆绑
172167
173- ### 载荷瘦身(2026.7.29.1 起)
168+ ### 载荷瘦身
174169
175170每个 linux 平台在** 打包后、打 tar 前** 调用 ` .github/tools/slim_linux_payload.sh ` ,
176171strip ` bin/mcpp ` 与 ` registry/bin/xlings ` 并** 断言结果** (` file ` 不得再含
177172` not stripped ` )。
178173
179- 为什么必须断言:在此之前,vendored 的 xlings 从来没被 strip 过(97.3MB,带
180- ` debug_info ` ),而 x86_64 那句 ` strip ` 跑在 ` mcpp pack ` ** 之前** —— pack 会重建
181- 二进制把它覆盖掉,于是直到 2026.7.28.2 发布的 ` bin/mcpp ` 一直是未 strip 的。
182- 一个不校验效果的 ` strip ` 等于注释。修完 linux-x86_64 tarball 从 ** 34.81MB 降到
183- 4.62MB(7.5×)** 。
174+ 为什么必须断言:单独执行一次 ` strip ` 不足以证明最终 tarball 已变小,后续的
175+ ` mcpp pack ` 可能重建并覆盖二进制。检查最终 payload 的 ` file ` 输出和资产体积,而非
176+ 依赖固定的 MB 数或历史发布大小。
184177
185- macOS / Windows ** 故意不做** :载荷本来就 6.1MB / 4.2MB,且 strip Mach-O 会让
186- ad-hoc 签名失效 。
178+ macOS / Windows ** 故意不做** :strip Mach-O 会让 ad-hoc 签名失效;按各平台的
179+ release 规则验证最终资产,不要套用 Linux 的 strip 判断 。
187180
188181### publish-ecosystem:镜像 + 索引(发布的后半程)
189182
@@ -216,11 +209,10 @@ gh pr merge <n> --repo openxlings/xim-pkgindex --squash --admin
216209# 2) 真实验证(注意:不带 @版本 不会升级已装的旧版)
217210xlings update && xlings install mcpp@$NEW_VERSION -y
218211
219- # 3) bootstrap pin 收尾 —— 第二组两处,到这一步才前移
220- # 新版此时已发布、已镜像、已进索引,CI 装得到,pin 才可以指向它
212+ # 3) bootstrap pin 收尾 —— 仅 .xlings.json;新版此时已发布、已镜像、已进索引
221213sed -i " s/\" mcpp\" : \" [^\" ]*\" /\" mcpp\" : \" $NEW_VERSION \" /" .xlings.json
222- sed -i " s/MCPP_PIN: '[^']*'/MCPP_PIN: ' $NEW_VERSION '/ " .github/workflows/ ci-fresh-install.yml
223- bash .github/tools/ check_version_pins.sh
214+ # 不编辑 ci-fresh-install.yml 的 MCPP_PIN:它由 wait-index 运行时推导。
215+ # 当前 check_version_pins.sh 有 Bash 语法错误;手工确认 pin 关系。
224216git commit -am " ci: workspace mcpp bootstrap pin -> $NEW_VERSION (released, mirrored, indexed)"
225217```
226218
@@ -254,11 +246,11 @@ gh workflow run bump-formula.yml -R mcpp-community/homebrew-mcpp
254246| 症状 | 原因 | 修复 |
255247| ------| ------| ------|
256248| ` mcpp X.Y.Z-1 ` 但 tag 是 ` vX.Y.Z ` | ` fingerprint.cppm ` 版本未更新 | 更新 ` MCPP_VERSION ` ,重新打 tag |
257- | bump PR 里** 所有** CI job 都红在 bootstrap,报 ` package 'mcpp@X.Y.Z' not found ` | 把第二组的 bootstrap pin 也一起 bump 了,CI 去装一个还没发布的版本 | 把 ` .xlings.json ` / ` MCPP_PIN ` 回退到上一个已发布版本,发布收尾时再前移 |
249+ | bump PR 里** 所有** CI job 都红在 bootstrap,报 ` package 'mcpp@X.Y.Z' not found ` | 把 ` .xlings.json ` bootstrap pin 一起 bump 了,CI 去装一个还没发布的版本 | 把 ` .xlings.json ` 回退到上一个已发布版本;不要修改运行时推导的 ` MCPP_PIN ` |
258250| 自查 ` --version ` 显示旧版本,但源码已改 | ` target/<triple>/<指纹>/ ` 的指纹随版本变,` ls \| head -1 ` 取到了上一次构建的目录 | 用 ` ls -dt … \| head -1 ` 取最新构建 |
259251| Smoke test 输出旧版本 | CI 缓存了旧的 sandbox/target | 删除 GitHub Actions cache 后重跑 |
260- | e2e ` 01_help_and_version.sh ` 挂 | 只改了 ` mcpp.toml ` 没改 ` fingerprint.cppm ` (它把两者交叉比对) | 同步四处版本 ;注意这个 e2e 只在部分分片里跑,可能表现为"只有某个平台红" |
261- | xlings bootstrap 失败 | xlings 版本不兼容 | 改 ` src/xlings.cppm::kXlingsVersion ` (** 唯一真源** )后跑 ` check_version_pins.sh ` 找出其余 15 个 pin 点 |
252+ | e2e ` 01_help_and_version.sh ` 挂 | 只改了 ` mcpp.toml ` 没改 ` fingerprint.cppm ` (它把两者交叉比对) | 同步两处正在构建的版本 ;注意这个 e2e 只在部分分片里跑,可能表现为"只有某个平台红" |
253+ | xlings bootstrap 失败 | xlings 版本不兼容 | 改 ` src/xlings.cppm::kXlingsVersion ` (唯一真源),再核对引用它的 workflow 与脚本;当前 pin-check 脚本修复前不能依赖它完成扫描 |
262254| macOS/Windows 构建失败 | 需要等 Linux job 先完成 | 检查 Linux job 是否成功 |
263255| ` slim: FAIL: ... still not stripped ` | strip 工具没生效/被 pack 覆盖 | 别绕过断言——它就是为了拦住 34.8MB 的 tarball 再次发出去 |
264256| mirror leg 报 ` missing/unverified ` | 资产没传上去或还没传播 | 先 GET 核验(** 必须 GET,` curl -I ` 会骗你** ),gitcode 用 ` gitcode.com ` 直链而非 ` api. ` 主机;确认缺件后本地补传再 ` gh run rerun --failed ` (脚本幂等,已验证的资产会跳过) |
@@ -310,9 +302,9 @@ gh workflow run release.yml --ref "v$NEW_VERSION"
310302| ` mcpp.toml ` | ` version = "X.Y.Z" ` — 项目版本,release.yml 由它推导 tag |
311303| ` src/toolchain/fingerprint.cppm ` | ` MCPP_VERSION = "X.Y.Z" ` — 编译期版本常量 |
312304| ` .xlings.json ` | ` workspace.mcpp ` — CI bootstrap 装哪个 mcpp(发布** 后** 才 bump) |
313- | ` .github/workflows/ci-fresh-install.yml ` | ` MCPP_PIN ` — 全新安装验证目标(发布 ** 后 ** 才 bump) |
314- | ` src/xlings.cppm ` | ` kXlingsVersion ` — xlings pin 的** 唯一真源** (其余 15 处由脚本校验) |
315- | ` .github/tools/check_version_pins.sh ` | 机器校验上述两组不变量,别靠肉眼 |
305+ | ` .github/workflows/ci-fresh-install.yml ` | ` MCPP_PIN ` — 由 ` wait-index ` 从最新 release 推导, ** 从不手工 bump** |
306+ | ` src/xlings.cppm ` | ` kXlingsVersion ` — xlings pin 的** 唯一真源** |
307+ | ` .github/tools/check_version_pins.sh ` | 版本/pin 校验的预期 guard;当前有 Bash 语法错误,修复前须手工核对 |
316308| ` .github/tools/slim_linux_payload.sh ` | linux 载荷 strip + 断言 |
317309| ` .github/tools/mirror_res.sh ` | 双端镜像(并发上传 + leg deadline + 完整性 gate) |
318310| ` .github/tools/gtc ` | GitCode CLI(release create/upload、PR) |
@@ -321,6 +313,7 @@ gh workflow run release.yml --ref "v$NEW_VERSION"
321313| ` CHANGELOG.md ` | Release notes 来源(按 ` ## [X.Y.Z] ` 提取) |
322314
323315> ** 注意版本 bump 的两个阶段** :` mcpp.toml ` + ` fingerprint.cppm ` 在发版** 前** 改
324- > (它们定义要发什么);` .xlings.json ` + ` MCPP_PIN ` 在发版** 成功后** 改(它们指向
325- > bootstrap 用哪个已发布版本)。` check_version_pins.sh ` 认得这个差异,不会因为
326- > bootstrap pin 落后一版就报错。
316+ > (它们定义要发什么);` .xlings.json ` 只在发版成功、镜像并进索引后才可更新
317+ > (它指定 bootstrap 使用的已发布版本)。` MCPP_PIN ` 是被测版本的运行时推导值,
318+ > 不属于任何手工 bump 阶段。当前 ` check_version_pins.sh ` 的 Bash 语法错误修复前,
319+ > 这些关系须手工核对。
0 commit comments