使用 cktool 和声明式 Schema 自动化 CloudKit 测试
Automate CloudKit tests with cktool and declarative schema
2021年6月10日
一句话判断
cktool 让 CloudKit 的 Schema 管理终于可以进入 CI/CD 管道了 —— 声明式 JSON 配置 + 命令行工具 = Schema 变更可审计、可回滚、可自动化,这是 CloudKit 从”玩具级后端”迈向工程化工具的关键一步。
这场 Session 讲了什么
Session 深入讲解了 cktool 命令行工具和声明式 Schema 管理系统。cktool 是苹果在 macOS 12 中引入的 CloudKit 管理命令行工具,支持 Schema 操作、数据查询、环境管理等。
核心能力:
- Schema 导出/导入:
cktool schema export把当前 Schema 导出为 JSON 文件,cktool schema apply从 JSON 文件应用 Schema 变更。 - Schema 推送:
cktool schema promote把开发环境的 Schema 推送到生产环境。 - 数据操作:
cktool record query查询记录、cktool record delete删除记录。 - 环境管理:查看容器列表、切换开发/生产环境。
声明式 Schema 的工作流:在 JSON 文件中定义 Record Type、Field、Index -> 用 cktool schema apply 应用到开发环境 -> 测试验证 -> cktool schema promote 推送到生产环境。整个过程可以集成到 CI/CD 管道。
值得深挖的点
Schema 变更的安全机制。CloudKit 的 Schema 变更有严格的安全限制:只能在开发环境中添加/修改 Field 和 Index,生产环境只能添加(不能删除或修改已有字段)。cktool schema apply 在执行前会做 diff,只应用变更的部分。如果变更涉及删除字段(开发环境),会要求二次确认。
cktool 的认证方式。cktool 使用 Apple ID 的 API Token 认证,不是 iCloud 登录。你需要在 App Store Connect 中生成一个 API Key(Issuer ID + Key ID + Private Key),然后用 cktool auth 登录。这个 token 可以设过期时间,适合 CI 环境。注意:token 权限继承生成它的 Apple ID 的权限,建议用一个专用的开发者账号生成 CI token。
代码片段
完整的 CI Schema 管道:
# 步骤 1:认证
cktool auth \
--api-token "$(cat /secure/ck-api-token.json)"
# 步骤 2:导出当前开发环境 Schema 作为基线
cktool schema export \
--container iCloud_com.myteam.myapp \
--environment development \
> schema_baseline.json
# 步骤 3:应用新 Schema(从代码仓库中的声明文件)
cktool schema apply \
--container iCloud_com.myteam.myapp \
--environment development \
--input schema/schema_v2.json \
--force # 跳过交互确认(CI 模式)
# 步骤 4:运行集成测试(验证新 Schema 是否正常工作)
xcodebuild test \
-scheme MyAppIntegrationTests \
-destination 'platform=iOS,name=iPhone 13'
# 步骤 5:测试通过后,推送 Schema 到生产环境
if [ $? -eq 0 ]; then
cktool schema promote \
--container iCloud_com.myteam.myapp
echo "Schema 已推送到生产环境"
fi
声明式 Schema JSON 示例:
{
"recordTypes": {
"UserProfile": {
"fields": {
"nickname": { "type": "STRING" },
"avatarURL": { "type": "STRING" },
"level": { "type": "INT64" },
"lastActiveDate": { "type": "DATE/TIME" },
"isPremium": { "type": "INT64" }
},
"indexes": {
"nicknameIndex": {
"field": "nickname",
"type": "VALUE"
},
"levelSortIndex": {
"field": "level",
"type": "SORTABLE"
},
"lastActiveQueryIndex": {
"field": "lastActiveDate",
"type": "QUERYABLE"
}
}
}
},
"zones": {
"_defaultZone": {
"capabilities": []
}
}
}
查询和清理测试数据:
# 查询开发环境中的测试记录
cktool record query \
--container iCloud_com.myteam.myapp \
--environment development \
--record-type UserProfile \
--filter 'level < 5' \
--limit 100
# 清理测试数据(仅开发环境)
cktool record delete \
--container iCloud_com.myteam.myapp \
--environment development \
--record-name "test_user_001" \
--force
# 批量清理(结合 jq 处理查询结果)
cktool record query \
--container iCloud_com.myteam.myapp \
--environment development \
--record-type UserProfile \
--filter 'nickname BEGINS_WITH "test_"' \
| jq -r '.records[].recordName' \
| xargs -I {} cktool record delete \
--container iCloud_com.myteam.myapp \
--environment development \
--record-name {}
最佳实践
- Schema JSON 文件纳入 Git 版本控制。每次 Schema 变更都是一个 commit,PR 中可以 code review 数据模型变更。
- CI 中先
schema apply到开发环境,跑完测试后再schema promote。不要跳过测试直接推生产,CloudKit Schema 变更不可逆。 - 用专用 Apple ID 生成 CI token。不要用个人账号的 token,离职时无法收回权限。专用账号只给 CloudKit 相关权限,遵循最小权限原则。
还有什么值得关注
cktool目前只在 macOS 上可用,不支持 Linux(CI 可以用 macOS runner)。- Schema 的 JSON 格式和 CloudKit Console 中导出的格式一致,可以互相转换。
cktool支持输出 JSON 格式的结果,方便在脚本中用jq处理。