为Capacitor应用设置CI/CD可能会很复杂和耗时。以下是您需要知道的内容:
推荐新建:使用Capgo Build
我们现在建议使用 Capgo Build与CapgoCLI For native Capacitor builds. 此 Fastlane 指南保留用于维护现有的 GitHub Actions pipeline 的团队,但新 iOS 构建应使用 Capgo CLI 以免自己维护 Fastlane、Xcode 运行器、证书和上传脚本。
Capgo Build for CI/CD by Capgo
跳过 Fastlane、Xcode 运行器、证书、分发配置文件和上传脚本的维护。 Capgo Build 从现有的 CI/CD pipeline 运行签名的本机 iOS 构建:
- 与您的管道兼容: 在您的 web 构建之后从 GitHub Actions、GitLab CI、Jenkins 或本地脚本中触发 Capgo Build。
npx cap sync. - 从 CI 秘密中签名: 在 App Store Connect 密钥、证书、分发配置文件、密码和团队 ID 中保留您的 CI 秘密。
- 无本机运行器维护: Capgo Build 提供维护的 Apple 构建环境,因此您不需要管理 macOS 运行器、Xcode 图像或 Fastlane 通道。
- 工件和提交: 下载已签名的工件进行QA或通过Capgo CLI提交发布版本
定价
- Capgo计划从每月12美元开始
- 包括OTA更新和约15个本机构建/月
- 额外的构建分钟通过信用额度按分钟计费
手动设置指南
这里是您需要做的事情:
使用Fastlane和GitHub Actions和证书的iOS持续交付
先决条件
继续教程之前:
- 确保你在开发机器上安装了Fastlane。 确保你是iOS开发者计划成员。 关于价格的重要信息。
- 价格__CAPGO_KEEP_0__ Action
https://__CAPGO_KEEP_0__.com/features/actions

https://github.com/features/actions
我们将使用一个macOS 已安装
iOS开发者计划成员 关于价格的重要信息 机器人截图中显示的价格和限制(截图创建时的价格,可能会在未来发生变化)
已知需求和价格后,我们继续。
注意:在本文中,我假设您已经在 App Store Connect 中创建了应用。重要信息将由 Fastlane 复制!
本教程中您将学习什么
本教程中您需要遵循的步骤
- 使用 App Store Connect API 和 Fastlane
- 要求:
- 创建 App Store Connect API 密钥
- 使用 App Store Connect API 密钥
- 要求:
- 复制 Fastlane 文件
- 配置 GitHub 动作
1. 使用 App Store Connect API 和 Fastlane
自2021年2月起,所有用户登录App Store Connect都需要使用两步验证或两因素身份验证。这一额外的安全层对于您的Apple ID有助于确保您是唯一能够访问帐户的人。
来自 Apple Support
要求
为了让Fastlane能够使用App Store Connect API上传您的应用程序,您需要提供以下内容 三个 事项:
- 颁发者ID
- 密钥ID
- 密钥文件或密钥内容
获取App Store Connect API密钥
要生成密钥,您必须在App Store Connect中具有管理员权限。如果您没有该权限,可以将相关人员指向此文章。
-
选择 用户和访问.

3 — 选择“集成”选项卡。

- 点击生成 API 密钥或添加 (+) 按钮。

- 为密钥输入一个名称。该名称仅供您参考,不是密钥的一部分。

6 — 在“访问”下,选择密钥的角色。密钥的角色与您的团队中用户的角色相同。请参见 角色权限我们建议您选择 应用程序管理器.
- 点击生成。
一个API密钥的访问权限不能被限制到特定的应用程序。
新密钥的名称、密钥ID、下载链接和其他信息在页面上出现。

您可以在这里获取所有三个必要的信息。
<1>问题ID。 (APPLE_ISSUER_ID 密钥)
<2>密钥ID。 (APPLE_KEY_ID 密钥)
点击“下载 API 密钥”来下载您的 API 私钥。下载链接仅在私钥尚未下载时才会出现。苹果公司不会保留私钥的副本。因此,您只能下载一次。
🔴 请将您的私钥存储在安全的地方。您不应共享您的密钥、将密钥存储在 code 仓库中或将密钥包含在客户端 code 中。
使用 App Store Connect API 密钥
要创建用于授权的 JWT 令牌,需要 API 密钥文件(下载的 p8 文件)、密钥 ID 和发行者 ID。有多种方法可以将此信息传递给 Fastlane。为了方便起见,我选择使用 Fastlane 的新动作 app_store_connect_api_key您可以学习其他方法 查看 Fastlane 文档我展示这种方法,因为我认为它是与大多数 CI 工具一起工作最方便的方法。您可以在 CI 中设置环境变量。
请将下载的 p8 文件转换为 Base64 并将其存储为一个秘密(APPLE_KEY_CONTENT).
base64 -i APPLE_KEY_CONTENT.p8 | pbcopy
现在我们可以使用 API 密钥来管理 App Store Connect,太棒了!
2. 证书
打开 XCode 并前往 设置 > 账户 > Apple ID > 团队 选择您的团队。

