From 6e98869f08a08050439fd49d7d7ddc8a7b46f270 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Wed, 29 Jul 2026 04:55:49 +0800 Subject: [PATCH] chore: xlings pin -> 2026.7.28.4, and bring the release spec up to date MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pin bump: `src/xlings.cppm::kXlingsVersion` is the single source of truth; check_version_pins.sh then named all 15 dependent pins across 7 files (including the three hardcoded aarch64 tarball literals in release.yml that a comment-only lock-step list had missed). All 16 now agree. Docs/spec, brought level with what the release pipeline actually does: - `mcpp --version` samples in getting-started (both languages) still showed `0.0.1`, from before the date-version scheme. - The release skill claimed THREE build platforms; there are four, plus `publish-ecosystem`. Its artefact checklist omitted the aarch64 tarball and the versionless aliases entirely. - It documented nothing about the second half of a release — mirroring to xlings-res, the index bump PR, `xlings install mcpp@` verification, and the bootstrap-pin bump — which is where every recent incident happened. That is now written down, along with WHY the mirror is built the way it is: measured 0.012 MB/s inbound to file.gitcode.com from a US runner vs 3.87 MB/s outbound and 16 MB/s to GitHub, ~4.6x jitter (so no fixed per-asset cap can work), per-connection shaping (so concurrency scales), no multipart on the presigned PUT (so a single file cannot be split), and gtc's exit code lying in both directions via the OBS callback. - Added the payload-slimming step and, more importantly, why it ASSERTS: the previous `strip` silently did nothing for many releases because `mcpp pack` rebuilds the binary after it. - Split the version-bump file list into the two phases it actually has — mcpp.toml/fingerprint.cppm BEFORE the release, .xlings.json/MCPP_PIN AFTER — which is what check_version_pins.sh already encodes but nobody had said. Historical records under .agents/docs/ are left alone on purpose: they record what was true when written, and rewriting them would falsify the ledger. Same for the `mcpp 0.0.95+` feature markers in docs/ — those are "introduced in" markers, not stale values. Verified: check_version_pins.sh OK, all touched YAML parses, `mcpp build` and `mcpp test` (37 binaries) green. --- .agents/skills/mcpp-release/SKILL.md | 89 ++++++++++++++++++++- .github/actions/bootstrap-mcpp/action.yml | 2 +- .github/actions/setup-macos-llvm/action.yml | 2 +- .github/workflows/bootstrap-macos.yml | 2 +- .github/workflows/ci-fresh-install.yml | 6 +- .github/workflows/ci-linux-e2e.yml | 2 +- .github/workflows/cross-build-test.yml | 4 +- .github/workflows/release.yml | 14 ++-- docs/00-getting-started.md | 2 +- docs/zh/00-getting-started.md | 2 +- src/xlings.cppm | 2 +- 11 files changed, 104 insertions(+), 23 deletions(-) diff --git a/.agents/skills/mcpp-release/SKILL.md b/.agents/skills/mcpp-release/SKILL.md index f36935e..dd197de 100644 --- a/.agents/skills/mcpp-release/SKILL.md +++ b/.agents/skills/mcpp-release/SKILL.md @@ -89,13 +89,18 @@ Tag push 会自动触发 `release.yml` workflow。 ### 4. 监控 Release CI -Release workflow 包含三个平台的构建: +Release workflow 包含**四个平台**的构建,外加一个生态发布 job: | Job | 平台 | 产物 | 依赖 | |-----|------|------|------| | `build-release` | Linux x86_64 | `mcpp-X.Y.Z-linux-x86_64.tar.gz` | 无(先执行) | +| `build-linux-aarch64` | Linux aarch64(交叉) | `mcpp-X.Y.Z-linux-aarch64.tar.gz` | 等 Linux x86_64 完成 | | `build-macos` | macOS ARM64 | `mcpp-X.Y.Z-macosx-arm64.tar.gz` | 等 Linux 完成 | | `build-windows` | Windows x86_64 | `mcpp-X.Y.Z-windows-x86_64.zip` | 等 Linux 完成 | +| `publish-ecosystem` | — | 镜像到 xlings-res 双端 + 开索引 bump PR | 等**全部四个**构建完成 | + +`build-linux-aarch64` 是两段式的(bootstrap 先构出本 release 的 x86_64 mcpp,再用它交叉构建 +aarch64),因为 bootstrap 装的是**上一个已发布版本**,可能不认新特性。 ```bash # 监控 release workflow @@ -118,13 +123,18 @@ gh release view "v$NEW_VERSION" 确认以下产物全部存在: - `mcpp-X.Y.Z-linux-x86_64.tar.gz` + `.sha256` +- `mcpp-X.Y.Z-linux-aarch64.tar.gz` + `.sha256` - `mcpp-X.Y.Z-macosx-arm64.tar.gz` + `.sha256` - `mcpp-X.Y.Z-windows-x86_64.zip` + `.sha256` +- 上述四个的**无版本号别名**(`mcpp-linux-x86_64.tar.gz` 等)+ `.sha256` - `mcpp-X.Y.Z.tar.gz`(源码包) - `mcpp.lua`(xpkg 描述) - `install.sh` - `SHA256SUMS` +**顺带核对体积**(2026.7.29.1 起,见下方"载荷瘦身"):linux 两个 tarball 应在 +**5MB 上下**。如果又回到 30MB 量级,说明 strip 断言被绕过了,先查再发。 + ## Release CI 详解 ### Smoke Test 检查项 @@ -138,14 +148,73 @@ gh release view "v$NEW_VERSION" 5. Linux: `mcpp self env` 中 MCPP_HOME 正确解析 6. xlings 二进制已捆绑 +### 载荷瘦身(2026.7.29.1 起) + +每个 linux 平台在**打包后、打 tar 前**调用 `.github/tools/slim_linux_payload.sh`, +strip `bin/mcpp` 与 `registry/bin/xlings` 并**断言结果**(`file` 不得再含 +`not stripped`)。 + +为什么必须断言:在此之前,vendored 的 xlings 从来没被 strip 过(97.3MB,带 +`debug_info`),而 x86_64 那句 `strip` 跑在 `mcpp pack` **之前** —— pack 会重建 +二进制把它覆盖掉,于是直到 2026.7.28.2 发布的 `bin/mcpp` 一直是未 strip 的。 +一个不校验效果的 `strip` 等于注释。修完 linux-x86_64 tarball 从 **34.81MB 降到 +4.62MB(7.5×)**。 + +macOS / Windows **故意不做**:载荷本来就 6.1MB / 4.2MB,且 strip Mach-O 会让 +ad-hoc 签名失效。 + +### publish-ecosystem:镜像 + 索引(发布的后半程) + +四个构建 job 全绿后自动执行,做两件事: + +1. **镜像到 `xlings-res/mcpp` 双端**(GitHub + GitCode),由 + `.github/tools/mirror_res.sh` 完成 —— 单 leg 内资产**并发上传** + (`MIRROR_MAX_PARALLEL`,默认 8),预算是**整条 leg 的 deadline** + (`MIRROR_LEG_DEADLINE_GH` 600s / `_GTC` 2400s),不是 per-asset cap。 +2. **向 `openxlings/xim-pkgindex` 开 bump PR**(带每平台 sha256)。 + +**为什么不是 per-asset cap**:实测(探针 PR #301)GitHub US runner 上传到 +`file.gitcode.com`(单 IP 华为云北京)只有 **0.012 MB/s** —— 而同一台 runner +从同一个 IP **下载**有 3.87 MB/s、传 GitHub 有 16 MB/s、大陆本机传它有 +1.84 MB/s。被限的是**国际入境方向**,且速率有 ~4.6× 抖动,所以任何固定 +per-asset 值都不可能既安全又有用。限速是 **per-connection** 的(1/4/8 并发 += 76/80/93s 墙钟),所以并发能叠加;但预签名是 OBS **单次 PUT** 签名,无 +multipart/无断点续传,**单文件拆不开** —— 这正是必须先把载荷 strip 小的原因。 + +**`gtc` 的退出码两个方向都会撒谎**:PUT 头里的 `x-obs-callback` 让 OBS 存完对象 +再回调 GitCode API,回调失败就返回 `code:400 ... EOF`,而**对象其实已落盘**。 +判定上传成功**只能靠回探下载 URL**,脚本就是这么做的。 + +### 发布后的收尾(必须做完,否则用户装不到) + +```bash +# 1) 索引 PR:CI 绿后合入,合入即自动发布索引 artifact +gh pr merge --repo openxlings/xim-pkgindex --squash --admin + +# 2) 真实验证(注意:不带 @版本 不会升级已装的旧版) +xlings update && xlings install mcpp@$NEW_VERSION -y + +# 3) bootstrap pin 收尾,直推 main +# .xlings.json 的 workspace.mcpp 与 ci-fresh-install.yml 的 MCPP_PIN +bash .github/tools/check_version_pins.sh +git commit -m "ci: workspace mcpp bootstrap pin -> $NEW_VERSION (released, mirrored, indexed)" +``` + +**索引传播有滞后**:索引 artifact 发布后,`latest` tag 上的指针文件在 GitHub +资产 CDN 上可能还要几分钟才更新。紧接着跑的 CI 可能仍拿到旧索引并报 +`package 'mcpp@X.Y.Z' not found` —— 这不是 release 坏了,等指针稳定后重跑即可。 + ### 常见失败原因 | 症状 | 原因 | 修复 | |------|------|------| | `mcpp X.Y.Z-1` 但 tag 是 `vX.Y.Z` | `fingerprint.cppm` 版本未更新 | 更新 `MCPP_VERSION`,重新打 tag | | Smoke test 输出旧版本 | CI 缓存了旧的 sandbox/target | 删除 GitHub Actions cache 后重跑 | -| xlings bootstrap 失败 | xlings 版本不兼容 | 更新 `XLINGS_VERSION` | +| e2e `01_help_and_version.sh` 挂 | 只改了 `mcpp.toml` 没改 `fingerprint.cppm`(它把两者交叉比对) | 同步四处版本;注意这个 e2e 只在部分分片里跑,可能表现为"只有某个平台红" | +| xlings bootstrap 失败 | xlings 版本不兼容 | 改 `src/xlings.cppm::kXlingsVersion`(**唯一真源**)后跑 `check_version_pins.sh` 找出其余 15 个 pin 点 | | macOS/Windows 构建失败 | 需要等 Linux job 先完成 | 检查 Linux job 是否成功 | +| `slim: FAIL: ... still not stripped` | strip 工具没生效/被 pack 覆盖 | 别绕过断言——它就是为了拦住 34.8MB 的 tarball 再次发出去 | +| mirror leg 报 `missing/unverified` | 资产没传上去或还没传播 | 先 GET 核验(**必须 GET,`curl -I` 会骗你**),gitcode 用 `gitcode.com` 直链而非 `api.` 主机;确认缺件后本地补传再 `gh run rerun --failed`(脚本幂等,已验证的资产会跳过) | ### 缓存管理 @@ -191,8 +260,20 @@ gh workflow run release.yml --ref "v$NEW_VERSION" | 文件 | 版本相关内容 | |------|-------------| -| `mcpp.toml` | `version = "X.Y.Z"` — 项目版本 | +| `mcpp.toml` | `version = "X.Y.Z"` — 项目版本,release.yml 由它推导 tag | | `src/toolchain/fingerprint.cppm` | `MCPP_VERSION = "X.Y.Z"` — 编译期版本常量 | -| `.github/workflows/release.yml` | Release workflow 定义 | +| `.xlings.json` | `workspace.mcpp` — CI bootstrap 装哪个 mcpp(发布**后**才 bump) | +| `.github/workflows/ci-fresh-install.yml` | `MCPP_PIN` — 全新安装验证目标(发布**后**才 bump) | +| `src/xlings.cppm` | `kXlingsVersion` — xlings pin 的**唯一真源**(其余 15 处由脚本校验) | +| `.github/tools/check_version_pins.sh` | 机器校验上述两组不变量,别靠肉眼 | +| `.github/tools/slim_linux_payload.sh` | linux 载荷 strip + 断言 | +| `.github/tools/mirror_res.sh` | 双端镜像(并发上传 + leg deadline + 完整性 gate) | +| `.github/tools/gtc` | GitCode CLI(release create/upload、PR) | +| `.github/workflows/release.yml` | Release workflow 定义(四平台 + publish-ecosystem) | | `install.sh` | 安装脚本(随 release 发布) | | `CHANGELOG.md` | Release notes 来源(按 `## [X.Y.Z]` 提取) | + +> **注意版本 bump 的两个阶段**:`mcpp.toml` + `fingerprint.cppm` 在发版**前**改 +> (它们定义要发什么);`.xlings.json` + `MCPP_PIN` 在发版**成功后**改(它们指向 +> bootstrap 用哪个已发布版本)。`check_version_pins.sh` 认得这个差异,不会因为 +> bootstrap pin 落后一版就报错。 diff --git a/.github/actions/bootstrap-mcpp/action.yml b/.github/actions/bootstrap-mcpp/action.yml index 0a13e9e..192746a 100644 --- a/.github/actions/bootstrap-mcpp/action.yml +++ b/.github/actions/bootstrap-mcpp/action.yml @@ -25,7 +25,7 @@ inputs: # `package.name`, so one of the two was simply unreachable — and which one # depended on the machine, which is why CI failed on `compat:lua` on # Windows and `mcpplibs.capi:lua` on Linux. Never pin below that. - default: '2026.7.27.2' + default: '2026.7.28.4' cache-target: description: also restore/save target/ (build artifacts + BMIs) required: false diff --git a/.github/actions/setup-macos-llvm/action.yml b/.github/actions/setup-macos-llvm/action.yml index 4ae107f..d6a33c8 100644 --- a/.github/actions/setup-macos-llvm/action.yml +++ b/.github/actions/setup-macos-llvm/action.yml @@ -15,7 +15,7 @@ inputs: # Floor imposed by the index, not a routine bump — see # .github/actions/bootstrap-mcpp/action.yml for why 0.4.69 is required # (two packages named `lua` in one repo need openxlings/xlings#381). - default: '2026.7.27.2' + default: '2026.7.28.4' runs: using: composite diff --git a/.github/workflows/bootstrap-macos.yml b/.github/workflows/bootstrap-macos.yml index 432db04..9a5495c 100644 --- a/.github/workflows/bootstrap-macos.yml +++ b/.github/workflows/bootstrap-macos.yml @@ -17,7 +17,7 @@ jobs: # Dormant (workflow_dispatch only), but kept in step with the rest — # check_version_pins.sh holds it there. Floor: 0.4.69, below which the # index cannot resolve two packages that share a short name. - XLINGS_VERSION: '2026.7.27.2' + XLINGS_VERSION: '2026.7.28.4' steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/ci-fresh-install.yml b/.github/workflows/ci-fresh-install.yml index 6853f09..f1bab4f 100644 --- a/.github/workflows/ci-fresh-install.yml +++ b/.github/workflows/ci-fresh-install.yml @@ -91,7 +91,7 @@ jobs: env: XLINGS_NON_INTERACTIVE: '1' run: | - curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.7.27.2 + curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.7.28.4 echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH" - name: Install mcpp and config mirror @@ -227,7 +227,7 @@ jobs: - name: Install xlings + mcpp run: | - curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.7.27.2 + curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.7.28.4 # Deliberately NOT writing to $GITHUB_PATH here. On container # images that declare no PATH in their config (opensuse/ # tumbleweed), appending a single dir to GITHUB_PATH makes the @@ -291,7 +291,7 @@ jobs: # (older ones carry minos=15 and refuse to start). # v0.4.51+: in-process sha256 — this image has no sha256sum # binary, so pinned fetches failed before it. - curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.7.27.2 + curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.7.28.4 echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH" - name: Install mcpp and config mirror diff --git a/.github/workflows/ci-linux-e2e.yml b/.github/workflows/ci-linux-e2e.yml index c05fa4b..86e9f1d 100644 --- a/.github/workflows/ci-linux-e2e.yml +++ b/.github/workflows/ci-linux-e2e.yml @@ -123,7 +123,7 @@ jobs: - name: Bootstrap xlings + released mcpp run: | - curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.7.27.2 + curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.7.28.4 export PATH="$HOME/.xlings/subos/current/bin:$PATH" xlings update xlings install mcpp -y -g diff --git a/.github/workflows/cross-build-test.yml b/.github/workflows/cross-build-test.yml index f2ef366..fb1be3c 100644 --- a/.github/workflows/cross-build-test.yml +++ b/.github/workflows/cross-build-test.yml @@ -108,7 +108,7 @@ jobs: # release assets were uploaded in a broken state (records present, # blobs missing → 404 on GET); re-uploaded clean. The stale-INDEX # half is handled by the marker-clear below. - XLINGS_VERSION: '2026.7.27.2' + XLINGS_VERSION: '2026.7.28.4' run: | tarball="xlings-${XLINGS_VERSION}-linux-x86_64.tar.gz" curl -fsSL -o "/tmp/${tarball}" \ @@ -245,7 +245,7 @@ jobs: - name: Bootstrap mcpp via xlings env: XLINGS_NON_INTERACTIVE: '1' - XLINGS_VERSION: '2026.7.27.2' + XLINGS_VERSION: '2026.7.28.4' run: | tarball="xlings-${XLINGS_VERSION}-linux-x86_64.tar.gz" curl -fsSL -o "/tmp/${tarball}" \ diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e8a7e74..0328f86 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -96,7 +96,7 @@ jobs: # Pin xlings to a known-good version. The upstream install # script always grabs `latest` (no version override), so we # download + self-install manually to avoid broken releases. - XLINGS_VERSION: '2026.7.27.2' + XLINGS_VERSION: '2026.7.28.4' run: | if [ ! -x "$HOME/.xlings/subos/default/bin/xlings" ]; then tarball="xlings-${XLINGS_VERSION}-linux-x86_64.tar.gz" @@ -288,7 +288,7 @@ jobs: - name: Bootstrap mcpp via xlings env: XLINGS_NON_INTERACTIVE: '1' - XLINGS_VERSION: '2026.7.27.2' + XLINGS_VERSION: '2026.7.28.4' run: | tarball="xlings-${XLINGS_VERSION}-linux-x86_64.tar.gz" curl -fsSL -o "/tmp/${tarball}" \ @@ -358,11 +358,11 @@ jobs: # below are pinned to the same version as XLINGS_VERSION; they are # NOT interpolated from it, so check_version_pins.sh scans for them # explicitly (they were absent from the old lock-step comment). - XLA="xlings-2026.7.27.2-linux-aarch64.tar.gz" + XLA="xlings-2026.7.28.4-linux-aarch64.tar.gz" if curl -fsSL -o "/tmp/$XLA" \ - "https://github.com/openxlings/xlings/releases/download/v2026.7.27.2/$XLA"; then + "https://github.com/openxlings/xlings/releases/download/v2026.7.28.4/$XLA"; then tar -xzf "/tmp/$XLA" -C /tmp - XLBIN=$(find /tmp/xlings-2026.7.27.2-linux-aarch64 -path '*/bin/xlings' -type f | head -1) + XLBIN=$(find /tmp/xlings-2026.7.28.4-linux-aarch64 -path '*/bin/xlings' -type f | head -1) if [ -n "$XLBIN" ]; then mkdir -p "$STAGING/$WRAPPER/registry/bin" cp "$XLBIN" "$STAGING/$WRAPPER/registry/bin/xlings" @@ -440,7 +440,7 @@ jobs: - name: Bootstrap mcpp via xlings env: XLINGS_NON_INTERACTIVE: '1' - XLINGS_VERSION: '2026.7.27.2' + XLINGS_VERSION: '2026.7.28.4' run: | if [ ! -x "$HOME/.xlings/subos/default/bin/xlings" ]; then WORK=$(mktemp -d) @@ -622,7 +622,7 @@ jobs: shell: bash env: XLINGS_NON_INTERACTIVE: '1' - XLINGS_VERSION: '2026.7.27.2' + XLINGS_VERSION: '2026.7.28.4' run: | # Captured before the `cd` below, in POSIX form: this step never # returns to the workspace, and GITHUB_WORKSPACE is a backslash diff --git a/docs/00-getting-started.md b/docs/00-getting-started.md index 5f02f4c..ca57b56 100644 --- a/docs/00-getting-started.md +++ b/docs/00-getting-started.md @@ -26,7 +26,7 @@ Once installation is complete, start a new shell session or run `source ~/.bashr ```bash mcpp --version -# mcpp 0.0.1 +# mcpp 2026.7.29.1 ``` > [!TIP] diff --git a/docs/zh/00-getting-started.md b/docs/zh/00-getting-started.md index 992466d..3789518 100644 --- a/docs/zh/00-getting-started.md +++ b/docs/zh/00-getting-started.md @@ -28,7 +28,7 @@ curl -fsSL https://github.com/mcpp-community/mcpp/releases/latest/download/insta ```bash mcpp --version -# mcpp 0.0.1 +# mcpp 2026.7.29.1 ``` > [!TIP] diff --git a/src/xlings.cppm b/src/xlings.cppm index 3e108ae..c94a538 100644 --- a/src/xlings.cppm +++ b/src/xlings.cppm @@ -42,7 +42,7 @@ namespace pinned { // in lock-step by hand; that list was already missing both composite // actions, which is how CI's sandbox sat on 0.4.30 unnoticed while // everything else had moved on. Don't reintroduce a hand-maintained list. - inline constexpr std::string_view kXlingsVersion = "2026.7.27.2"; + inline constexpr std::string_view kXlingsVersion = "2026.7.28.4"; inline constexpr std::string_view kNasmVersion = "3.02"; }