使用GitHub Actions和Match进行自动iOS构建
为Capacitor 应用设置CI/CD可能会很复杂和耗时。以下是您需要了解的内容:
推荐用于新构建:使用Capgo Build
我们现在建议使用 Capgo 使用 Capgo CLI 为原生 Capacitor 构建。 本指南是为维护现有 GitHub Actions pipeline的团队而保留的,但新iOS构建应使用 Capgo CLI,以免您需要维护Fastlane、Match仓库、Xcode runner、证书和上传脚本。
Capgo Build for CI/CD by Capgo
通过 __CAPGO_KEEP_1__ 构建CI/CD Capgo Build __CAPGO_KEEP_0__ 构建
- 从您的CI/CD pipeline运行已签名的原生iOS构建:: Trigger Capgo Build from GitHub Actions, GitLab CI, Jenkins, or local scripts after your web build and
npx cap sync. - : 从 __CAPGO_KEEP_1__ Actions、GitLab CI、Jenkins 或本地脚本中触发 __CAPGO_KEEP_0__ 构建,从CI密钥签名
- : 在您的CI密钥中保留App Store Connect密钥、证书、配置文件、密码和团队ID。Capgo Build 提供维护的 Apple 构建环境,因此您不需要管理 macOS 运行器、Xcode 图像、Fastlane 或 Match 仓库。
- 工件和提交: 下载已签名的工件进行 QA 或通过 Capgo CLI 提交发布版本。
定价
- : Capgo 计划从每月 $12 起
- : 包括 OTA 更新和约 15 个本地构建每月
- : 额外的构建分钟通过信用额度按分钟计费
: 手动设置指南
: 您需要做的就是
: 使用 Fastlane 和 GitHub Actions 实现 iOS 的持续交付使用 match
: 前提条件
继续教程之前…
- 确保你在开发机器上安装了Fastlane 安装 在你的开发机器上
- iOS开发者计划会员资格
- 想读的…
- 一个团队的许多开发者,否则我们建议使用 fastlane cert 更简单的工作流
关于价格的重要事项

https://github.com/features/actions
该服务在限制内是免费的,具体取决于所选的机器。
我们将使用一个 macOS 机器,截图中显示了其价格和限制(截至教程创建时的价格,可能会在未来发生变化)
🔴 一旦警告了要求和价格,如果您喜欢,我们继续…
📣 在文章中,我们假设我们已经在 iTunes Connect 中创建了应用,我们有 Apple 生态系统的证书,Fastlane 将复制所有内容!
让我们开始探索!
本文中的步骤
- 使用 App Store Connect API 和 Fastlane Match
- 要求
- 创建 App Store Connect API 密钥
- 使用 App Store Connect API 密钥
- 复制Fastlane文件
- 配置Fastlane match
1. 使用App Store Connect API与Fastlane Match
从2021年2月开始,所有用户必须使用两步验证或两因素认证登录App Store Connect。这一额外的安全层为您的Apple ID提供了额外的安全保障,确保您是唯一能够访问您的帐户的人。
来自 Apple支持
使用match进行初始设置需要您撤销现有的证书。但是,您将直接获得新的证书。
要求
要能够使用App Store Connect API,Fastlane需要 三个 证书颁发者ID
- __CAPGO_KEEP_0__
- __CAPGO_KEEP_0__ ID.
- __CAPGO_KEEP_0__ 文件或内容.
创建 App Store Connect API Key
要生成密钥,您必须在 App Store Connect 中具有管理员权限。如果您没有该权限,请将相关人员指向此文章并遵循以下说明。
1 — 登录到 App Store Connect.
2 — 选择 用户和访问.

3 — 选择

App Store Connect API 集成选项卡。

5 — 为此密钥输入一个名称。这个名称仅供您参考,不是密钥的一部分。

6 — 在访问权限下,选择此密钥的角色。密钥的角色与您的团队成员的角色相同。请参阅 角色权限. 我们建议选择 App manager.
7 — 点击生成。
一个 API 密钥的访问权限不能限制到特定的应用。
新密钥的名称、密钥 ID、下载链接和其他信息将出现在页面上。

