OpenWork 下载统计 V2 数据体系解析:GitHub Release 资产分类统计、生成管线与数据解读

OpenWork 下载统计 V2 数据体系解析:GitHub Release 资产分类统计、生成管线与数据解读 OpenWork 下载统计 V2 数据体系解析GitHub Release 资产分类统计、生成管线与数据解读【免费下载链接】openworkThe open-source alternative to Claude Cowork (powered by opencode)项目地址: https://gitcode.com/GitHub_Trending/ope/openworkSTATS_V2.md 是 OpenWork 仓库根目录下的下载统计文档它按资产类型将 GitHub Release 的累计下载量拆分为手动安装 / 更新器 / 其他三个口径并逐日记录增量。本文以该文档为骨架结合仓库中的生成脚本 scripts/stats.mjs、单元测试 scripts/stats.test.mjs 以及桌面打包配置 apps/desktop/electron-builder.base.yml完整还原这套分类统计体系的口径定义、自动化生成管线与数据形态帮助你读懂每一行表格背后的统计逻辑并能在自己的场景中复现或扩展同样的统计能力。一、文档定位从总量到分类的统计升级仓库根目录存在两份下载统计文档STATS.md标记为Legacy记录的是 GitHub Release 全部资产的累计总量单列GitHub Downloads表头为| Date | GitHub Downloads | Total |并在文档开头明确指引分类后的 v2 桶见STATS_V2.md。STATS_V2.md即本篇文章的主角将全部 Release 资产按用途分类统计表头为| Date | Manual Installs | Updater | Other | All Release Assets |。两者的关系可以理解为V1 只看总下载量有多少V2 回答下载量来自哪些通道——是用户主动下载安装包还是客户端自动更新拉取或是签名/侧车sidecar等辅助资产的流量。这一点从脚本的分工也能印证scripts/stats.mjs 的saveLegacyStats()写 STATS.md单总量而saveV2Stats()写 STATS_V2.md四桶分类一次运行同时更新两份文档。二、三类统计口径的定义文档原文口径STATS_V2.md 开篇给出了官方口径这是整个数据体系的核心约定Manual installscounts installer downloads (.dmg,.msi,.deb,.rpm).Updatercounts updater artifacts (latest.json, macOS updater bundles, updater signatures).Othercaptures signatures, sidecars, and uncategorized assets.翻译并展开如下统计桶中文含义覆盖的资产类型Manual Installs手动安装安装器下载.dmg、.msi、.deb、.rpm另见下文源码还含.pkg、.appimage、.exeUpdater更新器自动更新相关产物latest.json、macOS 更新包.app.tar.gz及更新包签名Other其他签名文件如.sig、侧车二进制sidecar及其他未归类资产All Release Assets全部资产以上三桶之和即全部 Release 资产的累计下载量需要特别说明的是文档正文列出的后缀只是代表性示例实际分类规则更完整见下一节源码级拆解。三、源码级拆解资产如何被归类3.1 分类函数classifyAsset分类逻辑集中在 scripts/stats.mjs 的classifyAsset(release, asset)export function classifyAsset(release, asset) { const name String(asset?.name || ).toLowerCase() if (!name) return other if (isDesktopRelease(release)) { if (UPDATER_SUFFIXES.some((suffix) name suffix || name.endsWith(suffix))) { return updater } if (MANUAL_INSTALL_SUFFIXES.some((suffix) name.endsWith(suffix))) { return manual_install } } return other }关键设计点有三个资产名先转小写再匹配避免大小写差异导致漏统计只有桌面版发布才参与分类。判定函数isDesktopRelease()stats.mjs检查 release 的tag_name是否匹配/^v\d/。也就是说像openwork-server-v0.11.135这类服务端 tag 下的资产一律落入other不会被误判为安装器或更新器Updater 优先于 Manual 判定因为latest.json这类清单文件若按后缀兜底可能被误归到其他桶。3.2 完整后缀清单源码定义scripts/stats.mjs 中的完整定义const MANUAL_INSTALL_SUFFIXES [.dmg, .msi, .deb, .rpm, .pkg, .appimage, .exe] const UPDATER_SUFFIXES [latest.json, .blockmap, .app.tar.gz, .app.tar.gz.sig]对照文档正文源码补充了.pkg、.appimage、.exe到手动安装桶并将.blockmap增量更新差分映射与.app.tar.gz.sigmacOS 更新包签名归入更新器桶。3.3 测试用例佐证分类边界scripts/stats.test.mjs 用断言固定了分类边界值得逐条阅读openwork-desktop-darwin-aarch64.dmg→manual_installmacOS 安装器openwork-desktop-windows-x64.msi→manual_installWindows 安装器openwork-desktop-linux-amd64.deb→manual_installLinux 安装器latest.json→updateropenwork-desktop-darwin-aarch64.app.tar.gz→updatermacOS 更新包openwork-desktop-darwin-aarch64.app.tar.gz.sig→updateropenwork-desktop-linux-aarch64.rpm.sig→other注意.rpm.sig以.rpm结尾但因先匹配了非手动安装规则、且.sig未在手动安装清单内最终归为otheropenwork-server-darwin-arm64→other服务端发布 tag 下的资产calculate()的聚合测试stats.test.mjs验证了legacy 总量 三桶之和的不变式total buckets.all。3.4 与桌面打包配置的映射分类后缀并非凭空而来它们与 apps/desktop/electron-builder.base.yml 定义的打包目标一一对应macdmg、zip目标对应手动安装桶的.dmglinuxAppImage、tar.gz目标winnsis目标产出.exe/.msi更新器相关资产则由 electron-updater 机制产出见下文第六节。桌面版 artifact 的命名模板在 apps/desktop/electron-builder.yml 中定义为openwork-${os}-${arch}-${version}.${ext}这解释了为何资产名中能稳定出现darwin-aarch64、windows-x64、linux-amd64等架构标识——分类逻辑正是依赖这些命名约定。四、统计生成管线一次运行双文档更新 指标上报STATS_V2.md 中的数据不是人工维护的而是由 scripts/stats.mjs 定时推测为每日运行自动追加的。脚本具备独立入口#!/usr/bin/env nodemain()守卫可直接以node scripts/stats.mjs运行。整条管线分五步4.1 步骤一环境变量与配置脚本顶部stats.mjs读取以下环境变量环境变量默认值作用POSTHOG_KEY/POSTHOG_API_KEY无未设置则跳过上报并告警PostHog 项目密钥POSTHOG_HOSThttps://us.i.posthog.comPostHog 上报端点POSTHOG_LEGACY_EVENT/POSTHOG_EVENTdownloadlegacy 总量上报事件名POSTHOG_V2_EVENTrelease_asset_snapshotv2 分类快照上报事件名POSTHOG_DISTINCT_IDopenwork-download上报用户标识v2 会按桶追加后缀GITHUB_REPOdifferent-ai/openwork拉取统计的仓库STATS_FILESTATS.mdlegacy 文档路径STATS_V2_FILESTATS_V2.mdv2 文档路径GITHUB_TOKEN无GitHub API 认证令牌用于提高速率限额4.2 步骤二分页拉取全部 ReleasesfetchReleases()stats.mjs通过 GitHub REST APIGET /repos/{repo}/releases逐页拉取每页 100 条、页间 sleep 1 秒直到取空。未设置GITHUB_TOKEN时以匿名方式请求受 60 次/小时限额约束设置后以Authorization: Bearer token请求限额更高。4.3 步骤三聚合计算calculate(releases)stats.mjs遍历所有 release 的资产累加每个资产的download_count得到 legacy 总量对每个资产调用classifyAsset()归桶分别累加manual_install、updater、other输出buckets.all legacyTotal保证总量恒等。4.4 步骤四解析上一行追加新行写表的关键在于读旧表 → 算增量 → 追加parseLastDataRow(content, expectedColumns)stats.mjs从文件末尾向上寻找第一行合法数据行跳过表头、分隔行、列数不符的行parseCountCell(cell)stats.mjs用正则/-?[\d,]/提取单元格中的数值忽略(xx)增量部分并去掉千分位逗号formatChange(change)stats.mjs把增量格式化为(1,234)样式负增量显示为(-123)零增量为(0)saveV2Stats()stats.mjs对四个桶分别计算delta 本次累计 - 上次累计然后拼出形如| 2026-07-30 | 180,930 (2,410) | ... |的新行追加到文件末尾自动补尾部换行。日期取脚本运行当日的 UTC 日期new Date().toISOString().split(T)[0]因此同一天重复运行会追加重复行实践中应通过调度任务保证每天恰好运行一次。4.5 步骤五PostHog 指标上报最后sendToPostHog()与sendClassifiedSnapshot()stats.mjs将结果上报 PostHoglegacy 事件download携带count、source: github、repo、datev2 事件release_asset_snapshot对manual_install、updater、other、all四个桶各发一条携带metric_version: 2、bucket、total、delta并以${distinctId}-${bucket}作为 distinct id便于在 PostHog 中按桶拆分趋势曲线。脚本最终在控制台打印汇总stats.mjs包括 TOTAL DOWNLOADS、三桶数值便于人工核对。五、数据表结构与增量语义STATS_V2.md 的表格共五列每行格式为| Date | Manual Installs | Updater | Other | All Release Assets | |------|-----------------|---------|-------|--------------------| | 2026-03-07 | 54,446 (54,446) | 89,201 (89,201) | 14,460 (14,460) | 158,107 (158,107) |解读要点每个数值都是截止当日 24:00 的累计值而非当日新增。例如Manual Installs列 2026-07-30 的180,930表示从首个被统计的发布至今所有安装器的累计下载总量括号内是相对上一行的当日增量(2,410)表示 07-30 当天手动安装器新增 2,410 次下载。增量 当日累计 − 前一日累计首行增量等于自身累计值如(54,446)因为首行没有可比较的前值默认前值为 0All Release Assets恒等于前三列之和可作为数据完整性的自检列。脚本对文档不存在或为空的情况也有兜底loadOrInitialize()stats.mjs会在文件缺失时用预置的V2_HEADER初始化saveV2Stats()还会检查表头是否存在不存在则先补写表头再追加数据行。六、更新器资产的来源桌面自动更新机制Updater桶能占到总下载量的大头根源在于 OpenWork 桌面端的自动更新机制。在 apps/desktop/electron/main.mjs 中客户端按平台/架构拉取不同的更新清单文件function updaterManifestName(arch) { if (process.platform darwin) return latest-mac.yml; if (process.platform win32) return latest.yml; return arch arm64 ? latest-linux-arm64.yml : latest-linux.yml; }这些latest*.yml清单、清单引用的.app.tar.gz更新包、.blockmap增量差分以及 macOS 更新包签名.app.tar.gz.sig正是UPDATER_SUFFIXES列表latest.json、.blockmap、.app.tar.gz、.app.tar.gz.sig要捕获的对象。每次桌面客户端自动检查并下载更新都会增加一次Updater桶的计数而用户在官网或 Release 页面手动下载.dmg/.msi/.deb/.rpm安装包则计入Manual Installs。七、数据形态解读从表格能读到什么以下分析全部基于 STATS_V2.md 中记录的实际数据截至文档最后一行 2026-07-30仅做数据层面的描述。7.1 总体量级与结构占比指标2026-03-07首行2026-07-30末行期间增量Manual Installs54,446180,930126,484约 2.3 倍Updater89,201692,629603,428约 6.8 倍Other14,460450,541436,081约 30 倍All Release Assets158,1071,324,1001,165,993约 7.4 倍可见Updater一直是占比最大的桶说明自动更新流量远高于手动安装流量Other桶增长倍数最高从侧面反映签名、sidecar 等辅助资产下载量的持续放大。7.2 关键拐点逐月摘要日期Manual InstallsUpdaterOtherAll备注2026-03-0754,44689,20114,460158,107v2 统计起点2026-03-3168,732135,64820,740225,1203 月末2026-04-0270,782159,31321,626251,721Updater 跳增前夜2026-04-0371,365207,31022,039300,714Updater 单日 47,9972026-04-0975,240460,14425,202560,586Updater 单日再 42,2102026-04-1579,422624,87427,576731,872Updater 增速骤降4,6812026-04-3092,816677,34135,427805,5844 月末2026-05-07100,415688,24048,419837,074Manual 突破 10 万2026-05-31119,570690,373146,394956,3375 月末2026-06-09126,150690,953185,4981,002,601All 突破百万2026-06-30143,609691,461286,4821,121,5526 月末2026-07-24171,270692,270414,4291,277,9697/25 无记录2026-07-26173,513692,346423,5641,289,4237/25→7/26 增量放大2026-07-30180,930692,629450,5411,324,100文档末行从数据形态可以观察到的几个事实完整逐日数据见 STATS_V2.md4 月上旬 Updater 桶出现跳变2026-04-02 至 04-14Updater从 159,313 增至 620,193仅用约 12 天就完成了近 46 万的累计增长单日增量峰值出现在 04-0347,997之后 04-15 起增速骤降至千级进入平台期。从数据看这与更新器相关资产latest.json、macOS 更新包、签名的统计口径或发布节奏变化高度相关但具体业务原因无法仅凭本表确认。5 月中旬起 Other 桶开始高速增长从 05-07 的 48,419 到 07-30 的 450,541日均新增数千成为后期总下载量的主要增长来源。7 月下旬出现一天数据缺口表格从 07-24 直接跳到 07-26无 07-25 行且 07-26 当日增量11,454明显高于前后几日可以推断 07-25 当天可能未运行统计任务其增量被合并计入 07-26 行该行Manual Installs增量2,243同样高于平日水平与两日合并的推断一致。Manual Installs 保持平稳线性增长日均增量长期处于 500–1,500 区间没有出现类似 Updater 的跳变反映了手动安装通道相对稳定的特征。以上解读仅为基于数据的描述性观察不应过度外推为业务结论。八、复现与扩展这套统计能力8.1 本地复现在仓库根目录执行需 Node.js 环境脚本为 ESM 模块node scripts/stats.mjs建议设置环境变量以获得完整能力GITHUB_TOKENtoken POSTHOG_KEYkey node scripts/stats.mjs不带GITHUB_TOKEN匿名访问 GitHub API受 60 次/小时限额仓库 Release 较多时可能失败不带POSTHOG_KEY脚本告警并跳过 PostHog 上报仅更新本地文档可通过GITHUB_REPO指向任意仓库把同一套分类逻辑复用到其他项目输出文件路径可用STATS_FILE、STATS_V2_FILE覆盖便于在不污染仓库的前提下试运行。8.2 运行单元测试仓库为脚本提供了 Node 内置测试器用例node --test scripts/stats.test.mjs测试覆盖了分类边界安装器/更新器/其他、聚合不变式total buckets.all、表格解析与增量格式化parseLastDataRow/parseCountCell修改分类规则后跑一遍即可验证口径没有回归。8.3 扩展建议基于现有代码结构新增桶在V2_BUCKETS与saveV2Stats()中增加桶名并在表头追加一列parseLastDataRow的expectedColumns参数同步调整调整分类规则修改MANUAL_INSTALL_SUFFIXES/UPDATER_SUFFIXES或classifyAsset()的判定顺序注意 Updater 优先于 Manual 的既有约定接入定时任务将node scripts/stats.mjs配置为每日定时执行即可维持与仓库中一致的逐日增量表。九、小结STATS_V2.md 表面是一张下载数据表背后则是一套完整、可复现、可测试的分类统计工程classifyAsset()定义了桌面版发布 后缀匹配的归桶规则calculate()保证总量恒等parseLastDataRow()/parseCountCell()实现了追加式增量表维护PostHog 上报让指标进入可观测体系而 electron-builder 与 electron-updater 的配置则解释了各类资产为何会出现在统计中。阅读本表时牢记累计值 括号增量的语义并留意类似 7/25 缺行这类调度层面的数据形态就能准确解读 OpenWork 各下载通道的长期走势。如需深入可继续阅读scripts/stats.mjs、scripts/stats.test.mjs、STATS.md、apps/desktop/electron-builder.base.yml、apps/desktop/electron-builder.yml、apps/desktop/electron/main.mjs。【免费下载链接】openworkThe open-source alternative to Claude Cowork (powered by opencode)项目地址: https://gitcode.com/GitHub_Trending/ope/openwork创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考