Automatic iOS Builds with GitHub Actions using Match
为 Capacitor 应用设置 CI/CD 可能会很复杂和耗时。以下是您需要了解的内容:
推荐新构建:使用 Capgo 构建
我们现在建议使用 Capgo 构建与 Capgo CLI 用于本机 Capacitor 构建。 本指南是为维护现有 GitHub Actions pipeline 的团队而保留的,但新 iOS 构建应使用 Capgo CLI 以免自己维护 Fastlane、Match 仓库、Xcode 运行器、证书和上传脚本。
Capgo 构建由 Capgo 提供
跳过 Fastlane Match、Xcode 运行器、证书、分发配置文件和上传脚本的维护 Capgo 构建 从您的现有CI/CD管道中运行已签名的原生iOS构建:
- 与您的管道一起工作: 触发 Capgo 从 GitHub Actions、GitLab CI、Jenkins 或本地脚本后进行您的 Web 构建和
npx cap sync. - 从CI机密中签名: 在您的CI机密中保留App Store Connect密钥、证书、分发配置文件、密码和团队ID
- 无native runner维护: Capgo 构建提供维护的Apple构建环境,因此您不需要管理macOS runner、Xcode图像、Fastlane或Match仓库
- 工件和提交: 下载用于QA的已签名工件或通过Capgo CLI提交发布构建
定价
- : Capgo 计划从$12/月开始
- 包括即时 OTA 更新和每月约 15 个本机构建
- 额外的构建分钟通过分钟计费使用积分
手动设置指南
您需要做的如下
使用 Fastlane 和 GitHub 动作的 iOS 持续交付
先决条件
继续教程之前,请确保
- 在开发机器上安装 Fastlane 拥有 iOS 开发者计划会员资格 __CAPGO_KEEP_0__
- __CAPGO_KEEP_0__
- 想读的内容😆…
- 团队中有很多开发者,否则我们建议使用 快速lane证书 更简单的工作流程。
关于价格的重要信息

https://github.com/features/actions
服务在限制范围内是免费的,具体取决于所选择的机器。
我们将使用一个 macOS 机器,截图中显示了其价格和限制(价格截至教程创建时间,可能会在未来发生变化)
🔴 已警告要求和价格后,如果您喜欢,我们继续...
📣 In本文中,我们假设我们已经在 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。
- 密钥 ID。
- 密钥文件或密钥内容。
- 创建 App Store Connect __CAPGO_KEEP_0__ 密钥
Creating an App Store Connect API Key
1 — 登录到
2 — App Store 连接.
2 — 选择 用户和访问.

3 — 选择 Integration tab.

4 — 点击 Generate API Key 或 (+) 按钮。

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

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

您可以在这里获取所有三个必要的信息。
1. 问题 ID。
2. 密钥 ID。
3. 点击“下载 API 密钥”以下载您的 API 私有密钥。下载链接仅在私有密钥尚未下载时才会出现。苹果公司不会保留私有密钥的副本。因此,您只能下载一次。
🔴 请将您的私有密钥存储在安全的地方。您不应共享您的密钥、将密钥存储在 code 仓库中或将密钥包含在客户端 code 中。
使用 App Store Connect API 密钥
您需要的有API Key文件(下载的p8文件)、密钥ID和发行者ID来创建用于授权的JWT令牌。这些信息可以通过多种方式输入到Fastlane中,使用Fastlane的新动作 app_store_connect_api_key. 您可以学习其他方式在 Fastlane文档中。 我展示这个方法,因为我认为它是与大多数CI一起工作最容易的方法,
现在我们可以使用App Store Connect的API密钥来管理Fastlane,真棒!
现在我们可以使用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"])
Appfile
配置Fastlane match match is a new approach to iOS’s code signing. Fastlane match makes it easy for teams to manage the required certificates and provisioning profiles for your iOS apps.
创建一个名为 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 文件夹中有一个名为 Matchfile 并且
_git_url_context: Capgo 营销网站。角色:短 UI 标签或导航项。见于:页面 trust.astro。消息键 `and` (And)。
# ios/Matchfilegit_url("https://github.com/gitusername/certificates")storage_mode("git")type("appstore")
应该设置为证书仓库的 HTTPS URL。可选地,您也可以使用 SSH,但这需要一个不同的步骤来运行。
接下来,我们将生成证书并在 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 能够导入证书和配置文件,它需要访问证书仓库。您可以通过生成一个个人访问令牌(应该在此之前使用),该令牌具有访问或读取私有仓库的权限。
In GitHub, 前往 设置 → 开发者设置 → 个人访问令牌 → 点击 Generate New Token → 勾选 repo 范围 → 然后点击 Generate token.