您可以在这里获取所有三个必要的信息。
1. 问题 ID.
2. 密钥 ID.
点击“下载 API 密钥”即可下载您的 API 私钥。下载链接仅在私钥尚未下载时才会出现。苹果公司不会保留私钥的副本。因此,您只能下载一次。
🔴 请将您的私钥存储在安全的地方。您不应共享您的密钥、将密钥存储在 code 仓库中或将密钥包含在客户端 code 中。
使用 App Store Connect API 密钥
需要创建 JWT 认证令牌的 API 密钥文件(下载的 p8 文件)、密钥 ID 和颁发者 ID。这些信息可以通过多种方式输入到 Fastlane 中,使用 Fastlane 的新动作 app_store_connect_api_key. 您可以在 Fastlane 文档中学习其他方法。
Now we can manage Fastlane with the App Store Connect API key, great!
现在我们可以使用 App Store Connect __CAPGO_KEEP_0__ 密钥来管理 Fastlane,太棒了!
2. 复制 Fastlane 文件夹内容
创建一个Fastlane文件夹在项目根目录,并复制以下文件: Fastfile
default_platform(:ios)
DEVELOPER_APP_IDENTIFIER = ENV["DEVELOPER_APP_IDENTIFIER"]
DEVELOPER_APP_ID = ENV["DEVELOPER_APP_ID"]
PROVISIONING_PROFILE_SPECIFIER = ENV["PROVISIONING_PROFILE_SPECIFIER"]
TEMP_KEYCHAIN_USER = ENV["TEMP_KEYCHAIN_USER"]
TEMP_KEYCHAIN_PASSWORD = ENV["TEMP_KEYCHAIN_PASSWORD"]
APPLE_ISSUER_ID = ENV["APPLE_ISSUER_ID"]
APPLE_KEY_ID = ENV["APPLE_KEY_ID"]
APPLE_KEY_CONTENT = ENV["APPLE_KEY_CONTENT"]
GIT_USERNAME = ENV["GIT_USERNAME"]
GIT_TOKEN = ENV["GIT_TOKEN"]
def delete_temp_keychain(name)
delete_keychain(
name: name
) if File.exist? File.expand_path("~/Library/Keychains/#{name}-db")
end
def create_temp_keychain(name, password)
create_keychain(
name: name,
password: password,
unlock: false,
timeout: 0
)
end
def ensure_temp_keychain(name, password)
delete_temp_keychain(name)
create_temp_keychain(name, password)
end
platform :ios do
lane :build do
build_app(
configuration: "Release",
workspace: "./ios/App/App.xcworkspace",
scheme: "App",
export_method: "app-store",
export_options: {
provisioningProfiles: {
DEVELOPER_APP_ID => "#{PROVISIONING_PROFILE_SPECIFIER}"
}
}
)
end
lane :refresh_profiles do
match(
type: "development",
force: true)
match(
type: "adhoc",
force: true)
end
desc "Register new device"
lane :register_new_device do |options|
device_name = prompt(text: "Enter the device name: ")
device_udid = prompt(text: "Enter the device UDID: ")
device_hash = {}
device_hash[device_name] = device_udid
register_devices(
devices: device_hash
)
refresh_profiles
end
lane :closed_beta do
keychain_name = TEMP_KEYCHAIN_USER
keychain_password = TEMP_KEYCHAIN_PASSWORD
ensure_temp_keychain(keychain_name, keychain_password)
api_key = app_store_connect_api_key(
key_id: APPLE_KEY_ID,
issuer_id: APPLE_ISSUER_ID,
key_content: APPLE_KEY_CONTENT,
duration: 1200,
in_house: false
)
match(
type: 'appstore',
git_basic_authorization: Base64.strict_encode64("#{GIT_USERNAME}:#{GIT_TOKEN}"),
readonly: true,
keychain_name: keychain_name,
keychain_password: keychain_password,
api_key: api_key
)
gym(
configuration: "Release",
workspace: "./ios/App/App.xcworkspace",
scheme: "App",
export_method: "app-store",
export_options: {
provisioningProfiles: {
DEVELOPER_APP_ID => "#{PROVISIONING_PROFILE_SPECIFIER}"
}
}
)
pilot(
apple_id: "#{DEVELOPER_APP_ID}",
app_identifier: "#{DEVELOPER_APP_IDENTIFIER}",
skip_waiting_for_build_processing: true,
skip_submission: true,
distribute_external: false,
notify_external_testers: false,
ipa: "./App.ipa"
)
delete_temp_keychain(keychain_name)
end
lane :submit_review do
version = ''
Dir.chdir("..") do
file = File.read("package.json")
data = JSON.parse(file)
version = data["version"]
end
deliver(
app_version: version,
submit_for_review: true,
automatic_release: true,
force: true, # Skip HTMl report verification
skip_metadata: false,
skip_screenshots: false,
skip_binary_upload: true
)
end
end
Appfile
app_identifier(ENV["DEVELOPER_APP_IDENTIFIER"])
apple_id(ENV["FASTLANE_APPLE_ID"])
itc_team_id(ENV["APP_STORE_CONNECT_TEAM_ID"])
team_id(ENV["DEVELOPER_PORTAL_TEAM_ID"])
配置Fastlane match
Fastlane match 是iOS的code签名的新方法。Fastlane match使团队更容易管理iOS应用所需的证书和配置文件。
创建一个名为 certificates的私有仓库,例如在你的GitHub个人账户或组织中。
初始化Fastlane match为您的iOS应用。
fastlane match init
然后选择选项#1(Git存储)。
[01:00:00]: fastlane match supports multiple storage modes, please select the one you want to use:1. git2. google_cloud3. s3?
将新创建仓库的URL assignments
[01:00:00]: Please create a new, private git repository to store the certificates and profiles there[01:00:00]: URL of the Git Repo: <YOUR_CERTIFICATES_REPO_URL>
现在您在Fastlane文件夹中有一个名为 匹配文件 和
_git_url_应该设置为证书仓库的HTTPS URL。您也可以使用SSH,但这需要一个不同的步骤来运行。
# ios/Matchfilegit_url("https://github.com/gitusername/certificates")storage_mode("git")type("appstore")
接下来,我们将生成证书并在Fastlane Match中输入您的凭据。
您将被要求输入一个密语。请正确记住它,因为它将在GitHub Actions中用来解密您的证书仓库。
fastlane match appstore
如果一切顺利,您应该看到如下内容:
[01:40:52]: All required keys, certificates and provisioning profiles are installed 🙌
如果您在GitHub和必要权限方面遇到任何问题,这个 帖子 将帮助您生成Git的认证令牌。
生成的证书和配置文件将上传到证书仓库资源中

