跳到主要内容

桌面升级、回退与 E2E 维护

升级的目标是缩短关闭应用到重新可用之间的时间。下载、解压、组件组合及插件运行目录准备均在当前应用仍可用时完成;只有目标环境准备完整,才提示重启。主程序和匹配组件作为一个完整版本切换,用户数据独立保存。

清单兼容和升级路径​

正式发版先构建候选包并完成验证,再生成升级清单,最后创建版本 tag 和 Release。 验证或清单生成失败时不会占用版本 tag。macOS arm64 和 Windows x64 独立运行 实际发布包的升级与回退验证;macOS x64 复用 arm64 通过的版本路径和最低来源版本, 不再在发版中运行升级与回退 E2E。x64 记录保留自身包哈希及下载地址,并通过 verification.kind=architecture-equivalence、arch=arm64 和 arm64 来源/目标包哈希 注明证据来源。来源和目标的源码提交必须分别与 arm64 相同;缺少匹配的历史 x64 包记录时阻止发布,不把 arm64 包哈希当作 x64 包哈希。普通 PR 不运行打包升级 E2E。 下文逐架构实际包验证规则在正式发版中适用于 macOS arm64 和 Windows x64; macOS x64 使用上述明确的架构等价规则。

继续使用既有 Electron YAML 和 components-<channel>-<platform>-<arch>.json,不更换发现地址、不改变原字段含义。组件清单新增 upgradePolicy,其中每个目标版本声明 minSourceVersion,并记录明确的来源版本、目标版本、交付包哈希及升级和回退 E2E 证据。

旧客户端忽略新字段,继续直升旧清单中声明的最新版。路径约束从客户端包含新实现开始生效;不将改造前的旧版本纳入新 E2E 矩阵,也不把旧渠道固定到桥接版。

minSourceVersion 是约束,不是兼容证明。即使 A 高于最低版本,没有通过验证的 A → B 边也不能升级。客户端选择通往所选渠道最新可达版本的最短路径,每一跳单独确认。测试中的 B 只需比 A 新,不要求 B 是全局最新版。

撤销版本或升级边会阻止新安装;已下载的更新也会在切换前重新检查。没有路径时显示明确原因,不退回不受约束的直升逻辑。

准备、切换与恢复​

随更新包交付修复步骤​

更新修复由新包自带的 release-preparation-cli 执行,与主程序一起经过完整性和签名校验; 不下载并执行独立的远程修复脚本。修复发生在目标准备完成、提示重启之前,必须明确适用来源、 检查前置条件、支持重复执行,并将阶段和结果写入准备日志。失败阻止继续安装。

0.6.2、0.6.3 和 0.6.4-beta.1 的默认启动入口读取工作台根目录下的 releases, 而更新器写入 user-data/releases。目标准备程序为这几个已交付版本建立物理目录相同的目录交接, 并核对来源包身份、发起更新的父进程可执行文件和当前 profile 所有权。只有事务的 trial 匹配且没有该 token 的启动尝试、 打开数据、成功或失败标记时,才归档事务并恢复来源选择;不恢复快照、不移动运行中的用户数据。 来源不能读取目标数据格式时,必须先安装兼容的修复版本,不能直接进行数据格式升级。