点击 管理证书.
如果您尚未创建证书,请创建新证书。
点击 + 选择并 Apple Distribution

然后您需要前往钥匙串下载证书作为 .p12 文件。
要实现这一点,请前往钥匙串切换到 登录 钥匙串,然后切换到 我的证书.

然后您可以选择要下载的证书。(查看证书的日期)
然后右键单击证书上的私钥并 导出.
选择文件格式 个人信息交换 (.p12).
将下载证书作为 .p12 文件。
请在终端中打开文件并使用以下命令将其转换为 Base64:
base64 -i BUILD_CERTIFICATE.p12 | pbcopy
将成为您的 BUILD_CERTIFICATE_BASE64 密钥。另外,当被询问时,请提供证书的密码。这将成为您的 P12_PASSWORD 密钥。
3. 配置文件
打开 Apple Developer 选择正确的团队。
然后创建一个新配置文件,点击 +

选择 App Store Connect.

然后需要选择正确的应用程序,注意不要使用通配符,否则签名会失败。

选择您之前创建的正确证书(注意查看有效期,应该与今天相同的日期和月份),然后点击 继续.

最后输入配置文件的名称并点击 生成.
将在 Fastlane 中使用该名称来识别配置文件
APPLE_PROFILE_NAME.

您可以将配置文件下载为 .mobileprovision 文件。