最后,打开您的 project 在 Xcode 中,更新您的应用程序的发布配置的分发配置文件。

注意事项 💡
MATCH
为了让 CI/CD 能够导入证书和分发配置文件,它需要访问证书仓库。您可以通过生成一个个人访问令牌(应在此之前使用),该令牌具有访问或读取私有仓库的权限。
在 GitHub 中,转到 设置 → 开发者设置 → 个人访问令牌 → 点击 Generate New Token → 勾选 repo 权限 → 然后点击 Generate token.

请保存生成的个人访问令牌,稍后将其用于环境变量 GIT_TOKEN.
然后用Matchfile替换Fastlane文件夹中生成的匹配文件 Matchfile
CERTIFICATE_STORE_URL = ENV["CERTIFICATE_STORE_URL"]
GIT_USERNAME = ENV["GIT_USERNAME"]
GIT_TOKEN = ENV["GIT_TOKEN"]
FASTLANE_APPLE_ID = ENV["FASTLANE_APPLE_ID"]
git_url(CERTIFICATE_STORE_URL)
storage_mode("git")
type("appstore")
git_basic_authorization(Base64.strict_encode64("#{GIT_USERNAME}:#{GIT_TOKEN}"))
username(FASTLANE_APPLE_ID)
此文件将被GitHub Actions用于导入证书和配置文件。 并且变量将在GitHub Secrets中设置,而不是在文件中硬编码。
构建处理
在GitHub Actions中, 您将根据运行CI/CD工作流程所用的分钟数进行计费。 从经验来看,构建在App Store Connect中处理需要约10-15分钟。
对于私有项目,估算的每次构建成本最高可达 $0.08/分钟 x 15 分钟 = $1.2或更多,具体取决于项目的配置或依赖项。
如果您对私有项目的定价有同样的担忧,就像我一样,可以保留 skip_waiting_for_build_processing 到 true.
实际上,这个过程中有一个陷阱:你需要手动更新你的应用程序在 App Store Connect 中的合规性,才能将构建分发给你的用户。
如果你想节省私有项目的构建时间,可以选择更新此参数。对于免费项目来说,这完全不是问题。 定价.
3. 配置GitHub
配置GitHub
你好奇这些值是从哪里来的?答案是:它们来自你的项目的密钥。 ENV 配置__CAPGO_KEEP_0__