新版启动入口在转交给这些旧来源时内部传递已验证的用户数据目录,使旧入口读取正确的 profile; 用户不需要设置环境变量。其他目录或身份冲突、已经尝试过的激活均不能走上述自动撤销路径。 下载、解包或新包准备入口本身已经不可用的客户端,仍需要完整安装包救援。

  • releases/slots/<id> 保存完整主程序、运行时缓存和准备好的插件 profile。目标包自己的准备入口执行准备工作,不使用旧版代码推测新版要求。
  • active 是启动器选择的版本指针;激活日志记录来源、目标、快照与试运行标识。原生启动器不加载目标版本业务代码。
  • 确认更新后先停止所有数据写入者,再保存迁移数据快照,随后退出并切换。后台复制运行中的数据库不能替代一致性快照。
  • 停止 Executor 或 app-server 时保留活跃 Goal 的恢复日志。上一回合已完成不代表 Goal 已完成;退出通知或通知流关闭不能用旧回合结果提前结束 Goal。
  • 运行时和主界面都就绪后确认健康。试运行退出或 60 秒未就绪,启动器进入恢复流程,不循环自动重启。
  • 已确认的手动回退独立记录事务方向;恢复中断后继续完成回退,不使用目标版本上一次的健康标记取消回退。
  • 旧版可以读取现有数据时直接切回;目标打开数据后发生不兼容失败,则先询问是否恢复快照。恢复前保留更新后的数据。目标在打开数据之前退出,可直接回退。
  • 快照注册表只包含迁移拥有的存储,包括任务 SQLite 及其 WAL/SHM、桌面偏好、持久化 renderer storage 和会话同步状态。新增迁移存储时必须同步更新注册表与恢复测试。源码仓库、云端记录及个人凭据不在恢复范围内。
  • 不兼容恢复还保留被回退版本的完整槽位,避免后续清理删除新版用户插件数据。preserved-data/<snapshot>/retained-release 记录对应槽位;保留的数据不自动过期。
  • 插件配置在准备期间变化会使准备结果失效;切换前再次核对,禁止重启后再补做大规模准备。
  • 克隆当前配置时只解析配置根指针,复制实际目录并保留内部依赖链接;不能把活动根链接复制成回退配置,否则旧版准备会修改运行中的新版配置。调用旧包的准备入口时传入解析后的实际配置路径,使尚未修复克隆逻辑的旧包也能获得独立副本。

三层测试,分别维护​

macOS 安装路径与 Dock 身份​

macOS 更新保留用户原安装位置的 .app 外层目录和 inode。完整、不可变的签名包仍保存在 版本槽位;准备阶段在安装所在卷上复制并校验签名,在停写后的受监督启动中原子交换 Contents,再从原安装路径启动。不能用应用或 Contents 符号链接代替物理目录, 也不修改用户 Dock 偏好。无法唯一确定安装位置、身份不匹配或无法写入安装卷时阻止准备。 旧客户端从版本目录运行时,优先使用上一健康版本记录中的原安装路径;不能从多个同名应用中猜测。 若该路径仍保存更早的健康版本,先保留其签名程序副本并更新该非活动版本的程序引用。 准备期间不替换外层应用中的任何程序文件,当前版本及之前的回退版本均保持可用。

已交付的启动器仍先进入目标槽位中的启动入口,由新包的原生助手完成安装路径修复, 再由原生中继以新 PID 启动安装位置的主程序。不能在同一 PID 内重新执行 Electron: RunningBoard 缓存的 PID 版本可能失效,控制中心会以 process has mismatched pid version 拒绝菜单栏图标的注册。槽位入口在交接前隐藏 Dock 身份,中继保留旧启动器监督的进程树, 直到既有健康标记确认或目标退出;目标失败仍由原激活事务处理。 旧来源建立独立的回退程序副本,引用原来源的数据所有者; 激活时使用已有快照保留协议保护这些数据,使旧版清理器也不会删除回退后的 profile。 目标启动入口成功加载且版本匹配后,在打开数据前接管恢复转交;旧启动器缓存的版本目录入口 也会先转交到新包的恢复代码,再恢复原安装位置。这个转交不确认运行时或界面健康。 准备不更改活动来源记录,取消准备只清理带有本存储所有权标记的暂存目录。

套件 v8 在共享升级与回退场景中额外核对真实 NSRunningApplication 的应用 URL、 bundle identifier 和外层目录 inode,并在回退后运行来源包自己的清理器,再续接原任务。 套件 v10 直接下载实际旧包,保留其启动入口、版本存储和原生启动器;不重建历史源码或重新实现旧行为。 故障激活场景让旧启动器实际通过签名的来源版本目录启动,验证缓存恢复入口的旧客户端。 这些机制证据不能代替实际交付包哈希绑定的发布版本对证据。