请将配置文件转换为 Base64 并将其存储为一个秘密(BUILD_PROVISION_PROFILE_BASE64).
base64 -i BUILD_PROVISION_PROFILE.mobileprovision | pbcopy
4. 复制 Fastlane 文件
Fastlane 是一个用于自动化移动开发任务的 Ruby 库。使用 Fastlane,您可以配置自定义的“道线”(lanes),这些道线包含一系列的“动作”(actions),这些动作执行您通常使用 Android Studio 执行的任务。您可以在 Fastlane 中做很多事情,但在本教程中,我们将仅使用一小部分核心动作。
在您的 Capacitor/Ionic 项目的根目录中创建 Fastlane 文件夹,并在其中添加 Fastfile:
- 文件夹:
<project-root>/fastlane/ - 文件:
<project-root>/fastlane/Fastfile
与此级别相同的 package.json, capacitor.config.*, 并且 ios/ 文件夹。不要在 ios/App/.
platform :ios do
desc 'Export ipa and submit to TestFlight'
lane :beta do
keychain_info = { keychain_name: "ios-build-#{Time.now.to_i}.keychain", keychain_password: SecureRandom.uuid }
begin
setup_signing(keychain_info)
bump_build_number
build_app_with_signing(keychain_info)
submit_to_testflight
ensure
cleanup_keychain(keychain_info)
end
end
private_lane :setup_signing do |options|
create_keychain(
name: options[:keychain_name],
password: options[:keychain_password],
unlock: true,
timeout: 0,
lock_when_sleeps: false,
add_to_search_list: true
)
import_cert(options)
install_profile
update_project_settings
end
lane :bump_build_number do
file = File.read('../package.json')
data_hash = JSON.parse(file)
api_key = app_store_connect_api_key(
key_id: ENV['APPLE_KEY_ID'],
issuer_id: ENV['APPLE_ISSUER_ID'],
key_content: ENV['APPLE_KEY_CONTENT'],
is_key_content_base64: true,
duration: 1200,
in_house: false
)
build_num = app_store_build_number(
api_key: api_key,
app_identifier: ENV['BUNDLE_IDENTIFIER'],
live: false
)
build_num = build_num + 1
UI.message("Bumped build number to #{build_num}")
increment_build_number(
build_number: build_num,
xcodeproj: "./ios/App/App.xcodeproj",
skip_info_plist: true
)
end
private_lane :import_cert do |options|
cert_path = "#{Dir.tmpdir}/build_certificate.p12"
File.write(cert_path, Base64.decode64(ENV['BUILD_CERTIFICATE_BASE64']))
import_certificate(
certificate_path: cert_path,
certificate_password: ENV['P12_PASSWORD'] || "",
keychain_name: options[:keychain_name],
keychain_password: options[:keychain_password],
log_output: true
)
File.delete(cert_path)
end
private_lane :cleanup_keychain do |options|
delete_keychain(
name: options[:keychain_name]
)
end
private_lane :install_profile do
profile_path = "#{Dir.tmpdir}/build_pp.mobileprovision"
File.write(profile_path, Base64.decode64(ENV['BUILD_PROVISION_PROFILE_BASE64']))
UI.user_error!("Failed to create provisioning profile at #{profile_path}") unless File.exist?(profile_path)
ENV['PROVISIONING_PROFILE_PATH'] = profile_path
install_provisioning_profile(path: profile_path)
File.delete(profile_path)
end
private_lane :update_project_settings do
update_code_signing_settings(
use_automatic_signing: false,
path: "./ios/App/App.xcodeproj",
code_sign_identity: "iPhone Distribution",
profile_name: ENV['APPLE_PROFILE_NAME'],
bundle_identifier: ENV['BUNDLE_IDENTIFIER'],
team_id: ENV['APP_STORE_CONNECT_TEAM_ID']
)
update_project_team(
path: "./ios/App/App.xcodeproj",
teamid: ENV['APP_STORE_CONNECT_TEAM_ID']
)
end
private_lane :build_app_with_signing do |options|
unlock_keychain(
path: options[:keychain_name],
password: options[:keychain_password],
set_default: false
)
build_app(
workspace: "./ios/App/App.xcworkspace",
scheme: "App",
configuration: "Release",
export_method: "app-store",
output_name: "App.ipa",
export_options: {
provisioningProfiles: {
ENV['BUNDLE_IDENTIFIER'] => ENV['APPLE_PROFILE_NAME']
}
},
xcargs: "-verbose",
buildlog_path: "./build_logs",
export_xcargs: "-allowProvisioningUpdates",
)
end
private_lane :submit_to_testflight do
api_key = app_store_connect_api_key(
key_id: ENV['APPLE_KEY_ID'],
issuer_id: ENV['APPLE_ISSUER_ID'],
key_content: ENV['APPLE_KEY_CONTENT'],
is_key_content_base64: true,
duration: 1200,
in_house: false
)
pilot(
api_key: api_key,
skip_waiting_for_build_processing: true,
skip_submission: true,
distribute_external: false,
notify_external_testers: false,
ipa: "./App.ipa"
)
end
end
5. 配置机密
GitHub Actions 使用您在下一步中配置的仓库机密。您只需要一个本地 .env 文件,如果您想在自己的机器上运行或测试 Fastlane。
对于本地测试,请在 <project-root>/fastlane/.env 旁边创建 Fastfile。不要将此文件提交。将 fastlane/.env 添加到您的 .gitignore 第一个(或验证它已经被忽略)。以下是示例:
APP_STORE_CONNECT_TEAM_ID=UVTJ336J2D
BUNDLE_IDENTIFIER=ee.forgr.testfastlane
# See previous section for these secrets
BUILD_CERTIFICATE_BASE64=
BUILD_PROVISION_PROFILE_BASE64=
APPLE_KEY_ID=
APPLE_ISSUER_ID=
APPLE_KEY_CONTENT=
P12_PASSWORD=
APPLE_PROFILE_NAME=
获取 APP_STORE_CONNECT_TEAM_ID
前往 开发者中心 并向下滚动到 Membership details 部分。 Team ID 是您需要在 APP_STORE_CONNECT_TEAM_ID 密钥.
获取 BUNDLE_IDENTIFIER
- 打开 Xcode
- 双击
App在项目导航器中 - 然后单击
Signing and Capabilities - 复制此值。
Bundle identifier此值需要在BUNDLE_IDENTIFIER中设置。
6.处理
In GitHub Actions, 中,您的CI/CD工作流程的运行分钟数将计费。从我的经验来看,需要约10-15分钟才能在App Store Connect中处理一个构建。 私有项目的估计每次构建成本最高可达
$0.08/分钟 x 15分钟 = $1.2 ,或更多,取决于您的项目的配置和依赖项。如果您对私有项目的成本有所担忧,可以设置
__CAPGO_KEEP_0__ skip_waiting_for_build_processing 到 true. 这将节省构建分钟,不必等待 App Store Connect 完成处理构建。
然而,这个优化有一个权衡 - 您需要手动更新应用的合规信息在 App Store Connect 之后才能将构建分发给用户。
这个优化主要适用于私有项目,构建分钟花费钱。对于公众/免费项目,构建分钟是免费的,所以没有必要启用这个设置。请参见 GitHub 的 定价页面 7. 配置 __CAPGO_KEEP_0__ Actions
配置 GitHub 秘密
请从文件中复制秘密并将其粘贴到 GitHub 仓库秘密中。
前往 .env file and paste them into the GitHub repository secrets.
__CAPGO_KEEP_0__ __CAPGO_KEEP_0__ > 密钥和变量 > 操作 > 新仓库密钥
2. BUILD_CERTIFICATE_BASE64 - 基于 Base64 的证书。
3. BUILD_PROVISION_PROFILE_BASE64 - 基于 Base64 的配置文件。
4. BUNDLE_IDENTIFIER - 应用程序的包标识符。
5. APPLE_KEY_ID — App Store Connect API Key 🔺Key ID。
6. APPLE_ISSUER_ID — App Store Connect API Key 🔺Issuer ID。
7. APPLE_KEY_CONTENT — App Store Connect API Key 🔺 Key content of .p8, 检查它
8. 配置 GitHub 工作流文件
创建一个 GitHub 工作流目录。
cd .github/workflows
在这个目录内 workflow 创建一个名为 build-upload-ios.yml并添加以下内容。
name: Build source code on ios
on:
push:
tags:
- '*'
jobs:
build_ios:
runs-on: macOS-latest
steps:
- uses: actions/checkout@v6
- name: Set Node.js
uses: actions/setup-node@v6
with:
node-version: 24
cache: npm
- name: Install dependencies
id: install_code
run: npm ci
- name: Build
id: build_code
run: npm run build
- uses: actions/cache@v5
with:
path: ios/App/Pods
key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }}
restore-keys: |
${{ runner.os }}-pods-
- name: Sync
id: sync_code
run: npx cap sync
- uses: ruby/setup-ruby@v1
with:
ruby-version: '3.0'
bundler-cache: true
- uses: maierj/fastlane-action@v3.1.0
env:
APP_STORE_CONNECT_TEAM_ID: ${{ secrets.APP_STORE_CONNECT_TEAM_ID }}
BUNDLE_IDENTIFIER: ${{ secrets.BUNDLE_IDENTIFIER }}
BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.BUILD_PROVISION_PROFILE_BASE64 }}
APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }}
APPLE_ISSUER_ID: ${{ secrets.APPLE_ISSUER_ID }}
APPLE_KEY_CONTENT: ${{ secrets.APPLE_KEY_CONTENT }}
P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
APPLE_PROFILE_NAME: ${{ secrets.APPLE_PROFILE_NAME }}
with:
lane: ios beta
- name: Upload release bundle
uses: actions/upload-artifact@v6
with:
name: ios-release
path: ./App.ipa
retention-days: 10
这个工作流应该在每次 GitHub 标签发布后触发如果您需要自动化标签,请参阅 使用 GitHub 动作自动化构建和发布 首先。
然后,这个工作流程将拉取您的 NodeJS 依赖项,安装它们并构建您的 JavaScript 应用程序。
每次您发送新的提交时,测试飞行中的一个发布将被构建。
您的 App 不需要使用 Ionic,只需 Capacitor 基础即可,它可以有旧的 Cordova 模块,但 Capacitor JS 插件应优先使用。
8. 触发工作流程
创建一个提交
制作一个 提交您应该在仓库中看到正在运行的工作流程。
触发工作流程
将新提交推送到分支 main 或 development 触发工作流程。

