如果你将 React Native / Expo 应用发布到 App Store,你一定熟悉这个流程。打开 Apple Developer 门户,创建 bundle identifier,勾选功能复选框,生成配置文件,选择正确的证书。然后跳转到 Expo 仪表板,创建 EAS 应用,连接凭证,一次一个屏幕地添加环境变量。
它可以工作,直到你需要为第二个应用或第二个环境重复操作,或者团队成员需要了解为什么某个功能被启用。所有这些都没有记录下来。它会漂移。而通常的移动工具在这里帮助不大:fastlane 和 EAS CLI 很好,但它们是命令式的——执行操作的脚本——而不是对发布设置应该是什么的声明性描述。
这两个提供程序填补了这个空白:
-
elevenode/appstore— App Store Connect:bundle identifiers、配置文件、证书。 -
elevenode/expo— Expo Application Services (EAS):应用、凭证、环境变量、更新通道。
两者都是开源的(Apache 2.0)并在 Terraform Registry 上发布。让我们一起使用它们,将移动应用的发布设置描述为代码。
你需要什么
- Terraform(或 OpenTofu)
- 一个 App Store Connect API 密钥(用户和访问 → 集成 → App Store Connect API):密钥、密钥 ID 和发行者 ID
- 一个 Expo 访问令牌(expo.dev → 账户设置 → 访问令牌)和你的 Expo 账户名称
将凭证导出为环境变量,这样敏感信息就不会进入你的配置中:
export APPSTORE_KEY="$(cat AuthKey_XXXX.p8)"
export APPSTORE_KEY_ID="XXXXXXXXXX"
export APPSTORE_KEY_ISSUER_ID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
export EXPO_TOKEN="your-expo-access-token"
export EXPO_ACCOUNT_NAME="your-account-name"
Enter fullscreen mode Exit fullscreen mode
连接两个提供程序
terraform {
required_providers {
appstore = {
source = "elevenode/appstore"
}
expo = {
source = "elevenode/expo"
}
}
}
# 从环境变量中读取 APPSTORE_KEY / APPSTORE_KEY_ID / APPSTORE_KEY_ISSUER_ID。
provider "appstore" {}
# 从环境变量中读取 EXPO_TOKEN / EXPO_ACCOUNT_NAME。
provider "expo" {}
Enter fullscreen mode Exit fullscreen mode
terraform init 从 registry 中拉取两个提供程序。
第一部分 — Apple 端
首先是 bundle identifier 及其所需的功能。这取代了开发者门户中的复选框界面:
resource "appstore_bundle_identifier" "app" {
name = "Acme"
identifier = "com.acme.app"
platform = "IOS"
capabilities = [
"PUSH_NOTIFICATIONS",
"APPLE_ID_AUTH",
"IN_APP_PURCHASE",
]
}
Enter fullscreen mode Exit fullscreen mode
然后是一个将该 bundle ID 绑定到签名证书的配置文件。证书 ID 来自你的 Apple 账户(你可以将它们作为变量传入,以便配置保持可移植性):
variable "distribution_certificate_ids" {
type = list(string)
description = "要嵌入配置文件的 App Store Connect 证书 ID。"
}
resource "appstore_provisioning_profile" "app_store" {
name = "Acme App Store"
type = "IOS_APP_STORE"
bundle_identifier_id = appstore_bundle_identifier.app.id
certificate_ids = var.distribution_certificate_ids
}
Enter fullscreen mode Exit fullscreen mode
注意 bundle_identifier_id 引用——Terraform 现在知道配置文件依赖于 bundle ID,并将按正确顺序创建它们。当你手动操作时,这种依赖关系是不可见的。
第二部分 — Expo 端
创建 EAS 应用,然后声明其环境变量,而不是在仪表板中输入它们:
resource "expo_app" "app" {
name = "Acme"
slug = "acme"
}
resource "expo_app_variable" "api_url" {
app_id = expo_app.app.id
name = "API_URL"
value = "https://api.acme.com"
visibility = "PUBLIC"
environments = ["PRODUCTION"]
}
Enter fullscreen mode Exit fullscreen mode
你也可以从这里驱动 EAS Update。定义一个分支和一个将更新映射到其上的通道:
resource "expo_update_branch" "production" {
app_id = expo_app.app.id
name = "production"
}
resource "expo_update_channel" "production" {
app_id = expo_app.app.id
name = "production"
branch_mapping = jsonencode({
version = 0
data = [{
branchId = expo_update_branch.production.id
branchMappingLogic = "true"
}]
})
}
Enter fullscreen mode Exit fullscreen mode
应用
terraform apply
Enter fullscreen mode Exit fullscreen mode
Terraform 会显示完整的计划——bundle ID、其功能、配置文件、EAS 应用、其变量、更新通道——在任何内容被创建之前。批准它,你的整个移动发布设置就存在了,在一个地方描述。
现在有趣的部分:针对一个全新的 Apple 团队和 Expo 账户再次运行它,你会得到一个相同的设置。在配置中更改一个功能,打开一个 PR,你的团队成员可以在它到达 Apple 之前审查差异。从配置中删除一个资源,terraform plan 会准确告诉你将要删除什么。这就是基础设施即代码的全部意义,最终应用于移动端总是存在于 web 控制台的那部分。
尝试
两个提供程序都是开源的,并接受 issue 和 pull request:
- App Store Connect: github.com/elevenode/terraform-provider-appstore (registry)
- Expo EAS: github.com/elevenode/terraform-provider-expo (registry)
如果它们为你节省了一些点击,一颗星可以帮助其他人找到它们。如果你希望存在某个资源,请提交 issue——这正是塑造接下来构建内容的那种反馈。
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.