套件 v10 进一步核对升级和回退后系统实际托管的原生菜单栏图标,不能仅断言 Electron 已创建 Tray 对象。过去已固定到版本槽位的 Dock 图标需要用户移除并重新固定安装位置; 应用不会修改用户的 Dock 偏好。

release-package-startup 保留真实发布包的首次冷启动,不预热运行时缓存。Windows CI 的原始 日志记录了 145 秒的运行时解包和约 192 秒后的控制器连接,因此该场景按组件准备、运行时解包、 Core profile 准备、Core 进程启动和渲染器加载分别执行原有 180 秒预算。阶段停滞、倒退或 超出单阶段预算仍失败,准备日志不能代替真实控制器连接。普通启动、重启和升级场景的原有 等待预算保持不变。

层级数据来源验证内容能否开放正式升级边
策略与事务测试小型清单和临时文件目录最低来源版本、路径、撤销、激活日志、快照恢复边界否
机制回归 E2E已构建的真实版本对真下载、真解压、真 Electron/Executor、切换、恢复、任务继续执行否,故障注入结果不能授权生产边
发布版本对 E2E不可变的实际来源包和本次交付目标包指定版本对的完整升级与回退是,且仅限该平台、架构和包哈希

场景集中在 app-upgrade.scenario.mjs,套件版本和场景列表集中在 upgrade-suite.mjs。四个 checkpoint 分别检查正常升级、包含升级的手动回退、已确认回退被中断后的恢复及目标进程启动失败后的恢复;每个 checkpoint 建立自己的最小数据,不能依赖上一个场景。

套件 v5 分别限制整包准备、解压和运行环境准备阶段,每阶段最多 5 分钟;阶段必须单向前进,停滞或失败立即终止,不能把单个步骤的预算误作所有串行操作的总预算。目标包将 profile 复制、组件准备、运行环境物化及 profile 准备的开始、结束和耗时写入 logs/release-preparation.log,CI 必须保留该日志。

套件 v10 的共享 runner 只接受预构建版本对;缺少产物立即失败,不执行编译、打包或签名。新版复用发版构建的候选归档,旧版直接下载不可变发布包,核对版本、源码提交和 SHA-256。版本号是输入数据,不决定断言分支。只允许模型服务替身;发布文件由真实 HTTP 服务提供,下载、签名校验、解压、存储、原生启动器及 Executor 都执行实际实现。故障场景终止真实目标进程,不伪造“回退成功”。

每个场景先通过来源包自己的无界面准备入口建立“已安装客户端”的运行环境,再开始 UI 操作;不重复把冷安装当作升级步骤。目标包仍须自行解压并准备独立版本槽位。升级和回退后逐项核对 host、Core、插件、executor、Codex 和 DWS 的实际路径与该槽位的准备结果,禁止继承来源包的固定路径覆盖。回归夹具写入独立输出目录,不覆盖正式包或同一 runner 中其他 checkpoint 的应用。

数据兼容性来自真实包的声明。不兼容版本对必须确认快照恢复,并检查保留的新数据;不能重命名现有归档、改写包身份或重签旧包来伪造版本对。发布门禁仍拒绝将 regression 结果提升成正式边。

日常修改与执行​

node --test wework/scripts/upgrade-policy.test.mjs wework/scripts/upgrade-evidence.test.mjs
pnpm --dir wework/electron test src/runtime/release-store.test.ts src/runtime/release-snapshot.test.ts src/runtime/release-profile.test.ts
pnpm --filter wework e2e:desktop -- --parallel-segments upgrade-and-rollback

