你在填什么
在 LingCode 里点击 Magic Deploy 并选择 App Store Connect (API key) 时,你会看到四个字段。每一个都来自 Apple 开发者门户中不同的页面——本指南按 LingCode 展示它们的顺序逐一说明。
| 字段 | 含义 | 去哪获取 |
|---|---|---|
| Key ID | API Key 的 10 位标识,如 ABC123XYZ0。 | App Store Connect → Users and Access → Integrations → Keys |
| Issuer ID | 团队 API 集成的 UUID。 | 同一个 Keys 页面(显示在表格上方) |
| Team ID | 10 位 Apple Developer Team ID,如 HPTTZS5J27。 | Apple Developer → Membership Details |
| .p8 文件 | 创建 API Key 时 Apple 只生成一次的私钥。 | 创建 Key 的瞬间下载——保存为 AuthKey_<KeyID>.p8 |
两个应用内捷径能让这件事更轻松。Magic Deploy 会在任何 xcodebuild 调用之前先跑一次 预检:确认 Xcode(不是仅 Command Line Tools)处于选中状态,并确认 Keychain 里有与 Team ID 匹配的 Apple Distribution 证书——一秒钟内识别掉首次部署约 70% 的失败。字段旁的 Auto-bump build number 勾选框会在每次归档前跑 agvtool next-version -all,消灭第二常见的失败("Redundant Binary Upload")。自动递增默认关闭——首次部署时记得打勾。
为什么这么多块?Apple 的部署流程很长,是因为它串起了一条 信任链:你的 Apple ID 证明你是你,你的 Team ID 证明是以哪个组织身份交付,你的 Apple Distribution 证书证明团队持有私钥,描述文件证明该应用可用此证书与相应 Entitlements,签好的 .xcarchive 把这条链一路带到用户设备上,每次启动都会被验证。LingCode 要你填的每一个字段都接入这条链的一环——缺一不可。术语不熟?见 术语表。
开始之前——一次性的 Apple 端准备
Magic Deploy 的四个字段是最后一步。Apple 那边必须先就位几件事,否则上传会以 UI 不总能解释清楚的方式失败。把这份清单走一遍,项目生命周期里就不用再管了。
1. 付费 Apple Developer Program 会员
免费 Apple ID 可以在自己 Mac 上构建和运行,但无法上传到 App Store Connect。到 developer.apple.com/programs/enroll 注册。个人 $99/年;组织账号需要 D-U-N-S 号,通常 3–10 个工作日审核。直到账号在 developer.apple.com/account 上显示为 Active,下面所有步骤都不会起作用。
2. 安装完整的 Xcode,不是只装 Command Line Tools
LingCode Magic Deploy 调用 xcodebuild,它住在完整的 Xcode 应用里——单独的 Command Line Tools 不够。从 Mac App Store 或 developer.apple.com/download 安装 Xcode,打开一次接受许可,然后在终端确认:
xcode-select -p
# 应该输出:/Applications/Xcode.app/Contents/Developer
如果它输出 /Library/Developer/CommandLineTools,把它指向 Xcode:
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
sudo xcodebuild -license accept
3. 在 Xcode 里用你的开发者账号登录
打开 Xcode → Settings → Accounts。点 +,选 Apple ID,用持有开发者会员的账号登录。你要交付所用的团队应该出现在 Apple ID 下方;点击它,确认 Team ID 与你将粘贴到 LingCode 的那一个一致。
4. 登录 Keychain 里有 Distribution 证书
xcodebuild 用 "Apple Distribution"(或旧称 "Mac App Distribution")证书为归档签名。最简单的办法是在首次归档时让 Xcode 自动生成——也可以自己创建:
- Xcode Settings → Accounts → Manage Certificates → + → Apple Distribution。Xcode 会创建证书并添加到登录 Keychain。
在终端里做个快速检查:
security find-identity -v -p codesigning | grep -i distribution
应能看到一行 1) 1A2B... "Apple Distribution: Your Name (HPTTZS5J27)"。括号里的 10 位就是你的 Team ID——必须与 LingCode 的 Team ID 字段匹配。
证书是绑定本机的。如果你换机或重装 Mac,要么从旧机的 Keychain Access 导出/导入私钥,要么新建一张证书并从新机交付。Magic Deploy 无法从没有匹配私钥的机器上传。
5. App Store Connect 上要有应用记录
Apple 不会接受一个还不存在的 Bundle ID 的上传。先创建记录:
- 登录 appstoreconnect.apple.com。
- My Apps → + → New App。
- Platforms:勾选 iOS、macOS 或二者——与你交付的 Xcode 目标对应。Magic Deploy 会从 Scheme 自动识别并选择正确的
altool --type。 - Bundle ID:选择与 Xcode 项目的 Bundle Identifier(见 target 的 General 页)完全一致的标识。下拉里没有?先到 developer.apple.com/account/resources/identifiers 以 Mac App 类型(不是 iOS)注册。
- SKU:任意不再重用的内部字符串。创建后无法更改。
com-example-myapp是安全的默认值。 - User access:保持 Full Access,除非有理由限制。
记录可以完全未填——没有截图、描述、定价——仍然无法提交审查,但可以往它上传 Build。这就是 Magic Deploy 干的事。
你的 Xcode 项目必须有这些设置
Apple 那边全准备好了,但如果 .xcodeproj 没为 Mac App Store 发布配好,上传照样会失败。打开目标的 Signing & Capabilities 页逐项确认:
Signing & Capabilities
- Automatically manage signing——开启。Magic Deploy 生成的
ExportOptions.plist把signingStyle设为automatic,手动签名会冲突。 - Team——设为你将粘贴到 LingCode 的 Team ID 对应的同一个团队。这里有黄色警告三角,点一下解决(通常就是"添加账号")。
- Bundle Identifier——与你在 App Store Connect 创建的应用记录匹配。拼写差异(
com.example.MyAppvscom.example.myapp)会在上传时被拒。 - App Sandbox——仅 Mac App Store 需要。没有就点 + Capability 加。只启用应用实际需要的 Entitlements(Network → Outgoing Connections、File Access 等)——不要"以防万一"全开,每项都会被审查。(iOS 目标跳过这一项——iOS 应用在 OS 层面默认沙盒。)
- Hardened Runtime——仅 Mac App Store 需要。Xcode 为新 macOS 目标自动加,老项目可能需要手动添加。(iOS 无此项。)
版本号与构建号
在目标的 General 页下 Identity 区:
- Version(
CFBundleShortVersionString)——面向用户的版本号,如1.2.3。App Store 审查看这个。 - Build(
CFBundleVersion)——内部构建号。必须严格大于你此前为相同 Version 上传过的所有构建号。如果你上传了1.2.3 (42),下次1.2.3的上传至少得是43。许多首次用 Magic Deploy 的失败就是"忘了往上加"。
Scheme
LingCode 选择 xcodebuild -list 返回的 第一个 Scheme。如果你的项目有多个 Scheme(App + 测试 + 辅助目标),请确保构建可分发 App 的那个排在最前——在 Xcode → Product → Scheme → Manage Schemes 里重排。
在同一个对话框里确认 Scheme 是 Shared。非 Shared 的 Scheme 住在你个人的 xcuserdata/ 里,xcodebuild 可能看不到。
步骤 1 — 创建 App Store Connect API Key
这一步一次拿下四个字段里的三个:Key ID、Issuer ID 和 .p8 文件。
- 用持有开发者账号的 Apple ID 登录 appstoreconnect.apple.com。
- 顶部导航点 Users and Access。
- 切到 Integrations 标签,侧边栏选 App Store Connect API(有时只叫 Keys)。
- 点 + 生成新 Key。起名为 "LingCode Magic Deploy",权限选——App Manager 足够上传 Build;若你还想让 LingCode 之后管理 App 元数据,用 Admin。
- 点 Generate。Apple 会显示一次性的 Download API Key 链接。
.p8 文件只能下载一次。Apple 不会让你重新下载。丢了就只能作废这把 Key 再新建一把。保存到你有备份的地方——文稿、iCloud 云盘,或支持文件附件的密码管理器。
下载的文件名通常是 AuthKey_ABC123XYZ0.p8。AuthKey_ 和 .p8 之间那 10 个字符就是你的 Key ID。同一个 Key ID 出现在 Keys 页表格里;表格上方(Issuer ID 旁)那个长长的 UUID 就是你的 Issuer ID。
复制到 LingCode
- Key ID → 粘贴到 Key ID 字段。
- Issuer ID → 粘贴到 Issuer ID 字段。
- .p8 文件 → 在 LingCode 里点 Browse… 选刚下载的文件。
步骤 2 — 获取 Team ID
Team ID 住在另一个站点——Apple Developer 门户,不是 App Store Connect。
- 用同一个 Apple ID 登录 developer.apple.com/account。
- 侧边栏点 Membership Details(老账号可能只显示 Membership)。
- 复制 10 位 Team ID。
如果你属于多个团队(个人 + 组织等),确认选的团队就是你要交付应用在 App Store Connect 记录的那个团队。Team ID 与 API Key 必须对应同一个团队。
步骤 3 — 点击 Deploy
四个字段全填好、.p8 也选好后,Deploy to App Store 按钮就会变亮。在讲 LingCode 实际执行什么之前,先看看手动版是什么样——这有助于你理解自动化的意义。
典型的手动归档 & 上传流程
没有 Magic Deploy 时,你大概会在 Xcode 和 App Store Connect 里走这串动作:
- 创建 App 记录。在 App Store Connect → My Apps → +,用与 Xcode 项目相同的 Bundle ID 新建 App。Bundle ID 还不存在就没法上传 Build。
- 选择发布 Scheme。在 Xcode 的 Scheme 下拉里选能构建可分发目标的 Scheme(通常就是你的 App 的 Scheme,Release 配置——见 Product → Scheme → Edit Scheme → Archive)。
- 归档。Product → Archive。Xcode 构建 Release、用团队证书签名(自动签名会临时取回或创建 Distribution 描述文件),产出
.xcarchive到~/Library/Developer/Xcode/Archives/。 - 打开 Organizer。归档完成后 Xcode 会自动跳到 Window → Organizer → Archives。选刚做好的那个。
- Validate(可选但推荐)。点 Validate App。Xcode 与 App Store Connect 交互检查归档——缺失图标、错误的 Info.plist 键、Entitlements 问题会在上传前暴露。
- Distribute App。点 Distribute App → App Store Connect → Upload。Xcode 会问签名方式(选 Automatically manage signing),然后上传到 App Store Connect。网络好时 1–5 分钟,视包大小而定。
- 等待处理。Build 进入 App Store Connect 的 Processing 状态。Apple 的构建服务器会自行校验、符号化崩溃信息、提取元数据。耗时 2–30 分钟,不在你掌控之内。
- 提交审查或分发到 TestFlight。处理完成后,Build 可挂到新 App 版本(用于 App Store 审查)或挂到 TestFlight 组(用于内测/外测)。
最烦的是 3–6 步:在 Xcode 里来回点、每次答同样的签名问题、等 Organizer UI 响应。Magic Deploy 把这些全替换掉。
LingCode Magic Deploy 实际执行什么
在底层,Deploy to App Store 按钮调的是与 Xcode 相同的命令行工具。运行时你在项目的 build/ 目录能看到。按顺序:
- 找到项目与 Scheme。LingCode 在已打开的项目目录里找
.xcodeproj,然后跑xcodebuild -list -project <project> -json枚举 Scheme,选第一个。UI 里没有 Scheme 选项——多 Scheme 项目里第一个不是你要的,请在 Xcode 的 Manage Schemes 重排,或暂时手动归档。 - 归档。
Destination(xcodebuild archive \ -scheme <scheme> \ -configuration Release \ -archivePath build/<scheme>.xcarchive \ -destination "generic/platform=macOS"generic/platform=macOS或generic/platform=iOS)和altool的--type参数会从 Scheme 的SUPPORTED_PLATFORMS自动选。你会在进度日志里看到[App Store] Detected platform: iOS或macOS,构建前可以确认。 - 生成
ExportOptions.plist。LingCode 会向build/ExportOptions.plist写入三键 plist:
这就是 Team ID 字段为什么重要——它最终落到这里,必须与你 Keychain 里安装的签名证书所属团队一致。<key>method</key> <string>app-store</string> <key>teamID</key> <string><your Team ID></string> <key>signingStyle</key> <string>automatic</string> - Export。
产出xcodebuild -exportArchive \ -archivePath build/<scheme>.xcarchive \ -exportPath build/AppStoreExport \ -exportOptionsPlist build/ExportOptions.plistbuild/AppStoreExport/<scheme>.app,一个签好名、打包完毕、可上传的 App 包。 - 上传。
就是 Xcode 的 Distribute App → Upload 内部用的那个API_PRIVATE_KEYS_DIR=<dir with .p8> xcrun altool \ --upload-app \ -f build/AppStoreExport/<scheme>.app \ --type macos \ --apiKey <Key ID> \ --apiIssuer <Issuer ID>altool。你提供的.p8是它给 App Store Connect 签 JWT 的依据。
以上命令的每一行 stdout / stderr 都会实时流到进度面板,所以出问题时(坏证书、缺 Entitlement、App Store Connect 校验失败)你看到的就是 Xcode 本会告诉你的那条错误——不用点 Organizer 去翻。
成功后,Build 以 Processing 状态落到 App Store Connect。Apple 处理完(2–30 分钟,不在 LingCode 掌控之内)后,它会出现在 TestFlight → Builds 里,可提交审查或分发测试。
读进度日志
Magic Deploy 运行时,右侧面板会流式显示 xcodebuild 和 xcrun altool 的实时输出。所有以 [App Store] 开头的行是 LingCode 自己的状态标记;其他都是 Apple 工具的原样输出。
一次成功的跑大概长这样:
[App Store] Archiving...
Build settings from command line:
...
ArchiveSucceeded
[App Store] Writing ExportOptions.plist...
[App Store] Exporting...
ExportArchive: signing
ExportArchive: writing /…/build/AppStoreExport/MyApp.app
[App Store] Uploading...
*** Upload Progress: ...
No errors uploading '…/MyApp.app'.
[App Store] Upload complete. Check App Store Connect for the new build.
出问题时去哪看:滚到日志最末端。xcodebuild 在构建过程中会打印一堆警告——真正的错误几乎总在最后 20 行,通常在 ** ARCHIVE FAILED **、** EXPORT FAILED ** 或 *** Error: ... 开头那行之后。LingCode 的简短提示 "Archive failed. Check the log above." 只是指路牌;诊断细节在原始输出里。
按阶段排错
按失败发生的阶段分类——各自的修复路径不同。
归档阶段(xcodebuild archive)
大多数首次错误在这里——因为这是你的项目第一次真正为 Release 构建并做真实签名。
| 日志包含 | 原因 | 修复 |
|---|---|---|
| No signing certificate "Apple Distribution" found | Keychain 里没有 Distribution 证书,或有的那张属于别的团队。 | Xcode → Settings → Accounts → Manage Certificates → + → Apple Distribution,再重新 Deploy。 |
| No profiles for 'com.example.app' were found | 自动签名无法为此 Bundle ID 创建或取回描述文件,通常是 Bundle ID 未在 developer.apple.com 注册。 | 到 developer.apple.com/account/resources/identifiers 以 Mac App 类型注册 Bundle ID,再重试。 |
| Provisioning profile doesn't include the current device | 你开着手动签名用了错误的描述文件。 | Signing & Capabilities → 重开 Automatically manage signing。 |
| Command PhaseScriptExecution failed with a nonzero exit code | 某个 Run Script 构建阶段(CocoaPods、SwiftLint、SwiftGen 等)出错。 | 打开目标的 Build Phases,找到失败脚本,它实际的错误就在上面几行的日志里。 |
Swift 编译错误(error: …) |
Release 构建编译不过——常见原因是 #if DEBUG 分支或条件 Import。 |
在 Xcode 里把 Scheme 的 Run 配置切到 Release,本地构建直到通过。 |
| Missing required architecture x86_64 | 项目没构建 Universal 二进制。Mac App Store 接受 Apple Silicon-only,但混合配置常在这儿挂。 | Target → Build Settings → Architectures → 设为 $(ARCHS_STANDARD)。移除任何硬编码的 arm64-only 覆盖。 |
| The archive was not created | Scheme 未启用 Archive,或 Archive 的 Build Configuration 不是 Release。 | Product → Scheme → Edit Scheme → Archive → Build Configuration: Release,并确保 App target 已勾选。 |
导出阶段(xcodebuild -exportArchive)
| 日志包含 | 原因 | 修复 |
|---|---|---|
| error: exportArchive: No "Apple Distribution" signing certificate matching team ID | 生成的 ExportOptions.plist 里的 teamID 与 Keychain 里任何证书都不匹配。 |
修正 Magic Deploy 的 Team ID。跑 security find-identity -v -p codesigning——括号里的 10 位就是该粘的。 |
| error: Provisioning profile "…" doesn't include the entitlement com.apple.security.app-sandbox | 目标未启用 App Sandbox,但 Mac App Store 要求有。 | Signing & Capabilities → + Capability → App Sandbox。 |
| error: Provisioning profile "…" doesn't include the hardened runtime | Release 配置未启用 Hardened Runtime。 | Signing & Capabilities → + Capability → Hardened Runtime,或 Build Settings 里设 ENABLE_HARDENED_RUNTIME = YES。 |
| error: No matching profiles found for bundle identifier … | 自动签名能生成 Development 描述文件但生成不了 Distribution——常见原因是 App Store Connect 的应用记录还不存在。 | 在 App Store Connect 创建应用记录(见"开始之前"第 5 步),再重新 Deploy。 |
上传阶段(xcrun altool --upload-app)
| 日志包含 | 原因 | 修复 |
|---|---|---|
| Unable to find API key with Key ID … | altool 在你选的目录里找不到 AuthKey_<KeyID>.p8。 |
在 Magic Deploy 里重新选 .p8 文件,并确保文件名精确为 AuthKey_<KeyID>.p8。改名会破坏 altool。 |
| Authentication credentials are missing or invalid (HTTP 401) | Key ID、Issuer ID 或 .p8 对不上。 |
直接从 App Store Connect 的 Keys 页面复制,不要手打。Issuer ID 是 UUID(有短横);Key ID 是 10 位字母数字。 |
| Forbidden / ITMS-90166 | API Key 没有上传权限。 | App Store Connect → Users and Access → Integrations,编辑 Key,设为 App Manager 或 Admin。Developer 只读。 |
| ERROR ITMS-90189: "Redundant Binary Upload" | 你正在上传的 Build 号在 Apple 服务器上对此 Version 已经存在。 | 在 Xcode 提升 Build 号(target → General → Build)后重归档。 |
| ERROR ITMS-90035: "Invalid Signature" | 签名 App 未通过 Apple 的 codesign 校验——通常是嵌入框架用 Development 证书签了名,或某个 Helper 工具缺自身签名。 | 检查目标的 Signing & Capabilities → Frameworks,确保每个嵌入框架写的是 Embed & Sign。Helper 工具要加一个 Embed & Sign 的 Copy Files 阶段。 |
| ERROR ITMS-90338: "Non-public API usage" | 某个框架(经常是分析 SDK)链接了 Apple 私有 API。 | 升级或移除该 SDK。Apple 的错误信息会指明具体符号。 |
| ERROR ITMS-90713: "Missing Info.plist value" | 缺少 NSCameraUsageDescription、LSApplicationCategoryType 等必要 Key。 |
把该 Key 加到目标的 Info.plist。错误信息里写了具体哪一个。 |
| The network connection was lost / timed out | 网络不稳。大包在慢速连接上会超 600 秒预算。 | 重试。若持续失败,把日志里的 xcrun altool 命令直接复制到终端跑——altool 会给更丰富的进度条,有时还能续传。 |
上传成功后会发生什么
Magic Deploy 完成时,Build 在 App Store Connect → 你的 App → TestFlight → macOS → Builds,初始状态是 Processing。Apple 的构建服务器会做它自己的上传后校验——符号化崩溃信息、扫描私有 API 使用、提取元数据。通常 5–30 分钟,高峰时可能拉长到一小时以上。处理完成(或以 ITMS- 错误失败)会发邮件。
处理完后,你有两条路:
- TestFlight——把 Build 挂到内测或外测组分发给测试者。内测最多 100 位拥有 App Store Connect 访问权的用户,立即可拿到。外测要过一次简短的 Beta App Review(小更新通常 24h 内)。
- Submit for review——把 Build 挂到 macOS App 区下的新版本,填必要元数据(描述、截图、定价、隐私),点 Add for Review。macOS App 审查通常 24–72 小时。
如果 Build 压根没出现——连 Processing 都看不到——查一下你 Apple ID 绑定的邮箱。Apple 会给服务端校验失败的二进制发拒稿邮件(ITMS-90xxx 代码),那些被拒的 Build 不会出现在 App Store Connect 里。
速查:出问题去哪改
| 症状 | 在哪修 |
|---|---|
| Magic Deploy 按钮一直灰着 | 四个字段之一为空,或 .p8 未附加。LingCode 会在启用按钮前校验四项。 |
| "No Xcode project found" | 你打开的是一个不含 .xcodeproj 的文件夹。打开含 .xcodeproj 的文件夹,或直接打开 .xcodeproj。 |
| "No schemes found" | Scheme 没设为 Shared。Xcode → Product → Scheme → Manage Schemes → 勾选目标 Scheme 的 Shared。 |
| 归档阶段失败 | 在 Xcode 里切 Release,自己跑 Product → Archive。修好 Xcode 抱怨的事,再回来重试 Magic Deploy。 |
| 导出阶段失败 | 99% 是 ExportOptions.plist 的 teamID 与 Keychain 对不上。跑 security find-identity -v -p codesigning,修正 LingCode 的 Team ID。 |
| 上传阶段 HTTP 401/403 | 问题在 API Key。重下 .p8,或新建一把 App Manager 权限的 Key 再试。 |
| 上传成功但 Build 没出现 | 查 Apple ID 邮箱里的 ITMS- 拒稿。如果没有,等 30 分钟——Apple 的处理队列时快时慢。 |
| "Redundant binary upload" | 在 Xcode 提升 Build 号。大于前值的任意整数即可。 |
| 还是卡住 | 把日志里精确的 xcodebuild 或 xcrun altool 命令复制到终端跑——错误信息一模一样但比 "Archive failed. Check the log above." 更好搜。 |
常见错误(速查清单)
- 给
.p8文件改名了。LingCode 找的是AuthKey_<KeyID>.p8。改了就改回来,或确保 Key ID 字段与文件名中AuthKey_和.p8之间的内容一致。 - 权限级别不对。Developer 级别的 Key 可读不可上传。需要 App Manager 或 Admin。
- 混淆 Issuer ID 与 Key ID。Key ID 是 10 个字符,每把 Key 在表格里单独显示。Issuer ID 是长 UUID(有短横),在 Keys 页顶部出现一次。
- Team ID 拿错团队。Apple ID 跨多团队时,先在开发者门户里切到正确的团队再复制。
- Bundle ID 未注册。应用的 Bundle Identifier 需要在 App Store Connect 有应用记录,并且该标识本身需要存在于 developer.apple.com 的 Certificates, IDs & Profiles。先到 App Store Connect → My Apps → + 创建应用记录,用与 Xcode 项目相同的 Bundle ID。
- 忘了提升 Build。同一 Version 下每次上传都要更高 Build 号。这是第二次上传失败的最常见原因——勾选面板里的 Auto-bump build number 让 LingCode 替你跑
agvtool next-version -all。 - 开着手动签名。Magic Deploy 的
ExportOptions.plist用signingStyle = automatic。目标若开着手动签名,导出会失败或产出不可签名的二进制。
安全须知
.p8 私钥等同于你 App Store Connect 账号的密码。按密码待它:别提交到 Git,别发到 Slack,队友离开或电脑丢失就到 Keys 页面吊销。LingCode 从不把 .p8 上传到任何地方——它留在你的 Mac 上,只在上传时交给 Apple 的 xcrun altool。
延伸阅读
本页概念的一手资料,来自 Apple 与 IETF:
- LingCode 部署术语表——本页每个术语的定义。
- App Store Connect API 参考(Apple)——
altool与 LingCode 在底层打交道的对象。 - Distributing your app for beta testing and releases(Apple)——官方 Xcode 分发指南。
- Code Signing Guide(Apple)——证书、描述文件、签名实际证明什么的深入介绍。
- RFC 7519 — JSON Web Token——Apple API 认证用的 JWT 规范。
- TestFlight(Apple)——你的上传首先落到的 Beta 服务。