1. APP_STORE_CONNECT_TEAM_ID - 在 App Store Connect 中,前往应用程序 →
2. DEVELOPER_APP_ID 应用信息 应用信息 → 向下滚动到您的应用程序并查找 General Information 您的应用程序的包标识符 Apple ID.
3. DEVELOPER_APP_IDENTIFIER - 如果您属于多个团队,则您的开发者门户团队 ID
4. DEVELOPER_PORTAL_TEAM_ID - 您用于管理应用程序的 Apple ID 或开发者电子邮件
5. FASTLANE_APPLE_ID &
6. GIT_USERNAME - 你的 Git 用户名和你的个人访问令牌 GIT_TOKEN - 当您初始化 match 时分配的密钥,用于解密证书和配置文件
7. MATCH_PASSWORD , 例如
8. PROVISIONING_PROFILE_SPECIFIER - match AppStore <YOUR_APP_BUNDLE_IDENTIFIER>& match AppStore com.domain.blabla.demo.
9. TEMP_KEYCHAIN_USER - 为您的工作流assign一个临时密钥链用户和密码 TEMP_KEYCHAIN_PASSWORD — App Store Connect __CAPGO_KEEP_0__ Key 🔺Key ID
10. APPLE_KEY_ID — App Store Connect API Key 🔺Key ID.
11. APPLE_ISSUER_ID —— App Store Connect API Key 🔺Issuer ID.
12. APPLE_KEY_CONTENT —— App Store Connect API Key 🔺 Key file or Key content of .p8, 在 Appflow 比较 / 迁移营销复制中,Appflow 凭证 Capgo Li1 的 HTML 文本片段(父级关键 `appflow_credentials_capgo_li1`).
13. CERTIFICATE_STORE_URL 在 Appflow 比较 / 迁移营销复制中,Appflow 凭证 Capgo Li1 的 HTML 文本片段(父级关键 `appflow_credentials_desc`). https://github.com/***/fastlane_match.git)
4. Configure GitHub workflow file
https://GitHub.com/***/fastlane_match.git
cd .github/workflows
4. 配置 __CAPGO_KEEP_0__ 工作流文件 workflow 创建一个 __CAPGO_KEEP_0__ 工作流目录 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: 2.7.2
- uses: maierj/fastlane-action@v2.3.0
env:
DEVELOPER_APP_IDENTIFIER: ${{ secrets.DEVELOPER_APP_IDENTIFIER }}
DEVELOPER_APP_ID: ${{ secrets.DEVELOPER_APP_ID }}
PROVISIONING_PROFILE_SPECIFIER: match AppStore ${{ secrets.DEVELOPER_APP_IDENTIFIER }}
TEMP_KEYCHAIN_USER: ${{ secrets.TEMP_KEYCHAIN_USER }}
TEMP_KEYCHAIN_PASSWORD: ${{ secrets.TEMP_KEYCHAIN_PASSWORD }}
APPLE_ISSUER_ID: ${{ secrets.APPLE_ISSUER_ID }}
APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }}
APPLE_KEY_CONTENT: ${{ secrets.APPLE_KEY_CONTENT }}
CERTIFICATE_STORE_URL: https://github.com/${{ secrets.CERTIFICATE_STORE_REPO }}.git
GIT_USERNAME: ${{ secrets.GIT_USERNAME }}
GIT_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
FASTLANE_APPLE_ID: ${{ secrets.FASTLANE_APPLE_ID }}
MATCH_USERNAME: ${{ secrets.FASTLANE_APPLE_ID }}
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
APP_STORE_CONNECT_TEAM_ID: ${{ secrets.APP_STORE_CONNECT_TEAM_ID }}
DEVELOPER_PORTAL_TEAM_ID: ${{ secrets.DEVELOPER_PORTAL_TEAM_ID }}
with:
lane: closed_beta
- name: Upload release bundle
uses: actions/upload-artifact@v2
with:
name: ios-release
path: ./App.ipa
retention-days: 60
并添加以下内容。这个工作流应该在每个 GitHub 标签, 如果您需要自动化标签,请参阅 自动构建和发布与 GitHub 动作 首先。
然后,这个工作流程将拉取您的 NodeJS 依赖项,安装它们并构建您的 JavaScript 应用程序。
每次您发送新的提交时,测试飞行中的发布将被构建。
您的应用程序不需要使用Ionic,只需 Capacitor 基础即可,且可以包含旧的Cordova模块,但 Capacitor JS插件应优先使用。
5. 触发工作流程
创建一个提交
制作一个 提交您应该在仓库中看到正在运行的工作流程。
触发工作流
推送新的提交到分支 main 或 development 让我们开始