通过 WEWORK_E2E_UPGRADE_PAIR 提供已校验的版本对;runner 从来源包解析应用与 executor,不自动构建。设置 WEWORK_E2E_REQUIRE_RELEASE_PACKAGE=1 保留包身份和签名。真实应用标识的默认目录测试需要干净的操作系统用户;发现已有原生应用数据时立即停止,不能清理个人数据来运行测试。

维护规则:

  1. 改行为时修改共用场景;发新版本时修改版本对配置,不复制测试代码,也不把历史用例自动改指向最新版。
  2. 接受标准有实质变化时增加套件版本,使旧证据不能为新边背书。
  3. 每次失败保留完整日志,定位并修复后再运行;不以重试、跳过或削弱断言获取通过。
  4. macOS arm64 和 Windows x64 独立验证。macOS x64 仅采用前述源码一致、保留自身包哈希的架构等价发布证明。
  5. 截图、测试包、快照、会话目录和临时恢复数据均不提交仓库,CI 仅上传经过筛选的诊断与结果文件。

升级 E2E 只由 Wework App 发版流程执行,包括不发布的构建验证;普通 PR 和 ci:all 不执行升级专项。发版门禁调用共享 upgrade-and-rollback 组,全部通过才生成并推广精确版本对的升级策略。接受标准版本统一由 upgrade-suite.mjs 管理,不能复用旧套件证据为新边背书。

套件 v7 的 app-upgrade 使用隔离 Home 下的正常默认目录,并执行升级和回退。 它在停写后复用正式快照、profile 保留和激活事务建立旧版未启动状态,验证重启后旧版仍可用、 新包自动恢复事务并保留任务,再完成升级、续聊和回退。 测试 runner 的初始应用环境采用系统会话与测试控制/模型替身白名单,不传入产品目录、应用标识、二进制路径或更新源覆盖。 套件 v10 保留实际下载的旧版启动入口,不重建历史源码。测试驱动在自己启动的子进程进入应用入口前, 将默认更新目录请求导向真实本地 HTTP 服务;不传入更新源或其他产品配置覆盖,不关闭 TLS 或签名校验。 较旧来源与上一发布版同时可用时,通过两个包各自的准备入口建立未启动事务,保留原 profile 和组件所有权断言。

套件 v11 删除与 app-upgrade 执行同一场景的重复 app-update-full checkpoint。慢速整包传输、请求不阻塞、禁止 Range/blockmap 和重复准备复用的断言仍由共用场景在四种升级/回退检查中执行。串行验证中一个版本对的任一检查失败后立即拒绝该版本对,保留原始诊断,继续验证策略要求的其他来源,不为失败版本对生成升级边。

套件 v13 将健康升级和旧版未启动事务检查合入 app-rollback,完整执行升级、续聊、手动回退及原有断言,不再另跑相同的 app-upgrade 前半程。app-upgrade-recovery 和 app-rollback-recovery 仍独立执行真实故障恢复。后续安装包的准备只用于未启动事务检查,不在未使用它的故障场景中重复执行。

0.6.2 与旧 beta 在下载目标前会复制宿主并准备 slot 内的回退 profile。此时来源记录并非正在运行的程序路径。无激活事务时,恢复入口仅接受已安装来源所属 slot 内的宿主与 profile,要求默认 live profile、准备记录中的配置版本一致,并逐一核对运行中父宿主与副本的 EXE 和 app.asar 哈希。带激活事务时仍要求原有直接所有权,不允许用副本关系取消事务。

macOS 保留回退源时,新 release slot 的 managed-components 必须绑定到原不可变程序目录,且 prepared.json 的组件路径使用新 slot;这样忽略 componentDataDirectory 的旧启动器也能选择同一组合。保留源声明 retainedRelease 以防清理原 slot。旧布局的未启动事务前置只用于已确认使用旧选择器的发布版本;0.6.4-beta.2 起的选择器会正确启动待激活包,不能再断言其继续运行旧版本。所有来源仍运行完整升级、任务续聊与回退检查点。

