跳转至正文

如何在云端对 Capacitor App 进行签名与构建

在云端签名并构建您的 Capacitor App:创建 Android keystore 和 iOS 证书,安全存储凭据,并通过 CI 运行已签名的构建。

如何在云端对 Capacitor App 进行签名与构建

要在云端对 Capacitor App 进行签名和构建,您只需创建一次签名材料(Android keystore、iOS 分发证书及 provisioning profile),将其提供给云构建服务,然后通过终端或 CI 触发构建。该服务会编译原生项目、进行签名,并能直接将其上传至 TestFlight 或 Google Play。本指南将涵盖每种签名文件、如何在没有 Mac 的情况下创建它们、如何通过 Capgo Build 进行配置,以及如何安全地实现已签名构建的自动化。

什么是“云端签名”

应用商店仅接受已签名的二进制文件。签名可以证明该构建版本出自您本人,且之后未被他人篡改。在本地开发时,Xcode 和 Android Studio 会隐藏大部分签名细节。但在云端,没有任何操作是默认完成的,因此您需要明确了解涉及哪些文件:

平台 文件 定义 用途
Android .jks / .keystore 存放 upload key 的 Keystore 为 AAB 或 APK 进行签名
Android 服务账号 .json Google Cloud 凭据 上传至 Google Play
iOS .p12 Apple Distribution 证书及私钥 IPA 签名
iOS .mobileprovision 绑定 Bundle ID、证书与 Capabilities 的 Provisioning profile 允许 App 运行及分发
iOS .p8 + Key ID + Issuer ID App Store Connect API 密钥 上传至 TestFlight 并读取 Build Numbers

请勿将这些内容提交至 Git。以下所有内容都将存储在您的本地凭据文件或 CI 的 Secret Store 中。

Android 签名

创建上传用的 keystore

如果应用已在 Google Play 上架,请复用现有的 keystore。除非通过 Play Console 重置上传密钥,否则使用不同密钥签署的更新会被拒绝。

对于新应用:

keytool -genkeypair -v \
  -storetype PKCS12 \
  -keystore release.jks \
  -alias upload \
  -keyalg RSA -keysize 2048 \
  -validity 10000

注意事项:

  • Google Play 要求密钥有效期至少到 2033 年 10 月 22 日。 -validity 10000 (约 27 年) 即可满足要求。
  • 使用 PKCS12 存储类型时,密钥密码与 store 密码相同。
  • 手边没有 JDK? Android keystore 生成器 可以在浏览器中生成相同的文件。

Play App Signing 与上传密钥

Google Play 上的新应用使用 Play App Signing。Google 会持有 App 签名密钥 并对用户下载的内容进行重新签名。你的 keystore 是 上传密钥。如果你丢失了它,Play Console 支持可以注册新的上传密钥,所以丢失它只会导致延迟,而不是灾难。但无论如何,请务必备份。

用于上传的服务账号

若要从云端上传,请在 Google Cloud 中创建一个服务账号,启用 Google Play Android Developer API,下载其 JSON 密钥,然后在 Play Console 的 用户和权限 中邀请该服务账号,并授予其应用的发布权限。如下所示,Capgo 的 onboarding 可以通过 Google 登录完成此操作。

iOS 签名

Apple 的三个核心要素

  • Apple Distribution certificate。 每个团队只需一个,有效期为一年。Apple 对证书数量有限制,因此请勿为每个开发者都创建一个。
  • 描述文件 (Provisioning profile)。 将 Bundle ID、证书以及推送通知等功能权限进行关联。请使用 App Store Connect 描述文件用于 TestFlight 和 App Store,并使用 Ad Hoc 描述文件用于在已注册设备上安装。每个 App Extension(如 Widget、Share Extension、Notification Service)都需要独立的描述文件。
  • App Store Connect API 密钥。 在以下路径创建: Users and Access > Integrations 并授予 App Manager 权限。该 .p8 文件仅需下载一次。

您需要在 Apple Developer 团队中拥有 Admin 或 Account Holder 权限才能创建这些内容。

无需 Mac 即可创建证书

Keychain Access 流程需要 macOS,但 OpenSSL 在任何地方都能用:

# 1. Private key and certificate signing request
openssl req -new -newkey rsa:2048 -nodes \
  -keyout dist.key -out dist.csr \
  -subj "/emailAddress=dev@example.com/CN=Example Inc/C=US"

# 2. Upload dist.csr at developer.apple.com > Certificates > + > Apple Distribution
#    and download distribution.cer

# 3. Convert and bundle into a .p12
openssl x509 -inform DER -in distribution.cer -out distribution.pem
openssl pkcs12 -export -legacy \
  -inkey dist.key -in distribution.pem \
  -out distribution.p12 -passout pass:choose-a-password

