news 2026/10/2 2:10:43

Presenton Mac App Store 构建实战:MAS 打包的证书、Profile 与脚本完整避坑指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Presenton Mac App Store 构建实战:MAS 打包的证书、Profile 与脚本完整避坑指南

Presenton Mac App Store 构建实战:MAS 打包的证书、Profile 与脚本完整避坑指南

【免费下载链接】presentonOpen-Source AI Presentation Generator and API (Gamma, Canva, Beautiful AI, Decktopus, Presentations AI Alternative)项目地址: https://gitcode.com/GitHub_Trending/pr/presenton

把 Electron 应用送进 App Store,最劝退的往往不是写代码,而是证书和 provisioning profile 这一套 Apple 的规矩。Presenton 是一个内置 Next.js 前端与 FastAPI 后端的 AI 演示文稿生成器,仓库已经把 Mac App Store 构建的工程化配置铺好了:沙盒 entitlements 文件、build.js构建脚本、npm 目标脚本全部就位,你要做的只是补齐 Apple 开发者账号侧的四样东西,然后跑一条命令。这篇按"一次真实构建"的动线走:先备好材料,再执行打包,最后处理报错。

先扫两张表:目标、命令与环境变量

这节解决"最高频信息 30 秒拿到"的问题,后面所有环节都是这两张表的展开。

构建目标与所需证书:

构建目标用途npm 命令(在electron/下执行)所需证书
dmg不走 App Store 的直接下载分发npm run build:all:mac:signedDeveloper ID Application + 公证凭据
mas-dev注册 Mac 上的沙盒内测npm run build:all:mas-devApple Development
masApp Store 提交npm run build:all:masApple Distribution + 3rd Party Mac Developer Installer(两张证书缺一不可)

三个目标全部由PRESENTON_MAC_TARGET环境变量驱动,上面三个 npm 脚本内部已经设好,你不必手动指定。两个关键身份标识写死在 build.js 顶部:Bundle ID 为com.presenton.presenton,Team ID 为S6W5C54KL6(同时通过mac.extendInfo.ElectronTeamID写进应用)。

环境变量速查:

变量用于说明
PRESENTON_MAC_TARGET全部由 npm 脚本设置,用脚本时别手动设
PRESENTON_MAS_DEV_IDENTITYmas-dev开发签名身份,如Apple Development: Your Name (TEAMID)
PRESENTON_MAS_DISTRIBUTION_IDENTITYmas分发身份,如Apple Distribution: Your Org (TEAMID)
PRESENTON_MAS_IDENTITYmas分发身份的别名
CSC_NAME两种 MAS 目标目标专属变量没设时的回退
PRESENTON_APP_STORE_VERSIONmasApp Store 版本号(x.y.z),package 版本带-beta后缀时必填
PRESENTON_APP_STORE_BUILDmasApp Store build 号,不设则默认取短版本号
PRESENTON_CODESIGN_TIMESTAMPmas/dmg设为1恢复 codesign 时间戳(默认本地打包用--timestamp=none)
PRESENTON_CODESIGN_TIMESTAMP_RETRIESmas/dmg时间戳失败重试次数,默认 4

准备阶段:四样材料一次备齐

这节解决"构建前到底要向 Apple 要什么、本地要放什么"的问题。材料顺序按 Apple 开发者工作流排:证书 → App ID → Profile → entitlements。

在 Xcode 里生成两张证书

为什么是两张:Apple Development 用于mas-dev沙盒内测;Apple Distribution 用于mas商店构建。而mas构建实际要签名两个东西——应用本体和.pkg安装包,所以 build.js 的resolveMasSigningIdentities会同时找应用证书(Apple Distribution或3rd Party Mac Developer Application)与安装包证书(3rd Party Mac Developer Installer),缺一就抛错退出。

  1. 打开 Xcode →Settings→Accounts→ 选择你的团队 →Manage Certificates。
  2. 点+,先创建Apple Development(给内测构建用)。
  3. 再点+,创建Apple Distribution(给商店构建用;安装包证书3rd Party Mac Developer Installer通常随团队在 Portal 上签发,导入钥匙串即可)。

在 Portal 注册一个匹配的 App ID

去 Apple Developer Portal →Certificates, Identifiers & Profiles→Identifiers→App IDs,创建一个 macOS App ID,取值填com.presenton.presenton。如果你用自己的 ID,记得同步改掉 build.js 里的APP_ID,否则签名和 profile 会互相不认识。