Windows 的物理宿主包与运行时解包共用隔离子进程,调用 %SystemRoot%/System32/tar.exe;其他平台使用锁定的 node-tar。包大小、SHA-256、运行时身份与签名检查保持独立。保留来源、清理、下载、宿主解包、签名和目标准备分别记录阶段耗时,不能将完整准备时间归为解压。

已安装来源的测试前置使用共享 runner 的运行时安装器,从其原始包校验大小和 SHA-256 后安装不可变缓存,再调用该来源自带的准备入口生成组件和可变 profile。缓存安装耗时计入验证;不修改旧包、签名或程序入口,首轮目标仍从自己的交付归档准备不可变程序。相同指纹的 Core/Workbench 角色只解包一次,两个角色都检查运行时身份。

正式版本对验证按完整运行时描述(包含归档 SHA-256、大小、版本、指纹及角色)在当前作业的临时目录中复用运行时文件,各 checkpoint 通过目录链接使用这些文件,并保留独立的运行时目录清单和可变 profile。每次使用仍检查包内运行时归档的大小、SHA-256 和角色身份;缓存未完整安装或校验失败时直接失败,不重试解包。场景清理不能删除共享缓存;整个作业结束后统一清理,清理时间同样计入完整验证。

目标运行时的不可变程序在 .prepared 存储中按指纹、版本、交付归档 SHA-256 与大小共同寻址,由目标自己的准备入口在首轮创建;后续 slot 仍校验其交付归档,然后绑定同一程序目录。该存储不向来源运行时清单发布未来版本,各 slot 仍保留独立角色清单及 profile。CI 在同一来源分片的串行检查点之间复用这个不可变程序存储,首次准备与最终清理均计入完整耗时,不额外预热目标。

CI 先冻结完整来源清单,再按平台、渠道及来源分片,最多使用 8 个 runner。启动检查点前完成来源不可变运行时缓存,后续读取仍校验交付归档,但不重写共享清单。每组检查点保持串行。Windows 即使 HOME 独立,原生旧数据目录与 Electron 单实例身份仍共享;macOS 则替换同一个应用包。Stable 目标同时验证 Stable/Beta,Beta 目标只能验证 Beta。汇总必须收到全部来源结果,拒绝缺失、重复及身份不符的证明。完整执行低于 10 分钟,包含输入解析、下载、准备、全部场景、清理、上传与汇总;不计外部 runner 排队,仍计算 8 并发上限下的额外执行波次。构建和签名单独计时,发布前按实际完成结果再次验收。诊断不生成升级边,也不能证明完整预算通过。

诊断需要新包时可设 build_only=true,只生成不可变构建输入,再用 verification_run_id 执行非发布重放。该模式禁止发布,不自动启动升级矩阵,也不生成升级兼容证据;普通发布与默认 dry run 仍需完整升级门禁。

清理器必须保留 electron-logs 和 release-logs, 以便从目标 executor 的原始日志区分启动失败、健康检查超时和回退;不得因缺少日志而猜测修改启动行为。 隔离 E2E 的启动诊断还监测主线程心跳;连续 5 秒无心跳时记录一次调用栈位置并恢复执行。 仅记录函数名、文件位置和行列,不读取局部变量、参数或源码;正常启动完成后停止监测。 未捕获异常观察器同步保留错误信息,不接管原有异常处理或退出行为。 Windows 原生子进程的工作目录必须使用扩展长度路径,涵盖 profile 校验和受监督的运行时启动。 命令执行器同时处理进程与标准流错误,保留原始启动错误;失败后停止进程树再返回,成功则等待标准流关闭。

升级边显式记录 fromSourceSha 和 toSourceSha,必须分别匹配交付包元数据中的 sourceSha;E2E 结果同时记录这两个提交号。缺失或不匹配的提交号不能晋升,客户端还会校验下载包内的提交号。诊断日志写入失败仅输出诊断错误,不阻止实际准备,也不能覆盖准备失败的原始原因。原生启动器在超时恢复数据前必须终止完整运行时进程树,包括独立进程组中的写入进程。

