news 2026/10/23 1:49:31

MacTools从源码到签名上架:插件目录、Ed25519签名与GitHub Actions发布流程解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MacTools从源码到签名上架:插件目录、Ed25519签名与GitHub Actions发布流程解析

【免费下载链接】MacTools

A free and open-source collection of native macOS menu bar tools.

项目地址:https://gitcode.com/gh_mirrors/mac/MacTools
点击查看免费下载

MacTools 是一款免费开源的 macOS 菜单栏工具集,把系统状态、设备电量、磁盘清理、显示控制等几十个小工具收进一个原生菜单栏面板,并支持通过插件目录自行扩展。这篇文章用通俗的语言拆解它的工程全貌:插件目录是怎么组织的、Ed25519 签名如何保证插件目录不被篡改、以及 GitHub Actions 是如何把源码一路变成"签名、公证、可自动更新"的发布产物的。

源码结构总览:一个 XcodeGen 项目如何组织

MacTools 的仓库根目录用 project.yml 描述整个 Xcode 工程,通过 XcodeGen 生成.xcodeproj,核心结构如下:

目录职责
Sources/App/主应用界面:菜单栏面板、设置、命令面板
Sources/Core/Plugins/插件宿主:加载、校验、生命周期管理
Sources/MacToolsPluginKit/所有插件共享的运行时框架(PluginKit)
Plugins/50+ 个内置插件,各自独立成包
.github/workflows/CI 与发布流水线定义
scripts/plugins/插件打包、目录生成与签名脚本

每个插件都是"自包含"的小工程,以Plugins/DockLock/为例:

Plugins/DockLock/ plugin.json # 插件清单(身份、版本、能力、权限、本地化文案) Sources/ # 实现代码 Bundle/ # 加载入口(Factory) Tests/ # 单元测试

plugin.json 是唯一的元数据源,关键字段包括id、version、pluginKitVersion(ABI 版本号)、capabilities(能贡献面板行、设置表单等)和permissions(如accessibility)。宿主在加载可执行代码之前先读这份清单,校验通过才会装载插件。

插件目录是如何运作的

MacTools 的插件不是随应用发布的,而是目录驱动:应用启动后拉取一份 JSON 目录(catalog),解析出每个插件包的下载 URL、SHA-256 校验和、最低宿主版本与所需 PluginKit 版本,再逐个校验、安装。生产目录按 ABI 版本分线路存放,例如当前源码线是 docs/plugins/v7/catalog.json,旧版本的 v4、v5、v6 目录保持不可变,老应用继续读取自己的线路,互不影响。

