Highlight
Apple 为 Xcode Cloud 增加环境变量、自定义脚本、额外 Git 仓库授权和 Webhooks,让开发者把团队内部工具、私有依赖和外部服务接入云端构建流程。
核心内容
很多团队的构建流程早就超出了“编译一下”这件事。
测试环境要连 staging API,发布环境要用 production API。PR 构建要换一个图标,避免测试者把 beta 版当成正式版。应用依赖私有 Swift package,CI 必须能拉到对应仓库。构建完成后,团队还希望自动通知测试者,或者触发下游发布流程。
如果这些步骤靠本地机器完成,配置会散落在每个开发者的电脑里。有人忘记设置环境变量,有人少跑一个脚本,有人没有私有仓库权限,构建结果就不一致。
Xcode Cloud 的基础 workflow 已经能构建、测试、归档和分发应用。这场 session 讲的是更靠近真实团队的一层:怎么把 workflow 调成团队自己的流程。
Apple 提供了四个入口。环境变量把配置传进构建环境。ci_scripts 里的 shell 脚本在固定阶段执行自定义命令。额外仓库授权让私有依赖进入云端构建。Webhooks 在构建生命周期里向外部服务发送 HTTP 请求。
这些能力的共同目标很明确:把原来写在团队 wiki、聊天记录、个人 shell 配置里的步骤,放进 Xcode Cloud 可重复执行的 workflow。
详细内容
用环境变量把构建配置传进去
(01:44)一个常见场景是测试环境切换。应用依赖某个 API 服务,测试时应该访问 staging,正式分发时才访问 production。把 URL 写死在代码里,会让同一份代码很难服务多个 workflow。
Xcode Cloud 的 Environment section(环境配置区)支持 key-value 形式的环境变量。变量属于 workflow 配置,不需要提交到源码仓库。每次 workflow 运行时,Xcode Cloud 会把这些变量设置到执行 action 的临时环境中。
Environment variables in Xcode Cloud
API_BASE_URL=https://staging.example.com
CI_WORKFLOW=<current workflow name>
CI_PRODUCT_PLATFORM=<iOS | macOS | tvOS | watchOS>
CI_XCODEBUILD_ACTION=<build | test | analyze | archive>
关键点:
API_BASE_URL:团队可以在 workflow 里配置业务服务地址,测试流程使用 staging 地址。CI_WORKFLOW:Xcode Cloud 提供的变量,可用于判断当前运行的是哪个 workflow。CI_PRODUCT_PLATFORM:Xcode Cloud 提供的变量,可用于判断当前 action 面向哪个 Apple 平台。CI_XCODEBUILD_ACTION:Xcode Cloud 提供的变量,可用于判断当前 action 是构建、测试、分析还是归档。
(02:37)敏感信息使用 secret environment variable(秘密环境变量)。API key 或 access token 可以加密存储。解密后的值只会出现在运行 action 的临时环境中,日志里会被遮盖,workflow editor 里也不能再次查看明文。
Secret environment variables
API_TOKEN=<encrypted value>
ACCESS_TOKEN=<encrypted value>
关键点:
API_TOKEN:适合保存 API key 这类敏感值。ACCESS_TOKEN:适合保存访问外部服务的 token。<encrypted value>:Xcode Cloud 保存的是加密值,运行时才在临时环境中解密。
用 ci_scripts 插入自定义构建步骤
(03:50)自定义脚本是放在源码仓库里的 shell script。Xcode Cloud 支持三类脚本,它们按固定时机运行。
ci_scripts/
ci_post_clone.sh
ci_pre_xcodebuild.sh
ci_post_xcodebuild.sh
关键点:
ci_post_clone.sh:主仓库克隆完成后运行。ci_pre_xcodebuild.sh:依赖解析完成后、xcodebuild执行前运行。ci_post_xcodebuild.sh:xcodebuild结束后运行,随后 Xcode Cloud 保存构建产物。ci_scripts:文件夹名称必须精确匹配,并且要和 workflow 使用的 project 或 workspace 放在同一级。
(09:03)演示里的 Fruta 应用有一个具体需求:PR 构建通过 TestFlight 分发给团队测试时,应用图标要换成 beta 图标。这样测试者在手机上能立刻识别当前安装的是 PR 构建。
#!/bin/sh
# ci_pre_xcodebuild.sh
# Fruta
#
# Made in Vancouver, Canada
#
if [[ -n $CI_PULL_REQUEST_NUMBER && $CI_XCODEBUILD_ACTION = 'archive' ]];
then
echo "Setting Fruta Beta App Icon"
APP_ICON_PATH=$CI_WORKSPACE/Shared/Assets.xcassets/AppIcon.appiconset
# Remove existing App Icon
rm -rf $APP_ICON_PATH
# Replace with Fruta Beta App Icon
mv "$CI_WORKSPACE/ci_scripts/AppIcon-Beta.appiconset" $APP_ICON_PATH
fi
关键点:
#!/bin/sh:声明脚本由 shell 执行。ci_pre_xcodebuild.sh:脚本名决定它会在xcodebuild前运行。CI_PULL_REQUEST_NUMBER:Xcode Cloud 提供的变量;有值时表示这次构建来自 pull request。CI_XCODEBUILD_ACTION = 'archive':只在归档 action 中换图标,因为 TestFlight 分发前会先归档。echo "Setting Fruta Beta App Icon":把当前操作写入 action 日志,方便排查。APP_ICON_PATH=$CI_WORKSPACE/...:用CI_WORKSPACE组装项目内资源路径。rm -rf $APP_ICON_PATH:删除默认 app icon set。mv "$CI_WORKSPACE/ci_scripts/AppIcon-Beta.appiconset" $APP_ICON_PATH:把ci_scripts中的 beta 图标移动到默认图标位置。
(10:48)脚本的标准输出和标准错误会进入 action 日志,也可以从 Artifacts tab 下载。脚本退出码会影响 action 结果;非零退出码会让 Xcode Cloud 判定 action 失败。
#!/bin/sh
set -e
echo "Run a required custom command"
# your command here
关键点:
set -e:命令失败时停止脚本,让失败尽早暴露。echo:把关键步骤写入日志,方便定位脚本是否执行。# your command here:替换为团队需要在 action 中运行的命令。
让 Xcode Cloud 访问额外 Git 仓库
(12:41)很多项目依赖共享库、工具或框架。它们通常放在团队私有 Git 仓库里。Xcode Cloud 构建项目时,如果没有权限访问这些仓库,构建会失败。
演示里的 Fruta 要加入一个叫 InvitationsKit 的私有 Swift package。开发者在 Xcode 里通过 Add Package 添加依赖,提交并推送后,Xcode Cloud 的新构建检测到它无法访问该仓库,于是在 App Store Connect 里显示授权提示。
Additional repository flow
1. Add InvitationsKit in Xcode
2. Commit and push the package dependency
3. Xcode Cloud starts a build
4. Build fails because repository access is missing
5. Open Manage Repositories
6. Grant access to the InvitationsKit repository
7. Rerun the build
关键点:
- 第 1 步:依赖仍然从 Xcode 正常加入项目。
- 第 3 步:workflow 可以由新 commit 自动触发。
- 第 4 步:首次引用私有仓库时,Xcode Cloud 可能没有访问权限。
- 第 5 步:失败页面会提供 Manage Repositories 入口。
- 第 6 步:授权动作可能会跳转到 GitHub 等源码服务完成确认。
- 第 7 步:授权完成后,重新运行构建即可拉取该依赖。
(16:07)这个机制不限于 Swift package。Xcode Cloud 会在构建期间检测新引用的 Git 仓库。自定义脚本里 clone 的仓库、Git submodule、其他依赖管理工具引用的 Git 仓库,也会走同一类授权流程。
Repository references detected by Xcode Cloud
- Swift package dependency
- Git clone inside a custom script
- Git submodule
- Git repository used by another dependency manager
关键点:
Swift package dependency:演示中的InvitationsKit属于这一类。Git clone inside a custom script:脚本里主动拉取仓库时,也需要 Xcode Cloud 有权限。Git submodule:项目使用 submodule 时,Xcode Cloud 同样需要访问对应仓库。another dependency manager:其他依赖工具只要引用 Git 仓库,也可能触发授权需求。
用 Webhooks 连接外部服务
(17:31)Webhooks 让 Xcode Cloud 在构建生命周期中向外部服务发送实时更新。团队可以用它通知 beta 测试者、创建或关闭 issue、构建失败时通知值班系统,或者触发下游构建。
Xcode Cloud 支持在三个阶段发送 webhook。
Xcode Cloud webhook delivery stages
1. Build is created
2. Build is starting
3. Build has completed
关键点:
Build is created:代码推送或手动启动构建后触发。Build is starting:构建开始执行时触发。Build has completed:构建结束时触发,成功和失败都会覆盖。
(18:01)添加 webhook 的入口在 App Store Connect 的 Xcode Cloud settings。每个 product 最多可以创建 5 个 webhook。配置项包括 webhook 名称和一个能接收 HTTP requests(HTTP 请求)的服务 URL。
Webhook configuration
Name: Release notification
URL: https://example.com/xcode-cloud/webhook
Limit: up to five webhooks per product
Payload: JSON blob with app, workflow, product, build, and more
关键点:
Name:名称应保持唯一,方便区分不同 webhook。URL:目标服务必须能接收并处理 HTTP 请求。Limit:每个 product 最多 5 个 webhook。Payload:Xcode Cloud 发送 JSON blob,内容包含 App Store Connect app、workflow、product、build 等信息。
(19:16)Apple 的示例逻辑是:服务收到请求,解码 JSON payload,检查 workflow 名称和 build state。如果 release workflow 构建成功,就向 Twitter 发消息,告诉测试者新版本可以测试。处理完成后返回 200 status code。
Webhook handler logic
1. Receive the request
2. Decode the payload to a JSON object
3. Check workflow name
4. Check build state
5. Post a message to Twitter when release workflow succeeded
6. Return HTTP 200
关键点:
- 第 1 步:外部服务作为 webhook endpoint 接收请求。
- 第 2 步:payload 是 JSON,需要先解码。
- 第 3 步:根据 workflow 名称筛选发布流程。
- 第 4 步:根据 build state 判断构建结果。
- 第 5 步:只有 release workflow 成功时才通知测试者。
- 第 6 步:返回 200 表示请求已处理。
(19:59)如果 endpoint 没有返回成功状态码,Xcode Cloud 会重试发送请求。App Store Connect 里也可以查看 webhook delivery 记录,检查发出的 request 和收到的 response。
Webhook troubleshooting
- Xcode Cloud retries when the endpoint does not return a successful status code
- App Store Connect shows delivered requests
- App Store Connect shows received responses
关键点:
retries:外部服务短暂失败时,Xcode Cloud 会再次发送。delivered requests:可以查看 Xcode Cloud 实际发送了什么。received responses:可以查看 endpoint 返回了什么,定位格式或状态码问题。
核心启发
-
做什么:给 PR 构建自动换 beta 图标。 为什么值得做:演示中的 Fruta 用
CI_PULL_REQUEST_NUMBER和CI_XCODEBUILD_ACTION判断构建来源,TestFlight 测试者能直接从桌面图标识别 PR 版本。 怎么开始:在项目同级目录创建ci_scripts/ci_pre_xcodebuild.sh,把 betaAppIcon.appiconset放进ci_scripts,在脚本里用CI_WORKSPACE替换资源。 -
做什么:为不同 workflow 配置不同 API 环境。 为什么值得做:环境变量属于 workflow 配置,不用把 staging URL 或 token 提交到仓库。secret 变量还能隐藏敏感值。 怎么开始:在 Xcode Cloud workflow 的 Environment section 添加
API_BASE_URL,把 API key 设置为 secret environment variable。 -
做什么:把私有 Swift package 纳入云端构建。 为什么值得做:Xcode Cloud 会检测构建中引用的额外 Git 仓库,并在 App Store Connect 提供授权入口。 怎么开始:先在 Xcode 里 Add Package,提交依赖变更。构建失败后打开 Manage Repositories,为私有仓库 Grant access,再 rerun build。
-
做什么:构建成功后自动通知 beta 测试者。 为什么值得做:Webhooks 会在构建创建、开始和完成时发送 JSON payload,外部服务可以根据 workflow 和 build state 决定是否通知。 怎么开始:在 Xcode Cloud settings 里新增 webhook,URL 指向自己的 HTTP endpoint。服务收到请求后解码 JSON,判断 release workflow 是否 succeeded,最后返回 HTTP 200。
-
做什么:构建失败时自动通知值班系统。 为什么值得做:Apple 明确提到 webhooks 可以把构建失败发送到 paging system,适合发布流程和主分支保护。 怎么开始:为主分支 workflow 配置 webhook,在 endpoint 中检查 build state,失败时调用团队已有的告警服务。
关联 Session
- Meet Xcode Cloud — 介绍 Xcode Cloud 作为 Apple 平台 CI/CD 服务的基本概念。
- Explore Xcode Cloud workflows — 讲解 workflow 的启动条件、环境、actions 和分发步骤。
- Meet TestFlight on Mac — 展示 Xcode Cloud 构建如何进入 TestFlight 测试分发流程。
- Discover and curate Swift Packages using Collections — 讲解演示中用到的 Swift Package collections 和包导入流程。
评论
GitHub Issues · utterances