原生 launcher 的链接器​

打包脚本直接调用 rustc 编译 launcher,因此必须将目标对应的 CARGO_TARGET_<TARGET>_LINKER 环境变量显式转换为 -C linker=<path>;其中目标名称转为大写, 连字符替换为下划线。例如 Windows x64 使用 CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_LINKER,其值应指向 MSVC 的 link.exe。 直接调用 rustc 不会读取 Cargo 的这项配置;仅配置 Cargo 无法避免 Git Bash 中同名工具的冲突。 未配置链接器时保留 Rust 的默认选择;显式配置为空或无效时让构建失败,与 Cargo 保持一致。

node --test wework/scripts/build-launcher.test.mjs 真实编译并启动 launcher,验证 PATH 中优先出现 Git link.exe 时仍使用配置的链接器,并检查无效配置不会被忽略。Windows 使用 Git 自带的真实 link.exe,macOS/Linux 使用原生冲突程序覆盖默认的 cc。该测试由构建验证负责,不在升级场景中重复编译。

发布版本对​

维护 CI 时,工作区依赖缓存还必须按绝对目录区分:pnpm 的依赖状态记录包含绝对项目路径, 宿主机与容器共用缓存会在服务启动期间触发重装。main 的平台 E2E 作业负责填充容器缓存。 已下载完整应用产物的 Windows 桌面分片直接使用打包依赖;原生启动验证另外安装 Electron。 并行 Rust 测试使用检入的可执行脚本夹具,避免新写入脚本的写句柄被 fork 继承后触发 ETXTBSY。 协作看板执行地址持久化后,原生会话仍可能正在启动;先在运行时启动预算内确认请求到达模型, 再开始独立的 10 秒界面断言预算,避免将会话准备时间计入界面响应时间。

wework/upgrade-policy.json 只维护产品允许的最低来源约束,不需要每次手填来源版本。每次发布按平台、架构和目标渠道读取线上升级目录,使用该渠道上一版记录的 minSourceVersion 作为固定起点 X,并且不低于仓库约束。Stable 清单只记录 Stable 版本和起点;Beta 清单可以记录 Stable 和 Beta,且在尚无 Beta 历史时可以从 Stable 建立第一条验证路径。Stable 不会导入 Beta 来源或升级边。

修复版本可以通过 requiredDirectUpgrades[目标版本] 声明必须实际验证的直达来源。 0.6.4-beta.2 要求从 0.6.2、0.6.3、0.6.4-beta.1 直接升级及回退成功, 避免仍然把用户引导到已知有问题的中间版本。与既有起点和上一版去重,每个来源只验证一次; 指定来源失败时阻止发布,不能重试以获取通过,也不能写入未经验证的边。该配置只影响指定目标版本。

CI 顺序验证 X → 目标版、上一版 → 目标版;两者相同时只运行一次。验证必须启动实际交付包,经真实界面升级并打开目标主界面,确认原任务和插件配置保留、任务可以继续执行,再回退到来源版本并确认可用。仅启动进程、解包或健康接口成功不能作为通过证据。

固定起点 X上一版发布决策
通过通过保留 X,生成两条实际验证的升级边
失败或尚未登记为可验证来源通过把最低支持版本提高到上一版,只生成通过的边
任意结果失败阻断发布,保留线上清单不变

来源包下载、权限、目录格式或哈希校验异常直接阻断,不视为版本兼容失败。已撤销版本和回归夹具不能作为来源。首次支持新协议、确实没有历史目录的版本以自身版本建立起点;已有历史却找不到合格上一版时必须报错,不能重新作为首次发布。不能因为 X 通过就推断所有中间版本都兼容;上一版必须独立实测,保留已有升级边和中转包以维持连续升级路径。