几分钟后,您的 App Store Connect 控制台中应该可以看到构建。

9. 我可以从本地机器部署吗?
是的,您可以,而且非常方便。
您可以使用 Xcode 构建和签名您的应用程序,正如往常一样。
相关文章
CI/CD 设置指南
- 自动 Capacitor Android 构建与 GitHub Actions - 完成 Android CI/CD 设置
- 自动构建和发布与 GitHub Actions - 全面 CI/CD pipeline 教程
- 使用 GitHub Actions 管理开发和生产环境 - 环境管理
- 使用 Capacitor 自动化 iOS 构建 - 使用 Fastlane Match 的替代方案
替代 CI/CD 平台
- 使用 GitLab CI 构建 - GitLab 替代方案
- 使用 CodeMagic 构建 - CodeMagic 配置指南
实时更新和部署
- Capgo 实时更新文档 - 为应用添加 OTA 更新
- CI/CD 与 Capgo 集成 - 将实时更新集成到管道中
感谢
本博客基于以下文章:
从自动 Capacitor IOS 构建中继续使用 GitHub 动作和证书
如果您正在使用 自动 Capacitor IOS 构建使用 GitHub 动作和证书 为CI/CD自动化编排,连接它 Capgo CI/CD 在Capgo CI/CD中, Capgo 原生构建 在Capgo 原生构建中, Capgo 集成 在Capgo 集成中, CI/CD集成 在CI/CD集成的实现细节中, GitHub 动作集成 在GitHub 动作集成的实现细节中。