该 -legacy OpenSSL 3 里这个 flag 很关键:不加的话,macOS 构建机可能导入失败, .p12 并提示 “MAC verification failed”。基于浏览器的 iOS 证书生成器 如果你不想用终端,它也能完成同样的步骤。

然后在开发者门户中创建 provisioning profile (配置文件 > + > App Store Connect),选择你的 App ID 和新证书,然后下载即可。

使用 Capgo Build 配置签名

Capgo 构建 在 Capgo 管理的机器上编译并签名 Capacitor 应用,让你可以在 Windows 或 Linux 上构建 iOS 版本。首先登录并注册应用:

bunx @capgo/cli@latest login
bunx @capgo/cli@latest app add
bunx @capgo/cli@latest build init --platform ios
bunx @capgo/cli@latest build init --platform android

在 iOS 上,onboarding 会使用你的 App Store Connect API key 来创建或复用发布证书(distribution certificate)和 App Store provisioning profile。在 macOS 上,它还可以引导你创建该 API key。在 Android 上,它会创建或导入 keystore,并可以通过 Google sign-in 配置 Google Cloud 服务账号和 Play Console 邀请。最后,它会提示你开始第一次 build。

方案 B:保存现有文件

如果你已经拥有前几节中的文件:

# iOS
bunx @capgo/cli@latest build credentials save \
  --platform ios \
  --certificate ./distribution.p12 \
  --p12-password "choose-a-password" \
  --ios-provisioning-profile ./AppStore.mobileprovision \
  --apple-key ./AuthKey_ABC1234567.p8 \
  --apple-key-id ABC1234567 \
  --apple-issuer-id 00000000-0000-0000-0000-000000000000 \
  --apple-team-id TEAM123456

# Android
bunx @capgo/cli@latest build credentials save \
  --platform android \
  --keystore ./release.jks \
  --keystore-alias upload \
  --keystore-key-password "store-password" \
  --keystore-store-password "store-password" \
  --play-config ./play-service-account.json

对于带有 extensions 的应用,请重复 --ios-provisioning-profile 配合 bundleId=path 为每个 target 进行映射:

  --ios-provisioning-profile com.example.app=./App.mobileprovision \
  --ios-provisioning-profile com.example.app.widget=./Widget.mobileprovision

凭据存储在 ~/.capgo-credentials/credentials.json中,通过 app ID 和 platform 进行键值管理。添加 --local 以将其存储在项目中的 .capgo-credentials.json 中,并将该文件添加到 .gitignore. Check what is saved with bunx @capgo/cli@latest build credentials list.

触发签名构建

准备原生项目,然后请求构建:

bun run build
bunx cap sync

# iOS: sign with the App Store profile and upload to TestFlight
bunx @capgo/cli@latest build request com.example.app --platform ios --build-mode release

# Android: sign the AAB and upload to the internal track
bunx @capgo/cli@latest build request com.example.app --platform android --build-mode release --android-track internal

Logs stream into your terminal. A pre-build scan checks certificate expiry, passwords, and profile pairing before anything is uploaded, so most signing mistakes fail in seconds instead of minutes. Run it on its own with bunx @capgo/cli@latest build prescan --platform ios.

常用变体:

目标 Flags
在已注册的 iPhone 上进行测试构建 --ios-distribution ad_hoc --ios-provisioning-profile ./adhoc.mobileprovision --output-upload
用于 MDM 或 kiosk 设备的 APK --platform android --no-playstore-upload --output-upload
直接提交至 App Review --submit-to-store-review --store-release-name 2.4.0
保留自定义构建版本号 --skip-build-number-bump
不使用缓存的全新构建 --no-cache

对于 ad hoc 构建,请先使用 iOS UDID 查询工具 收集设备 UDID 并将其添加到 profile 中。

在 CI 中实现签名构建自动化

在 CI 中,请将凭据作为环境变量传递,而不是使用凭据文件。CLI 导出了你所需的一切:

bunx @capgo/cli@latest build credentials manage --appId com.example.app
# choose "Export to .env"

在 GitHub 上,通过一条命令将每一行内容推送到 repository secrets,然后删除该文件:

gh secret set -f .env.capgo.com.example.app
gh secret set CAPGO_TOKEN --body "your-capgo-api-key"
rm .env.capgo.com.example.app

一个在推送 tag 时为双平台进行签名并发布的 release workflow:

name: Signed release
on:
  push:
    tags: ['v*']

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        platform: [ios, android]
    steps:
      - uses: actions/checkout@v6
      - uses: oven-sh/setup-bun@v2
      - run: bun install --frozen-lockfile
      - run: bun run build
      - run: bunx cap sync ${{ matrix.platform }}
      - run: bunx @capgo/cli@latest build request com.example.app --platform ${{ matrix.platform }} --build-mode release
        env:
          CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }}
          BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
          P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
          CAPGO_IOS_PROVISIONING_MAP_BASE64: ${{ secrets.CAPGO_IOS_PROVISIONING_MAP_BASE64 }}
          APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }}
          APPLE_ISSUER_ID: ${{ secrets.APPLE_ISSUER_ID }}
          APPLE_KEY_CONTENT: ${{ secrets.APPLE_KEY_CONTENT }}
          APP_STORE_CONNECT_TEAM_ID: ${{ secrets.APP_STORE_CONNECT_TEAM_ID }}
          ANDROID_KEYSTORE_FILE: ${{ secrets.ANDROID_KEYSTORE_FILE }}
          KEYSTORE_KEY_ALIAS: ${{ secrets.KEYSTORE_KEY_ALIAS }}
          KEYSTORE_KEY_PASSWORD: ${{ secrets.KEYSTORE_KEY_PASSWORD }}
          KEYSTORE_STORE_PASSWORD: ${{ secrets.KEYSTORE_STORE_PASSWORD }}
          PLAY_CONFIG_JSON: ${{ secrets.PLAY_CONFIG_JSON }}

该任务在 Linux 上运行。无需 macOS runner,无需 keychain 命令,也无需 fastlane。相同的环境变量适用于任何 CI:GitLab CI/CD variables、Bitbucket secured variables、Gitea secrets 或 Azure DevOps variable groups。各平台的详细指南: Bitbucket Pipelines, Gitea Actions以及 GitHub Actions 文档.

密钥处理机制

在将签名密钥交给任何云服务之前,这都是一个非常合理的问题。使用 Capgo Build:

  • 凭据存储在您的本地机器(~/.capgo-credentials/)或 CI 密钥库中。Capgo 不会保存您的密钥库。
  • 在每次构建时,CLI 会通过 HTTPS 发送它们。这些密钥仅在当前构建期间使用,并在构建完成后立即删除。
  • 我们仅上传准备好的 native 项目。您的 Web 源码 .git,以及 .env 及文件不会被上传。
  • 构建好的 App 会直接发送至 App Store Connect 或 Google Play,或者根据您的需求生成一个有时效性的下载链接。

权衡之处:更换凭据意味着您需要手动更新 CI secrets。重新导出并 build credentials manage 再次推送文件即可。

过期与轮换

项目 有效期 应对方案
Apple Distribution 证书 1 年 创建新的证书,重新生成 profiles,重新保存并更新 CI
描述文件 (Provisioning profile) 1 年,或直到证书被吊销 重新生成并保存
App Store Connect API 密钥 直到被吊销 当拥有访问权限的人员离职时吊销
Android 上传 keystore 有效期尽量长(设为数十年) 请务必备份;若丢失,可通过 Play Console 重置
Play 服务账号密钥 直至删除为止 每年轮换,或权限变更时轮换

把 Apple 相关日期记到共享日历里。证书过期不会影响用户设备上已有的 App,但会阻止所有新 build。

故障排除

错误 原因与修复
Provisioning profile doesn't include signing certificate 该 Profile 是用另一个证书生成的,请用当前证书重新生成。
Provisioning profile doesn't match bundle ID 该 Profile 是为另一个 App ID 创建的,或缺少 extension target。请添加一个 bundleId=path 每个目标的映射。
MAC verification failed 错误 .p12 密码,或 OpenSSL 3 导出时缺少 -legacy.
Keystore was tampered with, or password was incorrect Store 密码错误,或文件因 base64 换行符损坏。
Key alias not found Alias 与 keystore 中的不符。请使用以下命令列出: keytool -list -keystore release.jks.
App Store Connect 身份验证失败 Key ID 或 Issuer ID 错误、密钥已撤销,或签名机器的系统时间偏差。
Play 上传失败:调用者权限不足 Service account 未在 Play Console 中受邀,或 Android Developer API 未启用。

更多修复方案请参阅 Capgo Build 故障排除指南 和 Capacitor 的 CI/CD:常见坑点.

完成首次签名构建后

只有在原生 code 发生变化时才需要签名 Native Build。对于 JavaScript、CSS 和 HTML 的更改,请直接推送 live update 到已安装的应用中,并将 Store 构建保留给涉及插件或原生配置的发布。如果你之前使用的是 Mac 环境, 使用 Capgo Build 在 Windows 上构建 iOS 应用 展示了无需 macOS 的完整工作流。

为 Capacitor 应用提供实时更新

当 Web 层 Bug 已上线时,通过 Capgo 推送修复,不必等 App Store 审核数天。用户会在后台获取更新,而原生变更仍走常规审核流程。

博客最新文章

Capgo 为你提供打造真正专业移动应用所需的深度洞察。