已生成个人访问令牌,请复制。您稍后将使用它作为环境变量 GIT_TOKEN.
然后将 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 中设置,而不是在文件中硬编码。
构建处理
In GitHub Actions中 您将根据分钟数付费 对于私有项目,估计每次构建的成本可以达到
$0.08/分钟 x 15 分钟 = $1.2 ,或更多,取决于您的项目的配置或依赖项。如果您与我一样,对私有项目的定价有同样的担忧,可以保留
到 skip_waiting_for_build_processing to true.
这只是一个可选参数,如果您想为私有项目节省构建分钟数,或者您不想为免费项目支付此费用,请更新此参数。请参见
定价 pricing.
3. 配置GitHub Actions
配置 GitHub 秘密
你是否曾经想知道这些值的来源? ENV 答案不再是秘密了,它来自你的项目的秘密。 🤦

1. APP_STORE_CONNECT_TEAM_ID - 如果你属于多个团队,需要 App Store Connect 团队 ID。
2. DEVELOPER_APP_ID - 在 App Store Connect 中,进入应用程序 → 应用程序信息 → 滚动到底部到应用程序的 General Information 部分并寻找 Apple ID.
3. DEVELOPER_APP_IDENTIFIER - 应用程序的包标识符。
4. DEVELOPER_PORTAL_TEAM_ID - 如果你属于多个团队,需要开发者门户团队 ID。
5. FASTLANE_APPLE_ID - 你用于管理应用程序的 Apple ID 或开发者电子邮件。
6. GIT_USERNAME " GIT_TOKEN - 您的 Git 用户名和您的个人访问令牌。
7. MATCH_PASSWORD - 当您初始化 match 时分配的密钥短语,将用于解密证书和配置文件。
8. PROVISIONING_PROFILE_SPECIFIER - match AppStore <YOUR_APP_BUNDLE_IDENTIFIER>, 例如。 match AppStore com.domain.blabla.demo.
9. TEMP_KEYCHAIN_USER " TEMP_KEYCHAIN_PASSWORD - 为您的工作流assign一个临时密钥链用户和密码。
10. APPLE_KEY_ID — App Store Connect API 密钥 🔺密钥 ID。
11. APPLE_ISSUER_ID — App Store Connect API 密钥 🔺颁发者 ID。
12. APPLE_KEY_CONTENT — App Store Connect API 密钥 🔺密钥文件或密钥内容(.p8)。 .p8, 检查它
13. CERTIFICATE_STORE_URL — 您的 Match 密钥仓库 URL(例如: https://github.com/***/fastlane_match.git)
4. 配置 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: 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 标签发布后触发,如果您需要自动化标签发布,请参阅 tag首先。 自动化构建和发布与GitHub动作 first.
Create a __CAPGO_KEEP_0__ workflow directory.
每次您发送新的提交,测试版将在TestFlight中构建。
您的App不需要使用Ionic,只需使用Capacitor的基本版本即可,它可以使用旧的Cordova模块,但Capacitor的JS插件应该优先使用。
5. 触发工作流程
创建一个提交
制作一个 提交,您应该在仓库中看到正在激活的工作流程。
触发工作流程
将新的提交推送到分支 main 或 development 触发工作流程以构建测试版。

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

是否可以从本地机器部署?
是的,您可以,而且非常方便。
假设您有一个私有的仓库,且已用完免费计划的分钟数,您不想为新发布支付费用,或者您更喜欢手动提交应用程序。
让我们开始吧
好的,首先我们需要在 my_project_path/fastlane 路径中创建一个名为 .env 的文件, Fastfile, 为了能够创建相同的 密钥 在我们的_GitHub中找到的属性,以下是:
.env文件用于从本地机器部署
现在,您可以转到终端 并从您的机器上启动 Fastlane : ❌关于
fastlane closed_beta
.env .env 我们不想暴露这个文件,所以我们需要在我们的 .gitignore自動 Capacitor iOS 构建 GitHub Action 与 Match
fastlane/*.env
它应该与在远程机器上的 GitHub Actions 一样工作,但是在我们的本地机器上。 🍻

终端执行: $ Fastlane closed_beta
如果你已经走到这一步,我恭喜你,现在你已经拥有了一个完全自动化的iOS应用程序构建过程,使用Fastlane和 GitHub Actions。
每次你发送一个新的提交,一个release将会在Google Play控制台,beta通道中构建。 我会根据你的反馈来改进这个博客,如果你有任何问题或建议,请通过电子邮件联系我 马丁@capgo.app
在你的设备上构建
如果你仍然需要在你的设备上构建,你需要手动将它们添加到配置文件中。
将你的设备连接到你的mac,然后打开设备菜单
然后复制你的标识符
然后开始命令:
fastlane register_new_device
它会要求您设置设备名称和标识符:

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