下载两个 Provisioning Profile 放进 electron/build/

Provisioning profile 可以理解为"设备白名单通行证":它把证书、App ID 和允许的机器绑在一起,Apple 服务器凭它验证这个构建是否合法。两个目标各需要一份,对应关系如下:

Profile类型绑定证书保存为
开发 profilemacOS App DevelopmentApple Developmentelectron/build/AppleDevelopment.provisionprofile
商店 profileMac App StoreApple Distributionelectron/build/MacAppStore.provisionprofile

两个细节:

  • 构建脚本按候选文件名列表查找,mas-dev还接受AppleDev.provisionprofile、AppDev.provisionprofile作回退;mas还接受AppDistri.provisionprofile。
  • 真实 profile 不要提交进 git——仓库里那个MacAppStore.provisionprofile.replace_me占位文件就是让你只提交"待替换"状态用的。

放入后先验证能否解码:

cd electron # 两个文件都应能解码出 plist,解码失败说明文件不对或已损坏 security cms -D -i build/AppleDevelopment.provisionprofile security cms -D -i build/MacAppStore.provisionprofile

Profile 通常按年过期,到期后重新下载替换本地文件即可。

看清 entitlements 里每个开关管什么

这节解决"沙盒应用为什么能跑起来"的问题。entitlements 是"沙盒权限开关清单",entitlements.mas.plist 逐项声明了主应用的能力:

  • com.apple.security.app-sandbox:开启 App Sandbox,MAS 的硬性要求;
  • com.apple.security.application-groups:S6W5C54KL6.com.presenton.presenton,让应用和组件共享数据容器;
  • com.apple.security.cs.allow-jit:允许 JIT 编译,Electron 渲染进程依赖它;
  • com.apple.security.network.client/com.apple.security.network.server:允许发起和监听连接——Presenton 内置的 Next.js 与 FastAPI 本地服务全靠这两项;
  • com.apple.security.files.user-selected.read-write:读写用户主动选定的文件(导入文档、导出 PPTX 的路径);
  • com.apple.security.files.downloads.read-write:读写下载目录。

辅助进程的 entitlements.mas.inherit.plist 只有两项:app-sandbox加com.apple.security.inherit,意思是"继承主进程的能力边界,不额外开洞"。

执行阶段:三条构建路径

这节解决"命令怎么跑、产物落在哪"的问题。所有命令都在electron/目录下执行;首次使用先跑npm run setup:env,它会串起npm install、FastAPI 的uv sync、Next.js 依赖安装以及导出运行时与 ImageMagick 的准备。

完整构建(推荐首发路径)

会重建 Next.js、FastAPI、导出运行时再打包应用,适合首次或大改动后:

# 路径一:MAS 开发构建——只在开发 profile 注册过的 Mac 上能运行 PRESENTON_MAS_DEV_IDENTITY="Apple Development: Your Name (TEAMID)" \ npm run build:all:mas-dev # 路径二:MAS 分发构建——产物用于上传 App Store Connect # 当前 package.json 版本带 -beta 后缀,PRESENTON_APP_STORE_VERSION 是必填项 PRESENTON_MAS_DISTRIBUTION_IDENTITY="Apple Distribution: Your Org (TEAMID)" \ PRESENTON_APP_STORE_VERSION=1.0.0 \ npm run build:all:mas

只重跑打包阶段

资源已经构建好、只想再跑一次 electron-builder 打包时(比如刚改了签名身份):

PRESENTON_MAS_DEV_IDENTITY="Apple Development: Your Name (TEAMID)" \ npm run dist:mac:mas-dev PRESENTON_MAS_DISTRIBUTION_IDENTITY="Apple Distribution: Your Org (TEAMID)" \ PRESENTON_APP_STORE_VERSION=1.0.0 \ npm run dist:mac:mas

注意:dist:*脚本依赖 build.js 里的资源就绪校验——它会逐一检查 FastAPI 二进制、LLM 模型元数据、Next.js standalone server、导出任务 runner 与 export-core 包,任何缺失都会提前报错,避免打出"内置服务起不来"的坏包。

不走 App Store:直接出签名 DMG

只想产出签名并公证的磁盘映像、绕过商店审核时:

# 使用 Developer ID Application 证书,需 Apple 公证凭据 npm run build:all:mac:signed

这条路径的 Developer ID 证书、notarytool 凭据存储与 Gatekeeper 验证细节见 直接分发指南。

