自定义高级 Xcode Cloud 工作流
Customize your advanced Xcode Cloud workflows
2021年6月8日
一句话判断
如果你的 Xcode Cloud workflow 超出了「构建-测试-分发」的标准模板,这个 Session 教你用脚本和环境变量填平那些边角需求。
这场 Session 讲了什么
前两个 Xcode Cloud Session 覆盖了基本概念和 workflow 配置,这个 Session 聚焦在高级自定义场景。核心是 ci_scripts 目录——你在项目根目录下创建这个文件夹,放入特定的 shell 脚本,Xcode Cloud 会在构建生命周期的不同节点自动调用它们。
关键脚本有两个:ci_post_clone.sh(代码克隆后执行)和 ci_post_xcodebuild.sh(构建完成后执行)。Session 展示了几个典型用例:在克隆后安装 CocoaPods 或 SPM 的本地工具、运行代码风格检查、在构建后上传 dSYM 到第三方服务、发送通知到 Slack。Xcode Cloud 注入了大量环境变量(以 CI_ 开头),你可以在脚本中读取当前分支、scheme 名称、构建号等信息来驱动条件逻辑。
Session 还提到了一个容易踩的坑:脚本必须有可执行权限(chmod +x),否则 Xcode Cloud 会跳过它。另外,脚本执行失败会导致整个构建失败,所以如果你某个步骤是非关键的(比如代码风格检查),需要自己处理错误退出。
值得深挖的点
ci_post_clone.sh 的时序陷阱。 这个脚本执行时机是「代码已克隆,但尚未开始构建」。如果你在这里安装依赖(比如 pod install),要确保生成的 .xcworkspace 文件是 workflow 中 scheme 能找到的。一个常见的坑是:你的 workflow 配置的是 .xcodeproj,但 pod install 之后需要用 .xcworkspace 才能编译。解决办法是在脚本里直接修改 workspace 文件,或者在 workflow 设置中选择正确的 workspace。
环境变量的安全使用。 Xcode Cloud 允许你在 workflow 设置中定义自定义环境变量,可以标记为「敏感」(Secure),这样在构建日志中会被掩码显示。这很适合存放 API Key、Slack Webhook URL 等。但要注意,这些变量会以明文形式注入到 shell 脚本的环境中,所以不要在 echo 或日志中意外泄露。
代码片段
#!/bin/bash
# ci_scripts/ci_post_clone.sh
# 安装依赖并准备构建环境
set -euo pipefail
echo "=== 开始准备构建环境 ==="
echo "仓库: $CI_REPOSITORY_URL"
echo "分支: $CI_COMMIT_BRANCH"
echo "Scheme: $CI_XCODEBUILD_SCHEME"
# 安装 CocoaPods
if [ -f "Podfile" ]; then
echo "检测到 Podfile,开始安装依赖..."
gem install cocoapods --no-document --quiet
pod install --repo-update
echo "CocoaPods 依赖安装完成"
fi
# 安装 SwiftGen 等代码生成工具
if [ -f "swiftgen.yml" ]; then
brew install swiftgen
swiftgen
fi
#!/bin/bash
# ci_scripts/ci_post_xcodebuild.sh
# 构建完成后的后处理
set -euo pipefail
if [ "$CI_RESULT" = "success" ]; then
echo "构建成功!版本号: $CI_BUILD_NUMBER"
# 上传 dSYM 到 Firebase Crashlytics
if [ -n "${FABRIC_API_KEY:-}" ]; then
echo "上传符号文件..."
# 找到 dSYM 文件并上传
find "$CI_DERIVED_DATA_PATH" -name "*.dSYM" -exec \
./Pods/Fabric/upload-symbols -a "$FABRIC_API_KEY" {} \;
fi
# 发送构建成功通知到 Slack
if [ -n "${SLACK_WEBHOOK:-}" ]; then
curl -s -X POST "$SLACK_WEBHOOK" \
-H 'Content-Type: application/json' \
-d "{\"text\": \"✅ 构建 #$CI_BUILD_NUMBER 成功 ($CI_COMMIT_BRANCH)\"}"
fi
fi
#!/bin/bash
# 示例:在脚本中读取 Xcode Cloud 的环境变量
# 常用变量列表:
# CI_BUILD_NUMBER - 构建编号
# CI_COMMIT_BRANCH - 当前分支
# CI_COMMIT_SHA - 提交哈希
# CI_PRODUCT - 产品名称
# CI_SCHEME - scheme 名称
# CI_XCODE_VERSION - Xcode 版本
# CI_PLATFORM - 目标平台
# CI_ARCHIVE_PATH - 归档文件路径
# CI_DERIVED_DATA_PATH - DerivedData 路径
# CI_RESULT - 构建结果(success/failure)
# CI_WORKFLOW - workflow 名称
最佳实践
- 把非关键步骤的错误用
|| true吞掉,避免因为 lint 警告或通知发送失败导致整个构建标红 - 在脚本开头加
set -euo pipefail可以让脚本遇到未定义变量或管道错误时立刻失败,避免静默出错 - 敏感信息(API Key、token)始终通过 Xcode Cloud 的 Secure Environment Variables 配置,不要写在代码里
- 测试脚本时可以先在本地模拟 Xcode Cloud 的环境变量,手动设置
CI_*变量后执行脚本验证
还有什么值得关注
- Xcode Cloud 的 macOS 环境预装了 Homebrew 和常用工具,不需要每次在脚本里从头安装
- 脚本的超时时间有限制,如果你的依赖安装特别耗时,考虑用 SPM 替代 CocoaPods 以减少构建时间
- 构建日志中会显示脚本的 stdout 和 stderr 输出,利用
echo做好日志标记方便排查问题