Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -260,3 +260,11 @@ strip = "symbols"
# packages (docs/mobile-rn.md §6).
[profile.release.package.voltip-mobile-rn]
strip = false

# voltip-server as one codegen unit is one LLVM module, and LLVM spends about 14 minutes optimising
# it (2026-11-10, -Z time-passes: LLVM_passes 862.7 s, every other pass under a second), plus 5 in
# the ThinLTO link; the release candidate's Linux leg waited 19–34 minutes for it. In 16 units, at
# -j4 as on the runner, the library takes 2 s and the binary 26 s. ThinLTO still optimises across
# the units. Every other package keeps the single unit above.
[profile.release.package.voltip-server]
codegen-units = 16
2 changes: 1 addition & 1 deletion docs/runbook.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ Relay 无状态(内存里只有活动会话 / 频道),可水平扩展前
工作流都跑在 GitHub 托管的 runner 上:

- `ci.yml`:push `main` / PR → `changes`(`.github/scripts/changed-code.sh`:只改了 `docs/**`、`*.md`、`LICENSE*` 时 `code=false`;新分支、API 失败或一次推送 300 个以上文件都算改了代码)→ 并行的 `verify-rust`(`VERIFY_GATES=rust`:格式、features、clippy、交叉检查、覆盖率下跑一遍测试、cargo-deny、IPC e2e)与 `verify-web`(`VERIFY_GATES=web`:web 门禁、台账、主机名守卫、发布脚本测试,外加带 `VOLTIP_PRODUCTION_HOSTS` 的守卫;fork 与 Dependabot 的 PR 没有 secrets,跳过这一步)、`codecov`(上传覆盖率,只做报告,不阻塞)、`windows-cross`(`make windows-x64`,无内置服务)→ `windows-native`(Windows Server 上无头运行便携包与安装后的 exe)、`hooks-windows`(Windows 桌面上真实的单键钩子)、`smoke-desktop`(Xvfb 与纯 Wayland 冒烟、X11 真实钩子、无头识别)、`android`(对 Android 目标跑 clippy;用 `scripts/build-android-rn.sh --unsigned` 构建 React Native 版未签名的 release APK 与 AAB,用当次生成的临时密钥签名,再跑与候选相同的包检查)→ `android-device`(把这个 APK 装进 Android 15 模拟器并启动:首屏出现、20 秒内不退出、日志里没有致命错误,`.github/scripts/android-device-smoke.sh`)、`ci-success` 聚合(CI 的总结论);另有 `candidate-status` 给不是发布 PR 的 PR head 写 `Release candidate = success`(见下面的 ruleset)。只改文档时 `verify-web` 照常跑,其余构建、测试、平台 job 跳过;`ci-success` 只在 `changes` 判定为只改文档时接受跳过,其他任何跳过、失败或取消都判失败。CI 不注入任何内置引擎值。
- CI 的速度(2026-09-28 实测后调整):Rust 测试只在覆盖率门禁里跑一遍(原先 `cargo test` 与 `cargo llvm-cov` 各编一遍、各跑一遍,各约 170 秒);`verify` 拆成可并行的两半;Cargo 缓存只从 `main` 保存(PR 的缓存只有同一个 PR 能用,而仓库 10 GB 的上限会把 `main` 的挤掉),不缓存 `~/.cargo/bin`;dev / test 构建只留行号表(`CARGO_PROFILE_DEV_DEBUG=line-tables-only`);清理预装 SDK 只在剩余空间不足 40 GB 时做(`.github/scripts/free-disk-space.sh`,托管 runner 实测开跑时有 86 GB);CI 的 Windows 包复用按全部输入(锁文件、清单、`about.toml`、生成脚本与许可证文本)缓存的第三方声明,省掉约两分钟的 cargo-about(`VOLTIP_NOTICES_CACHED=1`,发布总是重新生成);下载失败重试(`CARGO_NET_RETRY`、`RUSTUP_MAX_RETRIES`);桌面壳的 lib 只编成 `rlib`(2026-10-05):Tauri 模板为手机准备的 `staticlib` 和 `cdylib` 让 release 构建的每个依赖都同时生成机器码和 bitcode,去掉后依赖只生成 thin LTO 用的 bitcode(`-C linker-plugin-lto`),本机 32 核冷构建 224 → 156 秒,target/ 3.3 → 2.4 GB;macOS 腿的钥匙串测试程序是带 `keychain-harness` feature 的 bin 而不是 example(example 会带上 dev-dependencies,它们的 feature 让应用构建的 60 多个 crate 重编一遍,Intel Mac 冷跑时 11 分钟),应用构建之后只需再编这个包本身。`verify-*.log` 里每道门都记了耗时(`secs=`)。
- CI 的速度(2026-09-28 实测后调整):Rust 测试只在覆盖率门禁里跑一遍(原先 `cargo test` 与 `cargo llvm-cov` 各编一遍、各跑一遍,各约 170 秒);`verify` 拆成可并行的两半;Cargo 缓存只从 `main` 保存(PR 的缓存只有同一个 PR 能用,而仓库 10 GB 的上限会把 `main` 的挤掉),不缓存 `~/.cargo/bin`;dev / test 构建只留行号表(`CARGO_PROFILE_DEV_DEBUG=line-tables-only`);清理预装 SDK 只在剩余空间不足 40 GB 时做(`.github/scripts/free-disk-space.sh`,托管 runner 实测开跑时有 86 GB);CI 的 Windows 包复用按全部输入(锁文件、清单、`about.toml`、生成脚本与许可证文本)缓存的第三方声明,省掉约两分钟的 cargo-about(`VOLTIP_NOTICES_CACHED=1`,发布总是重新生成);下载失败重试(`CARGO_NET_RETRY`、`RUSTUP_MAX_RETRIES`);桌面壳的 lib 只编成 `rlib`(2026-10-05):Tauri 模板为手机准备的 `staticlib` 和 `cdylib` 让 release 构建的每个依赖都同时生成机器码和 bitcode,去掉后依赖只生成 thin LTO 用的 bitcode(`-C linker-plugin-lto`),本机 32 核冷构建 224 → 156 秒,target/ 3.3 → 2.4 GB;macOS 腿的钥匙串测试程序是带 `keychain-harness` feature 的 bin 而不是 example(example 会带上 dev-dependencies,它们的 feature 让应用构建的 60 多个 crate 重编一遍,Intel Mac 冷跑时 11 分钟),应用构建之后只需再编这个包本身;voltip-server 的 release 构建单独用 16 个代码生成单元(2026-11-10,根 `Cargo.toml`):只有一个单元时整个 crate 是一个 LLVM 模块,LLVM 优化要 862 秒、ThinLTO 链接 303 秒,候选的 Linux 腿为此等 19–34 分钟;拆开后 4 个并行任务下分别是 2 秒和 26 秒,其余包仍是一个单元。`verify-*.log` 里每道门都记了耗时(`secs=`)。
- `ci.yml` 的 `macos` job(2026-09-28 从 `macos.yml` 并入):推送 `main` 或手动运行时在 `macos-15`(Apple 芯片)与 `macos-15-intel`(Intel)上构建 ad-hoc 签名的 `.app` 和 `.dmg`(发布包用固定证书,见下面「macOS 签名」),用 `.github/scripts/check-macos-bundle.sh` 检查,并确认发布用的检查会拒绝这个 ad-hoc 包,跑 macOS 单元测试、真实的事件 tap(仅 Apple 芯片,先在 TCC 里给测试程序授予辅助功能)、无头识别,以及桌面上的 `scripts/smoke-tray-macos.sh`(标题栏左端的内容离红绿灯至少 12 pt,菜单栏图标、菜单与各项操作,截图随产物保存);不跑在 pull request 上。在 push 和手动运行时 `CI Success` 等它(规则在 `.github/scripts/ci-success.sh`,只有 pull request 上允许它被跳过),所以 `main` 上任何一台 Mac 失败,下一个候选都过不了 `source-gate`;Cargo 缓存从 `main` 保存。
- release-please 的 PR(作者 `github-actions[bot]`、分支 `release-please--branches--main--*`、标签 `autorelease: pending`)和它合并到 `main` 的发布提交只改版本号和 CHANGELOG,只跑 `verify-web`:候选在同一个 head 上构建并检查每个安装包,而 head 的基点已经通过 CI(`.github/scripts/changed-code.sh`)。同样的改动换个作者或没有标签,照常跑完整 CI。
- 发布是「构建一次再晋升」(2026-09-28 用户选定):安装包在发布 PR 上构建、签名、证明并封存,合并后只校验和发布,不再编译。
Expand Down
16 changes: 16 additions & 0 deletions scripts/release/test_release_workflows.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import json
import re
import tomllib
import unittest
from pathlib import Path