带 beta 后缀的版本号坑

当前仓库 package.json 的版本是0.9.11-beta,带-beta后缀。mas目标的版本号推导逻辑(build.js 中的getAppStoreBundleShortVersion)是:

  1. 优先读PRESENTON_APP_STORE_VERSION,必须匹配x.y.z三段点分整数,否则直接抛错;
  2. 未设置时尝试从 package 版本截取(\d+)\.(\d+)\.(\d+)前缀;
  3. 截取失败(版本号根本不是语义化格式)就抛 "Cannot derive an App Store version from package version"。

PRESENTON_APP_STORE_BUILD走同样的校验风格(1~3 段点分整数,如42或1.0.1),不设则回退为短版本号。所以 beta 版本构建mas时,最省事的写法:

export PRESENTON_APP_STORE_VERSION=1.0.0 # 商店版本号,三段点分整数 export PRESENTON_APP_STORE_BUILD=42 # build 号,可选

产物都落在 electron/dist/

路径随架构(arm64/x64)略有不同,典型布局:

electron/dist/ mas-dev-arm64/ # 开发签名的 .app,仅限注册 Mac 运行 mas-arm64/ # 分发签名的 .app,供 App Store Connect 处理 Presenton-<version>.pkg # 上传 App Store Connect 的 MAS 安装包 Presenton-<version>.dmg # 签名并公证的直接分发 DMG

mas构建产出的.pkg就是最终上传 App Store Connect 的东西。

排错:五类高频报错的对照处理

这节解决"构建失败时怎么快速定位"的问题。每条按"报错长什么样 → 为什么会这样 → 一步修复"展开。

报错信息(节选)原因修复动作
Missing MAS development/distribution provisioning profile. Expected: ...electron/build/里没有该目标对应的 profile 文件按上表把正确的.provisionprofile放入electron/build/,报错信息里列出的就是它期望的文件名
Found MAS ... provisioning profile, but macOS could not decode it: ...文件存在但security cms -D与openssl cms -verify都解不开——文件损坏、传错或占位文件从 Developer Portal 重新下载对应 profile 覆盖本地文件;别把真实 profile 提交进 git
Cannot derive an App Store version from package version "0.9.11-beta"package 版本提取不出x.y.z三段整数设置PRESENTON_APP_STORE_VERSION=1.0.0再跑构建
MAS development builds must be run on macOS because Apple signing tools are required.在非 macOS 平台(如 Linux CI)上跑了 MAS 目标换到有 Xcode 命令行工具(xcode-select --install)的 Mac 上执行
Missing MAS signing identity.后列出已有身份清单钥匙串里缺应用证书或安装包证书之一,或身份变量指向了开发证书按报错清单补装缺失证书到钥匙串;分发构建不能使用 Apple Development 等开发身份,脚本会显式拒绝

沙盒内辅助程序不可执行(FastAPI / 导出二进制打不开):build.js 的afterPack钩子会先对打包后的二进制执行chmod 755并清理与目标架构不符的原生 prebuild 目录;如果之后仍签名失败,回到准备阶段那两份 entitlements,确认沙盒应用被允许执行Contents/Resources/app/resources/下的辅助程序。

进阶:身份解析、时间戳、图标与内测限制

这节面向要深度定制构建流程的读者,日常跑通前两个阶段可以跳过。

签名身份解析与构建前预检。mas目标的身份解析链是:PRESENTON_MAS_DISTRIBUTION_IDENTITY→PRESENTON_MAS_IDENTITY→CSC_NAME→ 自动发现。脚本用security find-identity -v读全钥匙串,取身份限定词后自动匹配"应用证书 + 安装包证书"这对组合,并拒绝开发身份混入分发构建。正式启动打包前还会执行一次codesign预检:在临时文件上用选中的分发身份真签一次,30 秒超时——超时通常意味着 macOS 在等钥匙串/私钥授权弹窗,此时按提示解锁登录钥匙串并允许 codesign 访问 Apple Distribution 私钥即可。

时间戳开关。本地 MAS 打包默认给 codesign 追加--timestamp=none,不依赖 Apple 时间戳服务,无网或受限网络下不会挂起。需要时间戳时设PRESENTON_CODESIGN_TIMESTAMP=1恢复;时间戳偶发失败的重试次数由PRESENTON_CODESIGN_TIMESTAMP_RETRIES控制(默认 4 次,指数退避)。

