# 小团队用 Xcode Cloud:工作流、开始条件和计算时数 > Xcode Cloud 工作流是什么,开始条件,构建、测试、分析、归档操作,TestFlight 和通知后续操作,ci_scripts,CI_ 环境变量,计算时数与日志位置。 - Canonical page: https://obelisk.club/blog/xcode-cloud-guide-zh - Author: Peter Zhang - Published: 2026-11-01 - Tags: xcode, xcode-cloud, testflight, ci, indie, 中文 Xcode Cloud 是 Apple 放在 Xcode 和 App Store Connect 里的构建服务。你配置一个**工作流**(构建什么、什么时候构建、用哪个版本的 Xcode 和 macOS、构建完做什么),之后每次推送、打开拉取请求、打标签、到了排定的时间,或者有人点 Start Build,Apple 的服务器就会构建、测试和归档你的 App。Apple Developer Program 会员**每月含 25 个计算时数**;付费方案提供每月 100、250、1,000 或 10,000 小时(价格见下文,2026 年 11 月 1 日读取)。日志和产物最多保存 30 天,所以上架 App Store 的版本要自己下载保存。 ## 开始之前 来自 Apple 的 "Get started" 和配置页面: - 需要 **Xcode 15.0 或更高版本**,以及 Apple Developer Program 会员资格。 - 第一次配置必须在 Xcode 里完成(报告导航器 → Cloud 按钮 → Get Started)。第一次构建之后,工作流可以在 Xcode 里改,也可以在 App Store Connect 中该 App 的 **Xcode Cloud** 标签页里改。 - 能配置工作流的人:账户持有人、管理员、App 管理,或者有创建 App 记录权限的开发者、营销角色。 - 支持的 Git 托管:Bitbucket Cloud 和 Server、GitHub 和 GitHub Enterprise、GitLab 和自建 GitLab。授权访问仓库需要仓库托管方的管理员级权限。 - Apple 提醒:如果你用工具在构建时临时生成或修改项目文件,"Xcode Cloud 的初始配置和之后的构建都可能失败"。项目文件需要原样放在仓库里。 ## 工作流是什么 Apple 的说法是:工作流就是"你希望 Xcode Cloud 执行的步骤的配置"。每个工作流包括: - **General**:名称和描述。Apple 建议起好认的名字,比如 "Nightly Builds",即使你一个人开发也可能有好几个工作流。 - **Environment**:Xcode 和 macOS 版本、可选的 **Clean** 构建(不用缓存),以及自定义环境变量。 - **开始条件**:什么情况下开始构建。 - **操作**:构建、测试、分析、归档。 - **后续操作**:通知、TestFlight、上传到 App Store Connect 备审。 Apple 建议的小团队分法:一个工作流在分支或拉取请求有改动时构建并测试;另一个在合并到 `main` 时构建、测试、分析并归档。 环境里有两点值得知道: - 构建默认复用缓存的 derived data。要发给 TestFlight **外部**测试员的工作流必须打开 **Clean**,Apple 说这会"明显增加构建所需时间"。 - Apple "可能会更新可用的 macOS 和 Xcode 版本,并要求你更新工作流"。构建机器包含 macOS 和 Xcode 自带的工具,另外装了 Homebrew,方便安装第三方工具。 ## 开始条件 | 开始条件 | 什么时候开始构建 | |---|---| | Branch Changes | 任意分支、某个分支、几个分支,或以某个前缀开头的分支有改动 | | Pull Request Changes | 拉取请求被创建或更新(可按源分支和目标分支过滤) | | Tag Changes | 标签被创建或更新(任意标签、指定标签,或以 `v1` 这类前缀开头的标签) | | On a Schedule for a Branch | 按你选的频率、时间和分支 | | Manual Start | 团队成员点 Start Build,可限定允许的分支、标签或拉取请求 | Apple 页面上的细节: - 新工作流默认是**默认分支的 Branch Changes**。Apple 指出,对慢的工作流(比如在很多模拟器上跑 UI 测试)来说,这可能太频繁。 - 对拉取请求,Xcode Cloud 会检出源分支和目标分支,在临时环境里合并,再对合并结果执行操作。 - **按文件和文件夹过滤**:分支、拉取请求和标签条件可以设为只在某些文件、文件夹或扩展名改动时开始构建,或者对它们跳过构建。同一个条件只能"开始"或"跳过"二选一,文件名里不能用 `*` 之类的通配符。 - **跳过某次推送**:在最新推送的那个提交的标题或说明里写 `[ci skip]`。 - **Auto-cancel Builds** 默认开启:同一个工作流排进新构建时,正在跑的构建会被取消。可以按开始条件关闭。 - Apple 建议给 TestFlight 构建用排程(比如每周一次),而不是每次改动都发,免得测试员被新版本淹没。 ## 操作 | 操作 | 执行的命令 | Apple 列出的产物 | |---|---|---| | Build | 针对某平台和 scheme 执行 `xcodebuild build`,目标为任意设备或任意模拟器 | 构建产品、构建日志、结果包 | | Test | 先 `xcodebuild build-for-testing`,再在你添加的目标设备上 `test-without-building` | 测试产品和结果包 | | Analyze | `xcodebuild analyze`(静态分析) | 构建日志 | | Archive | `xcodebuild archive` | 导出的归档或 framework 包、构建日志 | - 测试操作自己会为测试而构建,不用另加构建操作。目标设备越多,构建越久。 - 测试和分析可以设为 **Required to Pass** 或 **Not Required to Pass**。 - 每个操作在各自的临时环境里执行,一个操作产生的文件,另一个操作不一定拿得到。 - 归档操作的 **Deployment Preparation** 决定签名方式:**None**(不能用于 TestFlight 或 App Store)、**TestFlight (Internal Testing Only)**、**TestFlight and App Store**。发给外部测试员和正式上架都要选最后一个。 ## 后续操作 操作完成后,工作流可以: - **Notify**:只在某些构建结果时发邮件、多发给几个人,或者发到 Slack(用 Apple 提供的 Slack App;每个工作流可以用不同频道,也可以发私信;在 App Store Connect 里连接需要 App 管理、管理员或账户持有人角色)。 - **TestFlight**:把构建版本发给内部或外部测试员。先在 App Store Connect 里建好内部测试员群组。发给外部群组的构建仍要过 TestFlight App 审核,见我们的 [TestFlight 清单](/blog/testflight-checklist-zh)。 - **App Store Connect**:上传一个版本,之后可以提交审核。 ## 自定义构建脚本 在 `.xcodeproj` 或 `.xcworkspace` 同级目录建一个 `ci_scripts` 文件夹,把脚本放进去。只认三个文件名,而且必须放在这个文件夹的顶层: | 文件 | 什么时候运行 | |---|---| | `ci_post_clone.sh` | 克隆仓库之后(装工具、改 plist) | | `ci_pre_xcodebuild.sh` | 执行 `xcodebuild` 之前 | | `ci_post_xcodebuild.sh` | 执行 `xcodebuild` 之后,失败了也会运行(把产物上传到别处) | 每个操作都会跑这些脚本。Apple 的规则: - 脚本要可执行(`chmod +x`),第一行写 shebang,比如 `#!/bin/sh`。否则会以 `zsh $filename` 方式运行,可能导致构建失败。 - 不能用 `sudo`。 - 脚本生成的文件事后会被删除,其他脚本看不到,也不会出现在可下载的产物里。 - 脚本运行时源代码不一定在,所以脚本要用的资源放在 `ci_scripts` 里(或者在里面放符号链接)。 - 出错时返回非零退出码;Apple 的示例用了 `set -e`。非零退出码会让构建失败。 - 辅助脚本也可以放在 `ci_scripts` 里,Apple 建议它们的文件名不要以 `ci_` 开头。 ## 环境变量 **自己的变量**放在工作流的 Environment 部分。密钥和令牌要勾选 **Keep value redacted**(Xcode)或 **Secret**(App Store Connect),这样在日志里显示为 `**********`。**共享环境变量**可以套用到多个工作流、在一处修改,也可以限制只有账户持有人能改。 Apple 列出的始终可用的**预定义变量**包括: | 变量 | 值 | |---|---| | `CI`、`CI_XCODE_CLOUD` | 在 Xcode Cloud 中运行时为 `TRUE` | | `CI_BUILD_NUMBER`、`CI_BUILD_ID`、`CI_BUILD_URL` | 构建号、唯一 ID、App Store Connect 中该构建的链接 | | `CI_COMMIT` | 正在构建的 Git 提交哈希 | | `CI_WORKFLOW`、`CI_WORKFLOW_ID` | 工作流名称和 ID | | `CI_START_CONDITION` | `manual`、`manual_rebuild`、`push`、`pr_open`、`pr_update` 或 `schedule` | | `CI_PRODUCT_PLATFORM` | `iOS`、`macOS`、`tvOS` 或 `watchOS` | | `CI_XCODEBUILD_ACTION` | `analyze`、`archive`、`build`、`build-for-testing` 或 `test-without-building` | | `CI_XCODEBUILD_EXIT_CODE` | `xcodebuild` 执行后的退出码 | | `CI_PRIMARY_REPOSITORY_PATH`、`CI_WORKSPACE_PATH` | 源代码和工作区的位置,例如 `/Volumes/workspace/repository` | | `CI_BUNDLE_ID`、`CI_TEAM_ID`、`CI_XCODE_SCHEME`、`CI_DERIVED_DATA_PATH` | 顾名思义 | 另外一些变量取决于构建是怎么开始的、在跑哪个操作:`CI_BRANCH`、`CI_TAG`、`CI_GIT_REF`;`CI_PULL_REQUEST_NUMBER` 等 `CI_PULL_REQUEST_*`;测试相关的 `CI_RESULT_BUNDLE_PATH`、`CI_TEST_PLAN` 等;归档相关的 `CI_ARCHIVE_PATH` 和各种 `CI_*_SIGNED_APP_PATH`。在测试操作中,Xcode Cloud 会给变量加上 `TEST_RUNNER_` 前缀再交给测试进程。构建机器还设置了 `HTTP_PROXY` 和 `HTTPS_PROXY`。 ## 计算时数和方案 2026 年 11 月 1 日读取的 Apple Xcode Cloud 页面: | 方案 | 每月计算时数 | 价格 | |---|---|---| | Apple Developer Program 会员自带 | 25 | 已包含 | | 付费 | 100 | 每月 49.99 美元 | | 付费 | 250 | 每月 99.99 美元 | | 付费 | 1,000 | 每月 399.99 美元 | | 付费 | 10,000 | 每月 3,999.99 美元 | - **怎么算。** Apple 的定义:一个计算时数是在云端执行具体任务(比如构建 App 或运行测试)所用的一小时,"5 个各 12 分钟的测试等于一个计算时数"。因为操作是并行执行的,一次构建花的时间和报告的用量并不相同。 - **没用完的时数**"不会结转到下个月"。 - **谁来购买。** 只有账户持有人可以买,在 Apple Developer App 的 Account 标签页里,而且要先配置好工作流。方案以美元计价,部分地区以当地货币计价。 - **升级**会开始新的计费周期:"配额归零,计算时数按新方案重新给"。**降级**在本周期结束前仍用当前方案。**取消**付费方案后,本周期剩余时数还能用,之后回到每月 25 小时。 - 取消付费方案后再**退出** Xcode Cloud,你的产品、工作流和构建都将无法访问,且"无法恢复"。 - **查看用量**:App Store Connect → 用户和访问 → Xcode Cloud 标签页(团队),或某个 App 的 Xcode Cloud 标签页(单个 App),有趋势图,可导出 `.csv`;Apple Developer App 的 Account 标签页里也能看。 Apple 的页面没有说明月度时数用完时正在跑的构建会怎样,也没有列出各方案能同时跑几个构建。 ## 日志和产物在哪里 - **Xcode**:报告导航器 → Cloud 按钮 → 选中一个构建。在报告大纲里展开某个操作,点 **Logs**;点 **Artifacts** 可下载构建报告等文件。 - **App Store Connect**:进入 App → **Xcode Cloud** 标签页 → Builds,在侧栏展开操作,点 **Logs**。 - **保存了什么**:构建信息、App 二进制、符号信息、测试结果等。 - **保存多久**:"Xcode Cloud 在构建完成后最多保存产物 30 天。"Apple 建议每个上架的版本都下载并存档产物,因为以后看崩溃报告需要符号信息。 - **删除工作流**会把它的构建记录和产物一起删掉。想保留就停用工作流,不要删除。 - `ci_scripts` 的输出会出现在构建日志里。 ## 小团队的起步配置 按 Apple 自己的建议: 1. **检查**:Branch Changes 加 Pull Request Changes,一个测试操作,选一两个模拟器,开着 Auto-cancel,再加文件过滤,改文档不触发构建。 2. **测试员**:`main` 分支按排程(每周或每晚),归档选 TestFlight (Internal Testing Only),TestFlight 后续操作发给内部群组,再用 Notify 发 Slack 或邮件。 3. **发布**:Tag Changes,标签以 `v` 开头,打开 Clean,归档选 TestFlight and App Store,30 天内下载产物。 第一个月留意用量页面,确认 25 小时够不够,再决定要不要买方案。 ## 常见问题 ### 能只在 App Store Connect 里配置 Xcode Cloud 吗? 不能。Apple 说第一次配置必须在 Xcode 里完成;第一次构建之后,两边都能管理工作流。 ### Xcode Cloud 会帮我把构建传到 TestFlight 吗? 会,需要归档操作加 TestFlight 后续操作。Apple 原话:"Xcode Cloud 会归档构建并替你上传到 App Store Connect。"外部测试员仍需要 TestFlight App 审核,归档要选 TestFlight and App Store。 ### 怎样让某次推送不触发构建? 在最新推送的提交标题或说明里写 `[ci skip]`。 ### 没用完的计算时数能留到下个月吗? 不能。Apple 说没用完的计算时数"不会结转到下个月"。 ### 产物能下载多久? 构建完成后最多 30 天。 ## 参考资料 均于 2026 年 11 月 1 日读取。 - [Xcode Cloud](https://developer.apple.com/xcode-cloud/),Apple Developer - [Get started with Xcode Cloud](https://developer.apple.com/xcode-cloud/get-started/),Apple Developer - [Xcode Cloud](https://developer.apple.com/documentation/xcode/xcode-cloud),Apple 开发者文档 - [Setting up your project to use Xcode Cloud](https://developer.apple.com/documentation/xcode/setting-up-your-project-to-use-xcode-cloud),Apple 开发者文档 - [Configuring your first Xcode Cloud workflow](https://developer.apple.com/documentation/xcode/configuring-your-first-xcode-cloud-workflow),Apple 开发者文档 - [Xcode Cloud workflow reference](https://developer.apple.com/documentation/xcode/xcode-cloud-workflow-reference),Apple 开发者文档 - [Configuring start conditions](https://developer.apple.com/documentation/xcode/configuring-start-conditions),Apple 开发者文档 - [Configuring your Xcode Cloud workflow's actions](https://developer.apple.com/documentation/xcode/configuring-your-xcode-cloud-workflow-s-actions),Apple 开发者文档 - [Writing custom build scripts](https://developer.apple.com/documentation/xcode/writing-custom-build-scripts),Apple 开发者文档 - [Environment variable reference](https://developer.apple.com/documentation/xcode/environment-variable-reference),Apple 开发者文档 - [Sharing environment variables across Xcode Cloud workflows](https://developer.apple.com/documentation/xcode/sharing-environment-variables-across-xcode-cloud-workflows),Apple 开发者文档 - [Connecting Xcode Cloud to Slack](https://developer.apple.com/documentation/xcode/connecting-xcode-cloud-to-slack),Apple 开发者文档 - [Distributing your Xcode Cloud builds through TestFlight](https://developer.apple.com/documentation/xcode/distributing-your-xcode-cloud-builds-through-testflight),Apple 开发者文档 - [Developing a workflow strategy for Xcode Cloud](https://developer.apple.com/documentation/xcode/developing-a-workflow-strategy-for-xcode-cloud),Apple 开发者文档 - [Reviewing Xcode Cloud usage data](https://developer.apple.com/documentation/xcode/reviewing-xcode-cloud-usage-data),Apple 开发者文档 *Apple 的方案、价格和 Xcode Cloud 设置会变化,具体以上面这些页面的当前内容为准。*