安装包与自动发布
发布入口为 .github/workflows/release.yml。推送与应用版本相同的附注标签(例如 v0.3.0)后,GitHub Actions 完成测试、构建、安装包校验,再公开 GitHub Release。实现方式参考 Vex 的 tag → 原生打包 → SHA-256 → Release 流程。仅在本机打 tag 不会触发,推送 main 也只运行常规 CI,必须将新标签推送到 GitHub。
一键远程全平台发布
Windows 双击根目录 publish-release.bat,或运行 python scripts/packaging/publish.py。先更新应用版本 / 构建号、准备对应的版本说明、完成测试并提交推送 main;脚本检查干净工作区、源码已推送、新标签、SSH remote,输入版本标签确认后才创建并推送附注标签。不需要 GitHub CLI 或本机全平台工具链。--check-only 只预检,不创建标签。
GitHub 在 Windows、Linux x64 / ARM64、macOS runner 上分别编译,另外构建正式签名 Android 包;七个安装包及校验文件全部验证通过后才公开。publish-release.bat 不等待或冒充构建完成,需查看打开的 Actions 页面。新版作为非 prerelease 的公开发行参与默认 releases/latest 下载和应用检查更新;0.x 仍是早期软件,请按发布说明评估限制。旧版预发布记录不重写。
当前 Windows 电脑可以本机制作 Windows 和 Android 包,不能原生制作 macOS / iOS,也没有配置 Linux 跨编译。因此“本机一键构建所有平台”不提供;远程入口解决同一电脑发起全部构建的需求。只想自用 Windows 安装包仍双击 build-windows.bat,它不创建 Release。
当前安装包矩阵
| 平台 | 安装包 | 构建与验证 |
|---|---|---|
| Windows x64 | Vex-v版本-windows-x64-setup.exe |
Flutter Release + Inno Setup 6.7.2;按用户安装,附带 VC++ 运行库;静默安装、品牌、文件、版本、修复、卸载及独立文档保留检查 |
| macOS Intel / Apple 芯片 | Vex-v版本-macos-universal.dmg |
通用二进制;检查主程序和 Flutter / App framework 的两种架构;临时签名、镜像验证、只读挂载检查 |
| Linux x64 | Vex-v版本-linux-x64.deb |
Ubuntu 24.04 原生 runner;推导 ELF 运行依赖;安装、Xvfb 启动、卸载检查 |
| Linux ARM64 | Vex-v版本-linux-arm64.deb |
Ubuntu 24.04 ARM runner;相同安装检查 |
| Android ARMv7 / ARM64 / x86_64 | Vex-v版本-android-架构.apk |
production 包名;固定发行证书;校验签名指纹、包名、版本、非调试标记和 ABI |
| iOS | 暂无可安装 IPA | macOS runner 编译正式入口;缺 Apple 分发证书和 provisioning profile,编译检查不作为安装包 |
| HarmonyOS 手机 / 平板 / 电脑 | 暂无 HAP | 尚缺原生工程、兼容 SDK、插件适配、签名和设备验收,不生成占位产物 |
当前共有 7 个可发布安装包(1 EXE、1 通用 DMG、2 DEB、3 APK),每个附带独立 .sha256。发布脚本按文件白名单检查完整性、格式及校验和;有缺包、额外文件或便携 ZIP / tar 时停止发布。原始崩溃转储和测试文档不会进入发布目录。
2026-10-18 用户确认:iOS、HarmonyOS 安装包发布暂缓,待证书、SDK 和签名条件齐备后补充;不阻止其余平台发布。iOS 无签名编译检查保留,但不上传不可安装的产物。公开品牌、快捷方式和安装包统一使用维刻 Vex;平台包标识、Linux 包名和 Windows Markdown ProgID 已同步更名,接受新的应用身份。当前按全新开发维护,不提供旧身份、旧配置或草稿格式的兼容迁移;具体身份见 品牌命名与标识。
Actions 的 artifact 用于在构建任务之间传输已经制作好的安装包。GitHub 自动提供的源码 ZIP / tar.gz 属于平台自带源码下载;本工作流不制作或发布便携压缩包。
签名与安装
Android 使用包名 com.codewf.vex;preview 包名为 com.codewf.vex.preview,两者可以共存。production 不能回退到 debug 签名。仓库 Secrets:
ANDROID_KEYSTORE_BASE64:发行 keystore 的 Base64。ANDROID_STORE_PASSWORD、ANDROID_KEY_ALIAS、ANDROID_KEY_PASSWORD:对应密钥信息。- 仓库变量
ANDROID_CERT_SHA256:公开证书指纹,用于发布前比对实际 APK 签名。
本次生成的固定发行身份保存在开发机忽略目录 .signing,并已加密配置到 GitHub Secrets。应将该目录另行安全备份;后续升级必须复用此密钥。不要把密钥、密码、android/key.properties 提交到 Git。CI 构建结束会清理临时签名文件,仅上传安装包和校验文件。
Windows 安装器尚无 Authenticode 证书。macOS DMG 当前使用 ad-hoc 签名,尚无 Developer ID 和 Apple 公证;系统可能要求用户在隐私与安全性设置中明确允许。两者均不宣称已通过厂商信任认证。Linux DEB 的基线为 Ubuntu 24.04,其他发行版尚未逐一验收。
统一打包脚本
所有平台入口按目标归类到 scripts/packaging/。统一命令为 python scripts/packaging/build.py 目标(macOS / Linux 使用 python3),目标包括 win-x64、linux-x64、linux-arm64、osx-x64、osx-arm64、osx-universal、android 及仅编译的 ios-check。对应目录提供 BAT / Shell 快捷入口;宿主、工具链、签名和选项见该目录说明。本机与 GitHub Actions 共享此流程,不再分别维护构建命令。
本机产物统一位于 artifacts/local/目标/v版本-build构建号/,CI 显式指定 --output artifacts/release。两个 macOS 架构入口均归入 osx-universal,继续只生成一个同时支持 Intel / Apple 芯片的 DMG。
本机一键打包(Windows)
在 Windows 电脑双击仓库根目录的 build-windows.bat。窗口结束后保留结果,成功时打开产物目录;不会自动安装或启动 Vex,也不会提交、推送、打 tag 或发布到 GitHub。当前入口只制作 Windows x64 安装包,不能在 Windows 本机制作 macOS / iOS 包。
前提条件:
- 使用
.flutter-version固定的 Flutter SDK,把其bin加入 PATH。也可设置VEX_FLUTTER为flutter.bat的完整路径;当前工作区已经解析依赖时,脚本还能从生成的 package config 找到 SDK。换机后不要依赖这个缓存。 - 安装 Python 3.11+,使
python命令可用。 - 安装 Visual Studio 的「使用 C++ 的桌面开发」工作负载及 Windows SDK。这不是 Visual Studio Code。
- 首次构建需要网络。Inno Setup 使用既有脚本固定为 6.7.2,下载时同时校验 SHA-256 和发布者签名,安装到临时工具目录。
默认流程为:工具链与版本检查 → 锁文件依赖解析 → 静态分析 → 四组 Dart / Flutter 测试及 Python 脚本测试 → Windows Release → Inno 安装程序 → SHA-256 → 安装包格式与文件白名单校验。它不包含原生窗口集成测试或实际安装卸载测试,后者仍是单独的验证步骤。
| 结果 | 路径 |
|---|---|
| 安装包 | artifacts/local/win-x64/v版本-build构建号/Vex-v版本-windows-x64-setup.exe |
| 校验文件 | 同目录的 .exe.sha256 |
| 构建日志 | artifacts/build-logs/windows-日期-时间.log |
| Flutter 编译输出 | apps/vex/build/windows/x64/runner/Release,不是单文件便携程序 |
例如应用版本为 0.2.2+4 时,安装包目录为 artifacts/local/win-x64/v0.2.2-build4。重复构建同版本会更新该目录中的同名产物;构建失败时可能留有旧产物,只有本轮输出 READY 才表示本轮成功。这些目录已忽略,不提交到 Git。
命令行可在仓库根目录使用:
.\build-windows.bat -CheckOnly
.\build-windows.bat -Flutter C:\tools\flutter\bin\flutter.bat
.\build-windows.bat -NoOpenFolder-CheckOnly 只检查先决条件,不下载依赖或安装 Inno;-Compiler C:\tools\inno\ISCC.exe 可指定现有编译器。日常默认执行全部检查;只有明确接受风险时才使用 -SkipTests,它会跳过分析与测试,但不会跳过依赖锁定、Release 构建及产物校验。自动化调用可以设置进程环境变量 VEX_NO_PAUSE=1 取消 BAT 最后的等待,不影响退出码。
成功后自行运行安装包。安装包没有 Windows Authenticode 签名,可能出现 SmartScreen 提醒;哈希校验只能检查内容一致性,不等于受系统信任的签名。
用户数据与升级
Windows 当前使用三个独立位置:
| 类别 | 默认位置 / 规则 |
|---|---|
| 程序文件 | %LOCALAPPDATA%\Programs\Vex,安装时可更改 |
| 设置与恢复草稿 | %APPDATA%\Vex,通过 Windows 平台 API 获取;不加公司名子目录 |
| 个人 Markdown 与附件 | 用户自行选择的文档目录,不会自动搬入程序目录 |
shared_preferences.json 保存 workspace-v1 设置,recovery-v1.json 保存恢复草稿。临时 .tmp / .previous 文件用于替换过程,不是多版本备份。设置可能包含 MCP 访问令牌,不要把整个配置文件公开到仓库或问题报告中。
同一个 Windows 用户、同一应用身份下,正常覆盖安装 / 修复 / 升级只替换程序目录,不清理上述用户数据目录,也不删除个人 Markdown。当前安装器卸载时也没有删除用户数据的规则。安装目录可以更改,不必随之搬迁设置。升级前应保存并关闭应用,分别备份笔记目录和用户数据;恢复草稿不能代替备份。
Windows EXE 保留 ProductName=Vex,将 CompanyName 置空,使 path_provider 和 shared_preferences 都直接使用上述目录;作者及版权仍为 CodeWF。不要随意修改这两项路径相关元数据。
开发阶段只维护当前数据位置和格式,不扫描、导入或自动搬迁历史目录。已有目录不会被主动删除;不要将旧设置或恢复文件直接覆盖到当前目录。测试前先在原应用中把重要草稿保存为 .md,并另行备份笔记和应用数据。
程序与数据分离不代表跨版本数据兼容:目前不承诺开发版本之间的配置 / 草稿格式兼容或降级可用。磁盘错误及系统清理仍有风险。Android / iOS 卸载通常会删除应用沙箱,不能套用 Windows 的卸载保留规则。其他平台路径以平台 API 为准,不把 Windows 路径硬编码成跨平台目录。首次启动默认值、配置损坏容错和写入保护继续保留。
本地验证
使用根目录 .flutter-version 固定的 SDK,先执行 flutter pub get --enforce-lockfile。应用版本来自 apps/vex/pubspec.yaml,内部包版本与原型元信息随版本一起更新。
Actions 和锁文件统一使用 https://pub.dev。新增 Mermaid / 数学渲染依赖后,旧镜像源会把同版本依赖视为不同来源,使 --enforce-lockfile 失败;不要在发布时绕过锁文件检查。需要切换开发镜像时,应另行验证镜像同步状态,不提交混合源锁文件。
python -m unittest discover -s scripts/tests -v
python scripts/packaging/shared/release_tools.py metadata --tag v0.2.2
cd apps/vex
flutter build windows --release --target lib/main.dart
cd ../..
$compiler = ./scripts/packaging/win-x64/install_inno.ps1
./scripts/packaging/win-x64/package.ps1 -Version 0.2.2 -Compiler $compiler
./scripts/test_windows_installer.ps1 -Installer artifacts/release/Vex-v0.2.2-windows-x64-setup.exe -Version 0.2.2
python scripts/packaging/shared/release_tools.py checksums --targets windows-x64
python scripts/packaging/shared/release_tools.py verify --targets windows-x64安装卸载测试会创建临时目录;已有正式安装时拒绝执行,避免影响正常安装。开发机可给打包和测试脚本同时传入 -InstallerTest,并指定非发布输出目录:该编译变体具有独立 AppId,不创建快捷方式或 Markdown 关联,不能当作正式产物发布。日志保留在输出提示的临时目录。其他平台使用统一入口,已有编译产物的底层打包工具位于对应的 scripts/packaging/ 子目录。
如果本机已经留有专用测试安装,不覆盖或卸载它。可给两个脚本同时传入相同的 -InstallerTestId,例如 Vex.Installer.Test.Close-20261018,以独立注册和默认目录执行新一轮验证。标识必须以 Vex.Installer.Test 开头,只允许规定的 ASCII 字符;自定义标识必须与 -InstallerTest 一起使用,不影响正式产品的升级标识。
Windows 安装器采用 640 × 360 的 DPI 缩放原生窗口,保留系统键盘和无障碍控件。默认折叠安装选项,展开保留主标题;右上角 X 关闭,进度百分比跟随进度并限制在轨道两端,不展示复制文件详情。许可只读滚动区按 UTF-8 解码。按钮、复选框和许可正文分别校验明暗主题对比度;这些本机验证不代替其他 DPI 与各系统的实机验收。
安装资源已随源码提交:Windows 仅使用 scripts/installer/assets/hero-light.bmp 与 hero-dark.bmp,更新根目录 Logo 后可用 python scripts/prepare_installer_assets.py 重新生成;macOS 的两张背景图由 python scripts/prepare_macos_installer.py 生成(这两个生成脚本均需要 Pillow)。安装器不依赖原型整页截图、栅格皮肤或本机浏览器;正常克隆和打包无需重新生成这些资源。
macOS 使用 dmgbuild 写入标准 Finder 磁盘映像布局,不依赖 Finder 自动化授权。固定 740 × 380 内容区、88px 应用和 Applications 拖拽目标,附带 1x/2x 品牌背景;许可位于签名后的 Vex.app/Contents/Resources,不额外占用安装窗口。复制、覆盖确认、权限、进度与推出由系统 Finder 处理,不模拟安装成功或隐藏系统错误。打包依赖按版本和 SHA-256 锁定;只读挂载后检查实际签名、许可、链接、Retina 背景和 .DS_Store 布局。本机 Windows 仅验证背景资产与几何配置,DMG 的真实制作与挂载需 macOS runner。
.github/workflows/installer-check.yml 在原生安装脚本变更后检查 Windows/macOS 实际 Release 构建和打包,也可手工运行。该流程不创建 tag 或 GitHub Release,只保留短期 Actions 测试附件;最终发行仍通过 release.yml 的完整矩阵。
正式构建保留 Flutter 默认的 pub / 插件注册更新;Flutter 3.47 在 --no-pub 下不会重写平台注册文件,测试后的 Android 注册文件可能仍引用只用于开发的 integration_test,而 Release Gradle 已排除该依赖,导致 Java 编译失败。锁定依赖先用 --enforce-lockfile 校验。不要在同一工作副本同时执行会改写插件注册文件的构建和测试;CI 的平台任务使用各自独立 runner。
GitHub 的手工重试入口要求提供已经存在的标签,构建始终 checkout 该标签对应提交。标签、pubspec 和版本说明不匹配时停止;不会移动标签或把其他提交发布成旧版本。所有测试、桌面 / Android 构建和 iOS 编译检查通过后才公开 Release。
打包脚本归类前的历史 tag 不包含新的 scripts/packaging/ 路径。重试这些版本时,在 Actions 的 Use workflow from 中选择该 tag 本身,再填写相同标签,使用当时随标签保存的工作流;不要让 main 上的新工作流调用历史源码中不存在的工具。新版入口会提前给出此提示,不移动旧 tag 或偷偷改用当前源码。
若只有发布接口失败,可以在手工入口额外填写原运行的 artifact_run_id,复用其中已经通过测试和构建的安装包。入口检查来源工作流、提交关系、八项必要任务及五组未过期产物;汇总后仍逐个检查七个安装包与 SHA-256,缺失、异常或版本不符即停止,不重新执行构建。该方式不能复用本身由其他运行复用而来的产物。
发布前再次核对附注标签及源码提交。创建 Release 使用已有标签,更新 Release 仅修改标题、说明和发布状态,不传入 target_commitish 或修改标签;这样避免集成令牌对旧工作流提交的额外权限请求。同一标签下已经上传的附件必须与本轮校验结果完全相同,才允许复用;不会静默覆盖不同内容。七个安装包和校验文件全部上传并验证服务器 SHA-256 后才公开 Release。Latest 使用 GitHub 的版本排序,不因重试旧版而强行降回旧版本。
换机开发
- 在新电脑克隆仓库并使用
.flutter-version指定的 Flutter SDK,不依赖旧电脑的 SDK 安装路径。安装目标平台工具链后,在仓库根目录执行flutter pub get --enforce-lockfile。 - 正式打包脚本、安装器源码及所需静态资源均在 Git 中;
build、artifacts、Pub 缓存和本机工具链按需重建,不需要提交或迁移。 .signing、android/key.properties及密钥密码不在 Git 中。换机前单独加密备份发行密钥及配套信息,确认可在新电脑恢复后再处置旧电脑;后续 Android 更新必须复用原发行密钥,不能生成新密钥代替。仓库现有 GitHub Secrets 不随本地克隆下载。- 个人笔记、恢复草稿以及未提交的本地修改也不随克隆迁移。先保存未完成文档,并检查
git status,另行备份尚未提交的内容;确认文件和签名材料齐全后再清理旧电脑。
Windows 开发机上的移动端测试
Android 可直接使用本机 SDK、模拟器或真机开发测试,详见 Android 构建。HarmonyOS 的 DevEco Studio / SDK / 模拟器也支持 Windows,但本机目前没有完整 DevEco 环境。已有 Flutter OHOS 适配 SDK 为 3.41.10-ohos-1.0.1 / Dart 3.11.5,主项目要求 Flutter 3.47 / Dart 3.13;早前降低约束的临时副本仅通过依赖解析、分析和核心测试,不能证明原生插件、HAP 或设备适配完成。主项目不为打包静默降级工具链。
iOS 原生编译、模拟器和签名需要 macOS / Xcode。Windows 可以编辑共享 Flutter 代码并运行单元测试,原生编译交给 Actions 的 macOS runner。无 Apple 签名时不能提供可安装 IPA;后续需接入证书、描述文件、真实设备或 TestFlight 验证。当前编译检查没有上传 .app 压缩包代替 IPA。
有疑问或建议,欢迎到 GitHub 提交 Issue 参与讨论。