图标。默认 macOS 图标是electron/resources/ui/assets/images/presenton_short_filled.png。要为商店提供正式.icns,放到electron/build/icon.icns并同步更新 build.js 的mac.icon字段;生成图标集的源 PNG 在electron/build/icon.iconset/。

本地沙盒测试的四条边界。

  • MAS 签名的应用必须由mas或mas-dev目标产出,普通 DMG 构建不具备同等的沙盒兼容性;
  • mas-dev构建只能在开发 profile 里注册过的 Mac 上启动,适合 TestFlight 式内测;
  • mas分发构建通常无法在本地直接启动,它的归宿是 App Store Connect 的处理与发布流水线;
  • mas-dev签名带--timestamp=none(见上时间戳开关),本地签名与网络状态无关。

下一步:把 .pkg 交给 App Store Connect

构建跑通后,动作只剩一个:把electron/dist/下mas产出的Presenton-<version>.pkg通过 App Store Connect 的上传入口提交,等待审核后发布。之后每次发版,记住固定三步:确认 profile 未过期 → 递增PRESENTON_APP_STORE_VERSION与 build 号 → 重跑build:all:mas。

延伸阅读(仓库内相对路径):

  • macOS 开发 README——全部构建目标速查,含npm run dev与 notarytool profilepresenton-notary说明
  • Mac App Store Setup——本文对应的官方设置文档
  • Direct Distribution——Developer ID 证书、公证与 DMG 验证流程
  • build.js——签名身份解析、profile 校验与版本号推导的完整实现

【免费下载链接】presentonOpen-Source AI Presentation Generator and API (Gamma, Canva, Beautiful AI, Decktopus, Presentations AI Alternative)项目地址: https://gitcode.com/GitHub_Trending/pr/presenton

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

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

CentOS Stream 10 下 vsftpd 虚拟用户配置实战与排障指南

上一篇我们在 CentOS Stream 10 上把 vsftpd 装好、让 FTP 服务能正常启停了。但你如果真拿系统里的真实账号去登录一次&#xff0c;多半会发现这条路不太好走&#xff1a;密码跟 SSH 登录是同一个&#xff0c;权限全靠系统目录去卡&#xff0c;用户想上传个文件你还得斟酌半天…

作者头像 李华
网站建设 2026/10/2 2:09:32

KLJN协议随机数生成器统计攻击:Matlab仿真与防御实践

做物理层安全研究这几年&#xff0c;我的一个体会是&#xff1a;越是宣称“信息论安全”的协议&#xff0c;越容易在随机源这个环节翻车。基尔霍夫-洛-约翰逊噪声&#xff08;KLJN&#xff09;安全密钥交换协议就是典型——它绕开RSA、ECC那套大整数分解和离散对数难题&#xf…

作者头像 李华
网站建设 2026/10/2 2:09:22

让 Codex 直连 Claude 网关:CC Switch 本地路由配置指南

让 Codex 直连 Claude 网关&#xff1a;CC Switch 本地路由配置指南 【免费下载链接】cc-switch A cross-platform desktop All-in-One assistant for Claude Code, Codex, OpenCode, OpenClaw, Grok Build & Hermes Agent. Only official website: ccswitch.io 项目地址…

作者头像 李华
网站建设 2026/10/2 2:06:57

ClaudeCode 终端AI编程助手:三大平台安装实战指南

老实说&#xff0c;第一次看到 ClaudeCode 这个词的时候&#xff0c;我以为是某个 VS Code 插件名。直到同事在终端里敲了一个claude&#xff0c;唰一下拉出命令行对话界面&#xff0c;我才反应过来&#xff1a;这东西不走 IDE&#xff0c;它直接住在你的终端里。作为 Anthropi…

作者头像 李华
网站建设 2026/10/2 2:06:03

Linux下NVIDIA显卡型号识别的三层诊断法

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/2 2:05:29

Spring Boot 3 + MyBatis-Plus 3.5.9 实战:CRUD、分页与性能优化

1. 项目背景与整体设计思路1.1 为什么在这个时间节点选择Spring Boot 3我最近在一个新项目里把技术栈切到了 Spring Boot 3 MyBatis-Plus 3.5.9&#xff0c;整体体验下来确实有不少值得说的东西。先说结论&#xff1a;如果你是一个新启动的 Java 后端项目&#xff0c;现在可以…

作者头像 李华