26 路并行构建、4 路版本盯梢:WSABuilds 的 GitHub Actions 工作流实战指南
【免费下载链接】WSABuildsRun Windows Subsystem For Android on your Windows 10 and Windows 11 PC using prebuilt binaries with Google Play Store (MindTheGapps) and/or Magisk or KernelSU (root solutions) built in.项目地址: https://gitcode.com/GitHub_Trending/ws/WSABuilds
WSABuilds 是一个开源项目,它把 Windows Subsystem for Android(WSA)打包成预装 Google Play 服务和 Root 方案(Magisk 或 KernelSU)的可安装安卓子系统镜像。为了让下载页始终跟上上游最新版本,维护者用 GitHub Actions 工作流(代码仓库自带的自动化平台)驱动整个发布过程:每当微软发布新版 WSA,在 Actions 页面点一次运行,就会触发 26 路并行构建,自动产出 Windows 10/11、x64/arm64 的下载包。
WSA 构建为什么需要 CI:26 路并行构建替代手工打包
官方 WSA 包是为 Windows 11 准备的,要在里面注入 Root 或 GApps,得先移除签名、给 initrd(系统启动时加载的初始内存磁盘镜像)打补丁、替换内核或删除特定 apex 组件,再整体重新打包。再乘以 2 种 CPU 架构、8 种 Root 选项、GApps 与 Amazon Appstore 的开/关,以及 Windows 10 兼容层,手工操作一轮发布根本忙不过来。
这里 CI 承担的不是测试,而是重复性的打包劳动:下载、改镜像、压缩、记录版本。这意味着:发布节奏不再受限于维护者手速,一次发布从"动手操作"变成"填一个版本号"。
一次 WSA 更新会产出 8 种构建组合
运行 update.yml 一次,会启动 26 个构建任务:Insider Fast(WIF)通道 16 个,retail 通道 10 个。设备型号统一固定为 redfin(Pixel 5),交付格式为 .7z。组合如下:
| 组合(Root · GApps · Amazon Appstore) | WIF x64 | WIF arm64 | retail x64 | retail arm64 |
|---|---|---|---|---|
| 无 Root · GApps · 移除 | √ | √ | √ | √ |
| 无 Root · GApps · 保留 | √ | √ | √ | √ |
| 无 Root · 无 GApps · 移除 | √ | √ | √ | √ |
| 无 Root · 无 GApps · 保留 | √ | √ | √ | √ |
| KernelSU · GApps · 移除 | √ | √ | √ | √ |
| Magisk Stable · GApps · 保留 | √ | √ | — | — |
| Magisk Stable · 无 GApps · 移除 | √ | √ | — | — |
| Magisk Canary · GApps · 移除 | √ | √ | — | — |
retail 通道只保留最常用的 5 种组合(不含 Magisk),把运行器时间留给需求量最大的配置。
从版本号到下载包要经过哪几步
- 维护者在 Actions 页面填入新版本号(wsa_ver)、更新说明(wsa_message)和发布通道(WIF 或 retail),运行 update.yml。
- check 任务创建一个独立的孤儿分支(orphan 分支,历史与 master 完全无关)update,运行 4 个更新检查脚本,刷新分支上的 .appversion 文件(原理见后文)。
- update-downloadlinks 任务调用 update-downloadlinks.py 用新版本号重写 README.md 里的下载链接表,并推回 master。
- check-and-create-tag 任务先确认
Windows_11_$ver、Windows_11_${ver}_arm64、Windows_10_$ver三个标签不存在,再把更新说明填入<<MAGISKSTABLEVERSION>>之类的占位符,用 action-gh-release 创建三个空 Release。 - 26 个构建任务等前 3 个任务完成(通过 needs 声明)后启动,各自通过 uses 调用可复用工作流(workflow_call,只接受别的流程调用、类似函数的 YAML 文件):
build_x64_magisk_gapps_redfin: name: Build for x64 as Redfin with Magisk, GApps if: inputs.release_type == 'WIF' needs: [check, check-and-create-tag, update-downloadlinks] uses: ./.github/workflows/build.yml with: arch: x64 root: magisk gapps: --install-gapps devicemodel: redfin- 真正的活由 610 行的 build.sh 干:先由 generateWSALinks.py 生成下载清单,aria2c 多线程拉取 WSA 包;extractWSA.py 解开镜像;三个 generate*Link.py 脚本分别取 Magisk、KernelSU、GApps 组件;然后用 magiskboot 给 initrd 打补丁注入 Magisk(KernelSU 则直接替换内核)、挂载 GApps、删掉 Amazon Appstore 的 apex、移除原签名,并拷入 Install.ps1 等安装脚本。产物随后交给 Windows 运行器(build_old.yml 的 make-pri 任务):MakePri.ps1 合并资源,diskpart 对 system/product/system_ext/vendor 四块 vhdx 虚拟磁盘分区做压缩瘦身,Windows 10 构建再追加 AppxManifest.xml 兼容补丁和 3 个修改过的 DLL,最后 7z 压缩(LZMA2、8 线程)上传到对应 Release 标签。
arm64 这条线稍有不同:buildarm64.yml 在 Ubuntu 上压缩后直接发布,不经过 Windows 运行器。这就是典型的"多架构 CI 构建"形态:同一套参数分发到两种运行器,各干各擅长的部分。
构建失败时先查什么
| 现象 | 可能原因 | 处理 |
|---|---|---|
| 首步报 "Windows 10 patch does not support arm64 architecture" | 自定义构建工作流明确拦截 Windows 10 + arm64 组合 | wintype 改 Windows 11,或 arch 改 x64 |
| build.sh 中断 "Unsupported combination: Install GApps and KernelSU" | GApps 依赖 Magisk 环境挂载,脚本拒绝该组合 | 换 Magisk 或无 Root;无 Root + GApps 时脚本会自动改用 Magisk |
| "Unzip Magisk failed, is the download incomplete?" | 组件下载不完整 | build.sh 失败时会清理残缺文件,重跑构建任务即可 |
| "Some files are missing" | --offline 模式下 download/ 目录缺组件 | 去掉 --offline 联网构建,或先补齐文件 |
5 个工作流文件各管什么
.github/workflows/ 目录共 5 个文件,一个发布主入口、一个自定义构建、三个仅供调用的可复用工作流:
| 文件 | 触发方式 | 职责 |
|---|---|---|
| update.yml | 手动运行 | 发布主入口:更新检查、建标签与 Release、更新 README 链接、编排 26 路构建 |
| buildtester.yml | 手动运行 | 9 个参数的自定义构建,产物直接下载,不进 Release |
| build_old.yml | 仅被调用 | retail x64,一次产出 Win11 与 Win10 两个包 |
| build_arm64_old.yml | 仅被调用 | retail arm64,只出 Windows 11 arm64 包 |
| buildarm64.yml | 仅被调用 | WIF arm64,Ubuntu 上压缩后直接发布 |
WIF x64 的构建任务在配置里引用了 build.yml 路径,但该文件不在当前仓库快照中。这意味着:想加一种新组合,只需在 update.yml 里新增一个复用现有工作流的任务,构建逻辑一行不用动。
发起一次自定义构建要填哪 9 个参数
不必等下一个正式版本,你可以给自己想要设备型号的机器做包:在 Actions 页面选择 "Custom Build (for testing purpose)",点 Run workflow,所有自定义构建参数都在表单里:
| 参数 | 选项 | 默认值 |
|---|---|---|
| wintype | Windows 10 / Windows 11 | Windows 11 |
| arch | x64 / arm64 | x64 |
| release_type | Retail、Release Preview、Insider Slow/Fast/Private | Retail |
| user_code | 选填,Insider 账号代码 | 空 |
| root_sol | Non-root、KernelSU、Magisk Stable/Beta/Canary/Debug/Alpha/Delta | Magisk Stable |
| gapps_brand | MindTheGapps v13.0 / No GApps | MindTheGapps v13.0 |
| custom_model | WSA Default 加 12 个 Pixel 型号 | Pixel 5 |
| compression | .zip / .7z | .7z |
| remove_amazon | 开 / 关 | 开 |
Ubuntu 上的 build 任务先校验输入(拦截 Win10 + arm64),再用 bash 关联数组把选项翻译成 build.sh 的命令行参数——Pixel 5 变成 redfin,Magisk Stable 变成 stable;产物经 actions/cache 传给 Windows 任务做 PRI 合并与压缩,最终文件名按WSA_${版本}_${架构}_${通道}-with-magisk-…-GApps-13.0(-NoAmazon)规则生成,并附带 sha256-checksum.txt 校验文件。这意味着:不 clone 仓库就能拿到 Pixel 7 Pro 这类型号的包,而且从文件名就知道里面装了什么。
4 个上游版本是怎么被自动盯上的
Release 说明里的版本号不会写旧,是因为它们"构建时现取"。update 分支为每个组件保存一个 .appversion 文件,记录"上次已知版本":
currentver = requests.get( ".../WSABuilds/update/magiskstable.appversion").text.strip() latestver = json.loads(requests.get( ".../topjohnwu/magisk-files/raw/master/stable.json").content )["magisk"]["version"] if currentver != latestver: # 把新版本写入 update 分支,并向 GITHUB_ENV 输出更新消息MagiskStableUpdateCheck.py 与它的三个姊妹脚本(Canary、KernelSU、MindTheGapps)都遵循这个结构:读旧版本、拉上游最新、不一致就改写 .appversion 并输出 "Update ... fromvXtovY"。check 任务依次跑完它们,git-auto-commit 动作把 .appversion 变更推到 update 分支,消息则通过任务 outputs 流入 Release 说明的占位符。这意味着:.appversion 文件、Release 说明和实际构建的包三者版本永远一致,不用人肉盯上游发布页。
下一步可以亲自验证一遍:去仓库 Actions 页面运行 "Custom Build (for testing purpose)",保持默认、只把 gapps_brand 改成 "No GApps",构建完成后看产物名里的 -NoGApps 后缀——这是参数如何流入最终包名最直接的证据。
【免费下载链接】WSABuildsRun Windows Subsystem For Android on your Windows 10 and Windows 11 PC using prebuilt binaries with Google Play Store (MindTheGapps) and/or Magisk or KernelSU (root solutions) built in.项目地址: https://gitcode.com/GitHub_Trending/ws/WSABuilds
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考