Vortex 自动更新机制完全指南:从版本解析、状态机到本地联调
桌面应用【免费下载链接】VortexVortex Development项目地址https://gitcode.com/gh_mirrors/vor/Vortex点击查看免费下载本文围绕 Vortex游戏模组管理器的自动更新模块展开系统讲解其从如何判定有新版本、如何下载与校验到用户在每个环节看到什么的完整闭环。你将掌握installType激活门控、自研 release 解析器、UpdaterState状态机、补丁/小版本/降级三种更新流以及渠道切换的底层实现并学会用 mock feed 在本地完整演练更新流程。安装类型决定更新器是否运行的唯一闸门Vortex 的更新器是否启动完全由installType决定而它又来自启动时的唯一一次探测。在 src/main/src/Application.ts 的identifyInstallType中主进程检查应用目录下是否存在Uninstall Vortex.exe存在则判定为regular官方安装器安装否则判定为managed第三方启动器如 Steam、GOG Galaxy、Epic 负责更新。try { await stat(path.join(getVortexPath(application), Uninstall Vortex.exe)); this.mAppMetadata!.installType regular; } catch { this.mAppMetadata!.installType managed; }managed意味着更新权属于第三方启动器initUpdater不会调用setupAutoUpdater渲染器扩展在开始轮询前就提前返回设置页也只显示提示框而非更新控件见 SettingsUpdate.tsx 的 callout 文案。需要说明两点现实限制源码注释中明确承认目前还没有正式的managed构建发布因此该路径未被测试过由于探测逻辑是用缺少卸载器来反推managed从源码直接运行的构建同样会落入managed分支。二者都寄希望于未来对托管安装做更可靠的检测如匹配 GOG 的goggame-*.info等特征文件而非靠推断。在开发环境下installType没有意义于是被直接忽略改由环境变量VORTEX_DEV_UPDATER1单独决定不设置则更新器完全不做任何事设置则一切照常运行。这样做的关键原因是 electron-updater 拒绝检查未打包unpackaged的构建——若不显式开启每次检查都会在白白消耗一次真实 GitHub 请求后失败。这一逻辑集中在 src/main/src/extensions/updater.ts 的isUpdaterActiveexport function isUpdaterActive(installType: string): boolean { if (process.env.NODE_ENV development) { return process.env.VORTEX_DEV_UPDATER 1; } return installType regular; }它是唯一的闸门下游不再重复校验渲染器通过app:init元数据里的updaterActive得知结果而不是自己推断因为渲染器 bundle 只内联了NODE_ENV无法读取运行时环境变量。启动日志updater initialized会同时记录{ installType, active }方便区分托管安装和未开启的开发构建。如何发现更新自研 release 解析器Vortex 不信任 electron-updater 内置的 GitHub provider它按发布时间取最新这正是旧版把降级当升级推荐 bug 的根源——一个发布较晚的稳定版热修复会被推荐给 beta 用户。取而代之的是自研解析器 releaseResolver.ts直接查询 GitHub releases API为当前渠道选取最高合法 semver版本Stable取最高的非预发布版本。若某 release 的prerelease标志与版本号后缀如-beta.1互相矛盾视为发布失误并排除Beta / next取整体最高版本。更新的稳定版会胜过更旧的 beta 版保证 beta 用户不会错过稳定渠道的热修复永远不参与候选草稿draft、非 semver 标签、以及缺少安装包或latest.yml资产的 release。解析器的具体实现细节pickRelease只按 semver 大小比较与数组顺序、发布日期完全无关releaseResolver.ts。isEligible依次排除 draft、非法 semver、缺少latest.yml或vortex-setup-*.exe资产的 release最后用hasMismatchedPrereleaseFlag排除标志与后缀矛盾的版本。值得注意的是整个 1.x 时代都会触发这条规则奇数小版本的 beta 被标记为 prerelease 却没有版本后缀因此它在一次拉取中只汇总记录一次不会对每个 tag 反复告警。请求方面解析器分页拉取 releases每页 100 条最多MAX_PAGES 3页并用 ETag 做内存缓存——命中304时直接复用缓存正文遇到 GitHub 的403/429且x-ratelimit-remaining: 0时抛出RateLimitError并在重置时间前直接短路、不再发请求若重置头是垃圾值NaN 或 0则回退到 1 分钟后的重置时间。这些细节都有 releaseResolver.test.ts 的测试逐一锁定例如分页上限、304 缓存、限流短路、畸形 JSON 抛错等。解析完成后Vortex 通过 generic feed 把 electron-updater 指向这一个 releaseapplyResolvedFeed设置useMultipleRangeRequest: false——GitHub 的下载走 S3不支持 multipart/byteranges不关掉会让每次差分下载都退化成全量下载。electron-updater 的职责因此被削减为差分下载基于 blockmap补丁通常只需传输安装包约 10% 的体积、校验 sha512 与 Authenticode 签名publisherName来自打包生成的app-update.yml、运行安装器。Vortex 还强制disableWebInstaller true因为只发布完整 NSIS 安装包web 安装器文件可能缺失签名校验。每种更新的行为差异类型示例下载方式用户看到的内容补丁Patch2.6.0 → 2.6.1自动、静默阶段完成前无任何提示之后出现 Vortex will update on restart [Restart Now]。点击按钮或退出时安装小版本 / 大版本2.6.x → 2.7.0等待用户决定先出现 Vortex {v} is available to download [Whats New] [Download]下载中显示 Downloading Vortex {v} (p%)带进度条、无按钮随后是 Vortex {v} is ready to install [Whats New] [Restart Now]降级Downgradestable 渠道上运行版本比 stable 最新版还新仅在用户明确确认后见下文降级一节判定是否自动下载的逻辑在shouldAutoDownloadreleaseResolver.ts只有installType regular且目标版本满足~当前版本含预发布的补丁级升级才自动下载。测试 releaseResolver.test.ts 验证了2.6.0→2.6.1 自动、2.6.0→2.7.0 不自动、managed 安装不自动其中2.6.0-beta.1→2.6.0-beta.2也被判定为补丁。两条支配所有反馈的规则后台工作保持静默除非它改变了用户能看到的东西。启动检查、周期性检查每 4 小时一次、渠道同步检查都不弹通知离线时的后台检查失败只写入日志。按钮触发的工作从按下到结束全程可见。手动 Check now 立即显示 Checking...按钮和通知上都有且必有结果要么重新显示更新、要么弹 up to date toast、要么报错。用户主动发起的下载点 Download、确认降级、或手动检查发现了补丁显示实时进度关闭该通知即取消下载在下次检查前不再提供任何东西。下载进行期间 Check now 按钮被禁用显示 Downloading...任何新的检查请求都被忽略保证状态始终如实反映更新器当前在做什么。降级绝不主动推销低版本更低的版本永远不会被当作更新呈现。唯一提供降级的流程是用户在刻意把渠道切到 Stable而当前运行版本比 stable 最新版还新时例如离开 beta 渠道。此时弹出 Vortex {v} is a downgrade and older than your current version带 [More] 按钮打开对话框详细说明风险降级可能损坏应用状态停留在当前版本的话等下一个 stable 版本比当前版本新时自然会收到更新Stay on current version清除本次提议只有再一次刻意切换到 Stable 才会重新提出Downgrade to {v}可见下载带进度然后进入 staged 阶段显示 Vortex will update on restart。没有用户重启或退出就不会安装。降级确认时会写入一次性标记expectedDowngradeTosrc/main/src/extensions/autoupdater/index.ts用于抑制下次启动时对用户明知选择的版本的 Downgrade detected 警告。主进程在migrateIfNecessary中检查该标记src/main/src/Application.ts标记与当前版本一致则跳过警告并清空标记不一致的意外降级照常警告。注意allowDowngrade只在确认降级→应用 feed这一小段窗口内临时抬升应用完立即复位其余流程一律autoUpdater.allowDowngrade false。分类逻辑集中在classifyUpdatereleaseResolver.ts版本相等或更低且非刻意切到 Stable 时返回none忽略更高返回upgrade刻意切到 Stable 且更低才返回downgrade-offer。测试中还锁定了回归场景beta 用户运行2.6.0-beta.1时更旧的 stable2.5.0在非切换场景下必须被忽略旧版字段 bug 的回归测试见 releaseResolver.test.ts。安装永远可见的 NSIS 向导安装总是运行可见的 NSIS 向导自动更新模式无任何选项、直接安装、完成页自动重新启动 Vortex绝不静默后台安装。Vortex 是每机器per-machine安装因此 Windows 会先弹 UAC 提示。无论用户点击 Restart Now 还是带 staged 更新直接退出执行的安装完全相同staged 安装器只会在它对应的版本上运行绝不安装过期版本。这里有个值得注意的工程细节index.tsVortex 刻意关闭了 electron-updater 的autoInstallOnAppQuit静默路径而是在before-quit钩子里自己执行与 Restart Now 完全一致的可见安装。退出时只有处于staged状态才会安装——如果之后又有别的版本被推荐或下载进行中绝不能带着过期的安装器退出。启动安装可能遭遇瞬时文件锁错误约 360 MB 的安装包还握在杀毒软件手里时quitAndInstall会报 EBUSY / ETXTBSY / EPERM 等。实现会对这类installer busy错误最多重试 5 次、每次间隔 1 秒MAX_INSTALL_ATTEMPTS 5、INSTALL_RETRY_DELAY_MS 1000重试耗尽才进入error状态。另外从源码运行NODE_ENV development或未打包时attemptInstall直接跳过安装——即使开发模式下真下载了安装包也绝不能覆盖机器上正式安装的 Vortex。更新完成后的首次启动会显示 Vortex was updated to {v} 和 [View changes] 按钮展示本次更新跨过的每一个版本的 release notes。更新前版本来自持久化的appVersion与当前版本比较justUpdatedFromView changes 通过updater:get-update-changelog从解析器重新解析并汇总所有落在(旧版本, 新版本]区间内的 release 正文。失败处理下载失败弹出 Vortex update failed详情藏在 [More] 后面更新回到可下载状态供用户重试。自动下载失败的补丁 15 分钟内不自动重试AUTO_DOWNLOAD_HOLD_MS 15 * 60 * 1000防止每次周期性检查都对同一失败重复拉全量 delta而是像普通更新一样提供下载按钮用户主动触发的下载不受此冷却限制手动检查失败明确报错绝不伪装成 up to date后台检查失败离线属于正常情况只写日志不改变任何 UI通过切换渠道取消下载不算错误取消被识别为用户的主动行为状态直接归 idle不报错、不重试。分析整条漏斗的 Mixpanel 事件每一步漏斗都是 Mixpanel 事件由 updaterAnalytics.ts 从状态迁移和按钮点击中发出均携带update_channel事件触发时机app_update_check_completed一次检查尘埃落定outcome为up_to_date、offered、failed或already_staged检查前更新已在手。手动检查总是上报后台检查仅在状态有变化时上报app_update_offered某版本被推荐kind:patch、update、downgradeapp_update_download_started下载开始app_update_download_completed下载并校验完成携带duration_msapp_update_download_failed携带error_message以及是否提供重试app_update_install_started从通知或对话框点击 Restart Nowapp_update_downgrade_decided降级对话框被回答acceptedapp_update_channel_changed确认的渠道切换app_update_release_notes_viewed打开 Whats New 或 View changessource指明入口offer、staged、error_retry、post_updateapp_updated更新后的首次启动携带from_version和to_versionapp_launched同样携带update_channel作为以上事件的对照总体。在分析系统启动前发出的事件登录恢复前的启动检查和补丁下载会被 tracker 排队待用户同意与登录就绪后一并发送用户拒绝则丢弃。状态机单一显式状态渲染器纯函数映射更新器是一个单一的显式状态机UpdaterState定义在 src/shared/src/types/ipc.ts参照 VS Code 的更新器设计任意时刻只有一个状态每次迁移都作为Updater state {from, to}写入vortex.log渲染器的通知是当前状态的纯函数src/renderer/src/extensions/updater/index.ts。状态集合包括disabled渠道为 none、idle、checking、available、downgrade-offered、downloading携带version、kind、manual、percent、staged、error携带message、manual、可选的retry。类型设计刻意让矛盾组合不可表达——比如错误状态上挂着过期的进度、小版本更新上带着 patch 标志都是不可能的类型。拉取式 IPC渲染器轮询而非被推送渲染器采用拉取而不是推送主进程持有状态渲染器按适合 UI 的节奏读取——这与下载器IPCDownloadAdapter和上传器uploadV3是同一套模型。关键在于主进程给每个快照编号sequpdater:get-status(since)返回所有编号大于since的快照因此只持续 300 ms 的状态比如什么都没查到的手动检查也不会被采样漏掉。轮询器 updaterStatus.ts 在更新器忙碌时以 200 ms 间隔运行或在向主进程发请求后再持续几秒WAKE_WINDOW_MS 2000随后停止。所有更新活动都由渲染器发起所以它在任何事情发生前必然是醒着的闲置的 Vortex 不会产生任何更新 IPC。状态迁移图把渠道设为none会撤回当前一切推荐并彻底禁用检查设置页会以警告提示很老版本的 Vortex 最终会失去网络功能。通知层面有一条补充规则处于downloading且为后台 patch 下载时保持静默其余用户按钮触发的下载、确认的降级都可见关闭下载通知就是取消下载。渠道settings.update.channel的取值stable默认、beta和none。设置页中手动检查被限流为每分钟一次CHECK_UPDATE_INTERVAL 60000见 SettingsUpdate.tsx按钮在忙碌时显示 Checking... / Downloading... 并禁用。第四个渠道next已退役它从来只是beta的别名且多年无人使用。旧安装可能仍持久化了它因此toUpdateChannelsrc/renderer/src/types/IState.ts会把任何无法识别的值读作stable。主进程侧同样如此toResolveChannel将除beta外的一切都解析到 stable 轨道。渠道不选择仓库。要把某个构建指向不同仓库设置VORTEX_UPDATER_REPO例如Nexus-Mods/Vortex-Staging它会同时重定向 release 查询和安装包下载。相关环境变量一览环境变量作用默认值VORTEX_UPDATER_REPO重定向 release 查询与下载可传owner/repo或仅repoNexus-Mods/Vortexowner 默认Nexus-ModsVORTEX_UPDATER_API_BASE覆盖 releases API 基址本地 mock feed 用https://api.github.comVORTEX_UPDATER_DOWNLOAD_BASE覆盖下载基址本地 mock feed 用https://github.comVORTEX_DEV_UPDATER开发/源码运行时开启更新器值为1未设置IGNORE_UPDATES设置为yes时渠道切换不触发检查未设置另外从源码运行时若设置VORTEX_DEV_UPDATER1electron-updater 会读取 src/main/dev-app-update.ymlforceDevUpdateConfig其中updaterCacheDirName: vortex-updater-dev将更新器缓存隔离到%LOCALAPPDATA%\vortex-updater-dev便于反复测试。切换渠道时updater:set-channel会先取消正在进行的下载设置页对切换到 Beta 和关闭更新都会弹确认对话框。本地测试与真机排练更新器的完整周期解析、通知、差分下载、校验、安装可以完全离线演练。详细步骤见 docs/updater-testing.md 与面向真实 GitHub 的 docs/updater-rehearsal.md这里给出核心要点本地 mock feed离线用两个远高于真实版本的版本如9.0.0、9.0.1构成 patch delta 便于测自动下载打包构建产物落在根目录dist/vortex-setup-v.exe、.exe.blockmap、latest.yml把产物按每 tag 一个latest.yml 一个顶层扁平latest.yml的布局放进临时目录然后运行 scripts/mock-update-feed.mjsnode scripts/mock-update-feed.mjs --port 9877 --fixture C:\src\updtest\releases-blockmap.json --assets C:\src\updtest\assets它提供 releases 列表、per-taglatest.yml、带 HTTP range 支持的安装包和 blockmap差分下载可工作缺失 blockmap 会 404 从而演练全量下载回退--throttle 20MB/s可放慢下载以便观察进度 UI。随后用两个环境变量把 Vortex 指过去$env:VORTEX_UPDATER_API_BASE http://localhost:9877 $env:VORTEX_UPDATER_DOWNLOAD_BASE http://localhost:9877本地构建未签名但安装后的app-update.yml要求 Black Tree Gaming 签名因此每个下载都会校验失败这正是签名门在工作测试安装需手动删掉C:\Program Files\Vortex\resources\app-update.yml里的publisherName块且每次被更新器安装后都要重新删。mock 源无法覆盖的部分真实签名校验、GitHub CDN 重定向、限流、跨大版本降级警告需要 docs/updater-rehearsal.md 描述的对 scratch 仓库的排练流程它用 CI 签名构建配合VORTEX_UPDATER_REPONexus-Mods/vortex-updater-e2e完成并提供了 12 条可逐项核对的 UI/日志矩阵。开发模式注意pnpm start源码运行时更新器默认关闭需VORTEX_DEV_UPDATER1开启开发构建版本号固定为1.0.0占位符src/main/package.json因此 9.x fixture 会按大版本更新而非补丁处理其日志在%APPDATA%\vortex\main\vortex.log更新器缓存独立于正式版。切换测试构建时记得删除%LOCALAPPDATA%\vortex-updater避免待安装缓存短路下载。观察日志所有状态迁移以Updater state {from, to}输出electron-updater 自身的日志blockmap 获取、range 下载、签名校验、差分下载回退也被路由进vortex.log进度 tick 以 debug 级别记录如downloading 9.0.1 (patch 42%)。与发布流程的衔接更新器解析 GitHub release因此发布环节必须与解析规则对齐只有非 draft、带合法 semver 标签、同时携带安装器和latest.yml的 release 才会被解析器接受pre-release 标志与版本后缀必须一致。发布相关的完整操作流程见 docs/publishing-releases.md。对解析器与发布行为做回归锁定的测试位于 src/main/src/extensions/autoupdater/releaseResolver.test.ts 与 index.test.ts后者还覆盖了 patch 自动下载回归#22609等主进程行为。赞分享桌面应用【免费下载链接】VortexVortex Development项目地址https://gitcode.com/gh_mirrors/vor/Vortex点击查看免费下载相关推荐GitBucket版本控制从语义化版本到自动更新机制解析GitBucket版本控制从语义化版本到自动更新机制解析 GitBucket作为一款由Scala驱动的Git平台以其简易安装、高扩展性和GitHub API后端代码托管开发工具DevOpsVoyager从「Gemini Voyager」升级到 Safari 原生版的一次性迁移指南Voyager从「Gemini Voyager」升级到 Safari 原生版的一次性迁移指南 自 v1.6.0 起Voyager 的 Safari 宿主应用AI 应用前端插件系统提示工程零成本体验SolidWorks一份写给新手的完整上手路线图零成本体验SolidWorks一份写给新手的完整上手路线图 那年做毕业设计导师丢过来一句用SolidWorks画个装配体。正版授权动辄上万学生钱包实在上一篇QuickBMS游戏档案提取引擎完全指南一个工具破解数百种游戏文件格式下一篇HydraDB强大路径搜索SPpaths、SSpaths、MSpaths三大原生算法完整用法创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考