成功后将确认的最低来源和精确升级边写入目标渠道的 upgradePolicy,随不可变版本资产发布,再推广滚动清单。下一次发布从该清单读取 X,自动沿用或提升起点,不回写源码中的版本列表。Stable 发布分别生成 Stable 和 Beta 的验证记录,Beta 发布只推广 Beta。所有平台作业成功才执行发布;任何必需版本对失败都不会推广清单。CI 始终保存决策摘要和失败日志,区分 X 不可用、验证失败和发布阻断,不通过重试掩盖失败。

旧包解压目录必须先解析为实际路径,避免 macOS 的 /var、/private/var 等别名导致包身份校验失败。候选包在验证前作为 CI artifact 保存,验证证据另行上传;发布作业仍须等待所有平台验证成功,并校验证据后才推广清单。这样失败时可直接下载同一份签名包复现,无需重新打包或修改包身份。诊断保留界面快照及失败说明,排除凭据目录、浏览器分区和会话存储。

发布作业为 macOS 和 Windows 生成完整便携版本包,从既有发布下载自动选出的来源包,通过共享 checkpoint runner 运行升级和回退。成功结果绑定来源/目标版本、包哈希、平台、架构、套件版本和 CI run。只将验证成功的边合并进组件清单;旧边和其引用的中转包必须保留。修改已发布包内容会使哈希验证失败,必须作为新版本重新发布和验证。

Beta 的来源包可以来自 Stable。必须用 Beta 渠道的真实升级/回退结果建立新边;只引入已验证来源节点,不复制 Stable 的升级边。证据同时绑定渠道,同一版本的包哈希在两个渠道也必须一致。Stable 清单拒绝 Beta 节点和 Beta 最低版本。回退恢复本机上一健康版本,不会从线上目录挑选一个旧版本。

在推广滚动清单前,先上传不可变目标包和证据。任何必需版本对失败都阻止推广。最低版本、源码兼容声明或单元测试通过都不能替代真实版本对证据。

修复验证脚本后,非发布重放可复用同一流程中 macOS arm64 和 Windows x64 均构建成功、尚未过期的签名产物。未参与该重放的 macOS x64 或 Linux 构建失败不会阻断这两种平台的验证;实际验证平台仍必须有且只有一个成功的生产者,并通过来源、版本、产物摘要及包内哈希校验。普通 dry run 和正式发布仍要求四个平台生产者全部成功:

gh workflow run wework-app.yml --ref <验证脚本分支> -f verification_run_id=<原构建run-id> -f publish_release=false

此模式只下载并验证既有产物,跳过版本准备、编译、打包、签名和发布;拒绝与发布选项同时使用。验证脚本使用所选分支提交,版本与包身份来自原产物,证据仍绑定实际包哈希。

定位共同启动故障时,可在上述仅验证命令中添加 -f verification_checkpoint=app-upgrade,仅用上一个发布版本运行该检查点。该选项只允许用于既有构建的非发布重放,不生成升级策略或授权证据;正常发版仍运行完整套件。

诊断重放会将启动早期原生错误弹窗的完整文本写入 app.log 的 [desktop-e2e-startup-error] 记录,同时保留弹窗行为。尚未初始化产品日志时, 应先检查这项记录,再调查控制器连接超时,不能仅凭超时推断升级或回退失败的原因。 未启动事务夹具使用保留安装包的准备 API,来源版本的运行组件和包身份保持不变。

原生启动器交接在所有平台显式传递所选版本拥有的 userData 和 release root, 包括中断回退后的恢复启动。旧版入口可能仍按上一级目录解析 release store, 不能依赖目录桥接或仅在 macOS 安装路径中传递目录来完成交接。

同号正式版本已发布、其归档与原候选包不同时,可添加 -f verification_release_tag=wework-v<同一版本号>。此选项仅限非发布重放:测试驱动依赖复用原构建产物,目标归档和描述文件直接从该正式 Release 下载并校验,不修改或重签任何包。版本必须与输入产物一致,既有跨渠道哈希一致性检查保持生效。