Expand Down Expand Up @@ -623,6 +624,21 @@ def test_regression_the_appimage_carries_an_apprun_every_user_can_run(self) -> N
self.assertRegex(code, r"(?m)^for tool in [^\n]*\bunsquashfs\b")


class ServerPackageBuild(unittest.TestCase):
"""The release build of voltip-server (scripts/build-server-linux-x64.sh, the candidate's Linux
leg)."""

def test_regression_voltip_server_builds_in_more_than_one_codegen_unit(self) -> None:
# Regression (0.3.1 candidate 42733161564, 2026-11-10): the Linux leg spent 19.3 minutes in
# "Build and package voltip-server", 27.7–34.3 in earlier candidates. As one codegen unit
# the crate is one LLVM module: `-Z time-passes` measured LLVM_passes 862.717 s for the
# library (every other pass under a second) and the ThinLTO link took 302.7 s. With 16
# units, at -j4 as on the runner: 2.0 s and 25.6 s. Every other package keeps one unit.
profile = tomllib.loads((ROOT / "Cargo.toml").read_text(encoding="utf-8"))["profile"]["release"]
self.assertEqual(profile["codegen-units"], 1)
self.assertEqual(profile.get("package", {}).get("voltip-server", {}).get("codegen-units"), 16)


class WindowsPackageScript(unittest.TestCase):
"""scripts/build-windows-x64.sh (`make windows-x64`), which ci.yml's windows-cross job and the
candidate's Windows leg run, bundles NSIS with the bundler's tools already in place."""
Expand Down
Loading