本地开发则走 Debug 通道:运行make build-plugin会扫描Plugins/*/plugin.json,编译全部插件并生成build/LocalPlugins/catalog.dev.json,配合file://目录 URL 即可在应用"市场"中直接安装本地包,签名校验降级为可选。这就是为什么开发者改一行插件代码后,刷新市场列表就能看到新版本。

Ed25519签名:为什么插件目录也要"防伪"

代码签名(Developer ID)保护的是应用本身,而插件目录是一份随时更新的 JSON,攻击者若篡改目录就能让用户下载恶意插件包。MacTools 为此给目录加了一道独立的 Ed25519 数字签名,实现集中在 plugin-catalog-crypto.swift:

  1. 规范化:签名前先移除signature字段,再用 Foundation 的sortedKeys选项生成规范化 JSON——字段顺序统一后,同样的内容永远得到同样的签名。
  2. 签名:用 CryptoKit 的Curve25519.Signing.PrivateKey(即 Ed25519)对规范化字节做签名,结果以 base64 写回目录的signature.value,algorithm标记为ed25519。
  3. 验签:公钥被直接嵌入应用(见 Configs/Release.xcconfig 中的PLUGIN_CATALOG_PUBLIC_KEY),应用拉取目录后用公钥验证,不匹配就拒绝整个市场。

密钥管理上有几个值得学习的细节:

  • 私钥以 base64 存放在 CI secretPLUGIN_CATALOG_PRIVATE_KEY_BASE64,通过环境变量传入,绝不出现在命令行参数或仓库里,入口脚本是 sign-plugin-catalog.sh。
  • 昂贵的构建/签名开始前,verify-plugin-catalog-key-pair.sh 会先确认"这把私钥推导出的公钥 = 应用内嵌公钥",防止误换钥匙后发布的目录全量失效。
  • 它和 Sparkle 自动更新用的 EdDSA 密钥对(SPARKLE_PRIVATE_KEY)是两把独立的钥匙:前者保目录、后者保应用更新,职责分离。

GitHub Actions发布流程:从源码到"公证上架"

流水线定义在 docs/github-actions.md 中,核心工作流如下表:

工作流触发方式产物
BuildPR / main 推送测试、本地化校验、网站构建(只验不发)
Prepare Release手动校验版本号、编译 changelog、推 tag
Releasev*tag签名公证 DMG、GitHub Release、Sparkle appcast
Plugin Releaseplugins-*tag签名插件包 + 签名目录
Nightly每日定时独立的 Nightly 应用与插件目录

以 release.yml 为例,一次完整的应用发布是这样走的:

  1. 校验 tag:tag 必须与 Configs/AppVersion.xcconfig 中的MARKETING_VERSION完全一致,防止手滑发布错版本。
  2. 目录预检:运行 preflight-app-plugin-catalog.swift,确认线上插件目录与本次发布兼容且已签名——目录过期或缺失时应用发布直接中止。
  3. 导入证书:从 secret 还原.p12,创建临时钥匙串,找出Developer ID Application签名身份;用完即删。
  4. 分层签名:先签 Sparkle 框架内部的 XPC、dylib、Finder 右键扩展,最后才签主 App 并挂 entitlements,然后codesign --verify --deep --strict全量复核。
  5. 公证与装订:notarytool向 Apple 提交 DMG 并等待回执,stapler staple把票据装订进镜像,spctl本地模拟 Gatekeeper 放行。
  6. 生成 Sparkle appcast:用sign_update对 DMG 做 EdDSA 签名,写入sparkle:edSignature到 docs/appcast.xml——这就是应用内"检查更新"所读的源。
  7. 不可变候选 + 无凭据验证 + 发布:构建产物先上传为 immutable artifact,再由一个不带任何签名凭据的独立 job 验证 CLI 产物,最后 publish job 才创建 GitHub Release 并把 appcast 提交回 main。

插件发布 plugin-release.yml 则是"增量"思路:先由 plan-plugin-release.py 对比旧目录算出哪些插件真的变了(auto/selected/all三种模式),只构建签名选中的包,再合并进本 ABI 线路的目录、用 Ed25519 签名后提交回docs/plugins/v7/catalog.json,未变化的条目继续指向旧资产。这样一次只更新几个插件,用户也只会看到真正有新版本的条目。

新手速查:读懂这套流程的 5 个要点

  • 插件 = 目录条目 + 签名包:plugin.json声明身份与能力,目录条目提供下载链接与校验和,两层校验缺一不可。
  • 签名分三把钥匙:Developer ID 签应用与插件代码,Ed25519 签插件目录,Sparkle EdDSA 签应用更新,各司其职。
  • CI 只验不发:build.yml 不读任何发布 secret,发布权限收敛在专门的 publish job 中,缩小凭据暴露面。
  • 发布入口统一:本地用make release(见 Makefile),云端用 prepare-release.yml 的 Prepare Release,二者共享同一套 release.py 逻辑。
  • 通道隔离:Nightly 与稳定版使用独立的 Bundle ID、目录线路、钥匙串服务与 CLI 身份,互不覆盖。

想进一步深入,建议按顺序阅读:docs/plugins/local-native-plugins.md 了解插件包结构与本地开发,docs/plugins/plugin-catalog.md 了解目录格式与发布顺序,以及 docs/github-actions.md 了解全部工作流与 secret 配置清单。

【免费下载链接】MacTools

A free and open-source collection of native macOS menu bar tools.

项目地址:https://gitcode.com/gh_mirrors/mac/MacTools
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/23 1:49:03

STC8G1K17驱动MAX30205:51单片机实现0.1℃体温监测的I²C时序与校准指南

简介:本资源面向51单片机初学者与嵌入式传感器开发者,提供STC8G1K17驱动MAX30205高精度体温传感器的完整工程实践。STC8G1K17基于51内核并集成硬件I2C接口,MAX30205测量精度可达0.1C,适合医疗健康监测与物联网测温场景。压缩包共3…

作者头像 李华
网站建设 2026/10/23 1:48:37

骨质疏松诊断新标准与影像学技术应用指南

1. 骨质疏松诊断的临床痛点与共识价值第一次拿到骨密度报告时,我和大多数临床医生一样困惑——T值-2.5到底意味着什么?为什么同一个患者在不同设备上的检测结果会相差10%?这些疑问促使我深入研究了最新发布的《骨质疏松影像学与骨密度诊断专家…

作者头像 李华
网站建设 2026/10/21 6:11:50

Labview数据采集例程避坑指南:生产者消费者与状态机实战

简介:这份LabVIEW基础例程资源面向图形化编程初学者与工程应用入门者,围绕报表生成、气象监测与人机界面三大方向,帮助读者快速建立LabVIEW编程思维并掌握实用开发技巧。内容涵盖仿真PPT演示、空空导弹控制模拟、界面设计技巧、HMI人机界面、…

作者头像 李华