或

或
推送新的提交到分支
推送新的提交到分支
推送新的提交到分支
推送新的提交到分支 my_project_path/fastlane 路径中的一个文件 。env, 与Fastfile在同一路径 才能创建相同的 机密 属性在我们的___CAPGO_KEEP_0__,a_s如下: properties found in our _GitHub, a_s below:
现在,您可以转到
终端 并启动 and launch the 快速lane 从您的机器上:
fastlane closed_beta
❌ 关于 .env 文件的重要信息 文件, 因为我们不想暴露这些数据, 我们必须在我们的 .gitignore 文件中添加它 , 类似于这样: ❌ 它应该与在远程机器上的 __CAPGO_KEEP_0__ Actions 上发生的相同, 但是在我们的本地机器上。 🍻本地快速lane 运行
fastlane/*.env
It should work the same as it happens from GitHub Actions on the remote machine but in our local machine. 🍻

每次您发送新的提交, 在 Google Play 控制台中, beta 通道中将会构建一个发布。 我会根据您的反馈来改进这篇博客, 如果您有任何问题或建议, 请通过电子邮件联系我
If you have come this far, my congratulations, now you have a fully automated process for your iOS apps with Fastlane and GitHub Actions.
终端执行: $ 快速lane closed_beta martin@capgo.app
在设备上构建
如果您仍需要在设备上构建,需要手动将它们添加到配置文件中。
将设备连接到您的Mac并打开设备菜单
然后复制您的标识符
然后输入以下命令:
fastlane register_new_device
它会要求您设置设备名称和标识符:

如果您遇到问题
如果您遇到开发设备无法测试等问题,通常可以通过以下解决。
有一个神奇的命令可以帮助您:
fastlane match nuke development
fastlane match development
然后: 清理项目,按住 Shift(⇧)+Command(⌘)+K 或选择 Product > Clean(它可能标记为“清理构建文件夹”)
然后再次尝试在设备上运行应用。
感谢
本博客基于以下文章:
从自动 Capacitor IOS 构建中继续,使用 GitHub 动作和 match
如果您正在使用 自动 Capacitor IOS 构建,使用 GitHub 动作和 match 来规划 CI/CD 自动化,连接它与 Capgo CI/CD 为Capgo产品工作流程在Capgo CI/CD中 Capgo原生构建 为Capgo产品工作流程在Capgo原生构建中 Capgo集成 为Capgo产品工作流程在Capgo集成中 CI/CD集成 为CI/CD集成的实现细节 GitHub动作集成 为GitHub动作集成的实现细节