大多数 Capacitor CI/CD 失败来自同一短列表:iOS code 签名,缺失或过时的 macOS 工具,未能进入本机项目的 Web 构建,重复使用的构建号码,以及仅在上传时才会失败的商店要求。每个都有已知原因和可以应用一次的修复。这份指南将陷阱按管道阶段分组,包括错误、发生原因和需要更改的内容。
如果您正在从头设置管道,请先阅读 为 Capacitor 应用设置 CI/CD 然后使用此列表来加固它。
阶段 1:构建 Web 层
陷阱:本机应用程序传输的 Web 构建过时
症状: CI成功,但应用安装后显示昨天的UI。
原因: cap sync 拷贝的是当时的内容。如果流水线在web构建之前运行,或者web构建写入的文件夹与 webDir 中的文件夹不同,native项目会获取过时的文件。 cap sync 解决方法: webDir in capacitor.config.ts与打包工具的输出(对于Vite,
)匹配。 始终按照此顺序运行步骤,并在输出文件夹为空时失败。
bun install --frozen-lockfile
bun run build
test -f dist/index.html || { echo "web build missing"; exit 1; }
bunx cap sync
确保 webDir 匹配您的打包器输出(dist 为 Vite www 对于 Angular 与 Ionic 的情况, build 对于某些 React 配置的情况,
陷阱:开发服务器 URL 未从配置中删除
症状: 发布构建显示空白屏幕或尝试加载 http://192.168.x.x:5173.
原因: server.url 在 capacitor.config.ts 设置为实时重载并提交了
修复: 永远不要提交 server.url. 从 CI never 设置的环境变量中读取:
import type { CapacitorConfig } from '@capacitor/cli'
const config: CapacitorConfig = {
appId: 'com.example.app',
appName: 'Example',
webDir: 'dist',
...(process.env.LIVE_RELOAD_URL && {
server: { url: process.env.LIVE_RELOAD_URL, cleartext: true },
}),
}
export default config
陷阱:环境变量在错误的时间内被烘焙
症状: 生产应用程序与API阶段通信。
原因: Vite、webpack和Angular在构建时间内行内环境变量。存在于__CAPGO_KEEP_0__中的值是二进制中的一个,来自同一工作的任何__CAPGO_KEEP_0__。 bun run build 在二进制中,ran是唯一的,并且在任何来自相同作业的live update中都是如此。
Fix: 陷阱:锁文件漂移 cap sync.
CI中的插件版本与机器上的版本不同,原生编译失败,缺少符号。
症状: 将锁文件提交并使用
Fix: Pitfall: lockfile drift bun install --frozen-lockfile 或 npm ci. Pin @capacitor/core, @capacitor/ios, @capacitor/android, 和 @capacitor/cli 到相同的版本。版本不匹配是原生错误的常见来源;参见 修复Capacitor版本不匹配错误.
阶段 2:原生工具链
陷阱:错误的 Node、JDK 或 Xcode 版本
症状: Unsupported class file major version, The engine "node" is incompatible, 或 Xcode 错误关于SDK功能。
原因: 托管运行器图像更改,并且Capacitor 8 有固定的最低要求。
| 工具 | Capacitor 8 要求 |
|---|---|
| Node.js | 22 或更新 |
| JDK | 21 |
| Xcode | 26 或更新 |
| iOS 部署目标 | 15.0 |
Android minSdkVersion / targetSdkVersion |
24 / 36 |
修复: 将每个版本都明确地在管道中固定,而不是信任 latest:
- uses: actions/setup-node@v6
with:
node-version-file: .nvmrc
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '21'
- uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: '26'
陷阱:在 Xcode Apple 不再接受的构建
症状: 由于应用程序使用不支持的SDK进行构建,上传失败,显示错误信息。
原因: 自 2026 年 4 月 28 日起,App Store Connect 需要 Xcode 26 和 iOS 26SDK。自建 Mac 和旧的运行器图像仍然默认使用 Xcode 16。
解决方法: 选择一个 macos-26 图像或在运行器上安装 Xcode 26。详细信息在 Apple 的 Xcode 26 要求Capacitor应用程序.
陷阱:CocoaPods 和 SPM 混淆
症状: xcodebuild: error: 'App.xcworkspace' does not exist,或找不到 pods。
原因: 新Capacitor 8 项目使用 Swift Package Manager 构建 ios/App/App.xcodeproj . 使用较旧的项目使用 CocoaPods 和构建 ios/App/App.xcworkspace after pod install . 从较旧的教程中复制的管道假设工作区
Fix: 检查您的项目使用哪一个,并构建正确的文件。如果您正在迁移,请参阅 如何将您的 Capacitor 应用程序迁移到 SPM.
陷阱:Android 插件构建在 Gradle 升级后会中断
症状: Namespace not specified, package attribute is deprecated,或插件的错误 build.gradle 在更新 Android Studio 后
Fix: 固定 Android Gradle 插件 android/build.gradle升级到特定分支,首先更新插件。具体错误在 修复 Capacitor 插件构建错误与 AGP 9.
阶段 3: Code 签名
陷阱:iOS 签名仅在 Mac 上有效
症状: No signing certificate "iOS Distribution" found, No profiles for 'com.example.app' were found或 errSecInternalComponent.
原因: 你的 Mac 的密钥链持有证书,Xcode 下载配置文件。CI 运行器没有,且其密钥链在非交互式会话中锁定。
修复: 导入证书到临时解锁的密钥链,并在 Xcode 16 及其后版本中安装配置文件:
security create-keychain -p "$KEYCHAIN_PASSWORD" ci.keychain
security set-keychain-settings -lut 21600 ci.keychain
security unlock-keychain -p "$KEYCHAIN_PASSWORD" ci.keychain
security import dist.p12 -k ci.keychain -P "$P12_PASSWORD" -T /usr/bin/codesign
security set-key-partition-list -S apple-tool:,apple: -s -k "$KEYCHAIN_PASSWORD" ci.keychain
security list-keychains -d user -s ci.keychain login.keychain
PROFILES="$HOME/Library/Developer/Xcode/UserData/Provisioning Profiles"
mkdir -p "$PROFILES"
cp app.mobileprovision "$PROFILES/"
使用身份名称 Apple Distribution而不是遗留 iOS Distribution. fastlane的 setup_ci plus match 自动化此过程。 Capgo security.
构建
使用证书和配置文件作为环境变量, 在其机器上完成密钥链工作,因此Linux任务永远不会触及
错误:过期或被吊销的证书 症状:
Fix: 原因: bunx @capgo/cli@latest build prescan --platform ios 苹果分发证书和配置文件在一年后过期。团队成员在Xcode中创建新证书也可以使CI使用的配置文件失效。
解决方案:将过期日期添加到团队日历中,保持一个共享的分发证书用于CI,并在构建之前检查。
症状: fastlane hangs 等待一个 6 位数字 code.
解决方法: 使用 App Store Connect API 密钥((.p8key ID
base64密钥无法解码
症状: MAC verification failed, invalid keystore format, or base64: invalid input.
, 或 原因: .p12 复制 base64 值时添加的换行符,或者
解决方法: 编码在一行中,使用 -legacy 创建时 .p12 使用 OpenSSL 3:
base64 -i dist.p12 | tr -d '\n' > dist.p12.b64
openssl pkcs12 -export -legacy -inkey key.pem -in cert.pem -out dist.p12
陷阱:丢失的 Android 密钥库
症状: 无法签名更新,因为没有人有密钥库。
解决方案: 使用 Play App Signing 时,密钥库是上传密钥,Play 控制台支持可以注册一个新的密钥库。将密钥库存储在 CI 秘密中,并在离线备份中。绝不让它只存储在一个笔记本电脑上。 Android 密钥库生成器 如果您刚开始使用,会创建一个新的密钥库。
阶段 4:管道设计
陷阱:每次拉取请求都进行原生构建
症状: 慢速PR检查和大型macOS分钟账单。
原因: iOS在托管macOS运行器上构建的分钟是大多数CI计划中最昂贵的分钟,且大多数提交只触摸JavaScript。
解决方案: 在每个PR上运行lint、测试和web构建。 在发布标签或合并时运行本机构建。 对于PR预览,向__CAPGO_KEEP_0__频道发送web包,而不是构建二进制文件,正如在 main比较CI/CD平台的Capgo应用程序 Comparing CI/CD platforms for Capacitor apps.
使用矩阵,使两者在并行中构建,并设置
解决方案: 以便iOS签名问题不会取消一个好的Android构建。 fail-fast: false Comparing CI/CD platforms for __CAPGO_KEEP_0__ apps
strategy:
fail-fast: false
matrix:
platform: [ios, android]
陷阱: 缓存不开或缓存设置错误
症状: 每次构建都会从头下载 Gradle 依赖项和 CocoaPods, 或者是使用陈旧缓存的环境构建会将生产配置发送给客户端。
解决方案: 缓存 ~/.gradle/caches, ~/.gradle/wrapper,并 ios/App/Pods 根据 lockfiles 键值对缓存,根据环境分区缓存。使用 Capgo Build,可以将每个应用程序的构建缓存分区为 --cache-key prod 或 --cache-key staging跳过以进行干净构建。 --no-cache 陷阱: 多模块项目路径
单库项目路径陷阱
症状: could not find capacitor.config 或原生项目中缺少的插件。
解决方案: 在应用程序包中运行 Capacitor 命令,并将工具指向提升的 node_modules。 Capgo CLI 接受 --path 并且 --node-modules 用于此。
第五阶段:商店提交
陷阱:重复使用的构建号
症状: “iOS上必须更新的bundle版本号要高于之前上传的版本号”,或“Google Play上版本code已经被使用过了”。
解决方案: 生成CI中的数字。使用fastlane,读取最新的TestFlight构建并加一。使用 Capgo Build,这是默认行为:它从App Store Connect或最高的 versionCode 从 Google Play 和增加它。
陷阱:在 TestFlight 中卡住的构建
症状: 上传成功,但测试者永远无法看到构建。
原因: 缺少出口控制答案。
解决方案: 在中声明它一次 ios/App/App/Info.plist 如果您只使用标准加密:
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
陷阱:隐私清单拒绝
症状: 来自苹果的电子邮件关于缺少必需的原因API声明(ITMS-91053)。
修复: 添加一个 PrivacyInfo.xcprivacy 到应用目标并更新将自己的插件更新。请参阅 隐私清单指南为Capacitor应用.
__CAPGO_KEEP_0__ 应用
修复: 陷阱:错误的工件类型bundleReleaseGoogle Play 需要一个 AAB( bundleRelease ),而不是 APK。 release 仍然成功而没有签名配置并产生一个 Play 拒绝的未签名 AAB,因此配置 signingConfigs.release 在 android/app/build.gradle 首先。 iOS 需要 App Store 导出,而不是开发或广告 hoc IPA。检查您的构建步骤中的导出方法。
第 6 阶段: 实时更新
陷阱: 发布一个需要新本机构建的live update
症状: 在实时更新后,应用程序崩溃,调用一个在安装的二进制文件中不存在的插件方法。
原因: web 包依赖于一个版本的插件新于用户设备上的应用程序编译的版本。
解决方案: 让管道决定。 build needed 退出码 0 表示本机依赖项与实时通道上的匹配,1 表示需要新二进制文件:
if bunx @capgo/cli@latest build needed com.example.app --channel production; then
bunx @capgo/cli@latest bundle upload com.example.app --channel production
else
bunx cap sync
bunx @capgo/cli@latest build request com.example.app --platform ios
bunx @capgo/cli@latest build request com.example.app --platform android
fi
也强制本机路径,当文件位于 ios/, android/或 capacitor.config.* 改变。完整模式在 自动选择 live update 或原生构建, 并且兼容性规则在 原生兼容.
移除最多陷阱的修复
如果您只改变一个东西,请将 iOS 编译和签名从 CI 运行器中移出。 Keychain 设置、 Xcode 升级、 macOS 成本和配置文件安装都从管道中消失,当 Linux 任务将准备好的项目交给 Capgo 构建:
bun install --frozen-lockfile && bun run build
bunx cap sync ios
bunx @capgo/cli@latest build request com.example.app --platform ios --build-mode release
context 修复CapacitorCI/CD管道中的构建失败.
阶段 1、5 和 6 的陷阱仍然适用,因为它们与您的项目有关,而不是运行器。关于调试失败的工作更多信息,请参见
| Error | 快速参考 | 错误信息 |
|---|---|---|
| 新旧 UI 在新构建中 | cap sync 在 web 构建之前 |
阶段 1 |
No profiles for ... were found |
未安装或不匹配的配置文件 | 阶段 3 |
errSecInternalComponent |
密钥链已锁定 | 阶段 3 |
MAC verification failed |
密码错误或 OpenSSL 3 .p12 |
阶段 3 |
Unsupported class file major version |
JDK 错误 | 阶段 2 |
| SDK 上传时过旧 | Xcode版本低于26 | 阶段2 |
| 捆绑包版本必须高于 | 重复使用的构建号 | 阶段5 |
| 版本code已使用 | 重复使用 versionCode |
阶段5 |
| 在live update后发生崩溃 | 原生代码通过无线更新 | 阶段6 |